aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-06-10 07:07:24 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-06-10 07:07:24 +0000
commitd3861ce75a308c65b58c0159e2cee58aea2dff1c (patch)
treed0f7d334fee6c47ce05d686e6f38921c89dbeaf5 /lib/Sema/SemaDeclCXX.cpp
parent7756afa6273cf708b5e3fbd6a6478eb2cada27e2 (diff)
Remove CXXRecordDecl flags which are unused after r158289.
We need an efficient mechanism to determine whether a defaulted default constructor is constexpr, in order to determine whether a class is a literal type, so keep the incrementally-built form on CXXRecordDecl. Remove the on-demand computation of same, so that we only have one method for determining whether a default constructor is constexpr. This doesn't affect correctness, since default constructor lookup is much simpler than selecting a constructor for copying or moving. We don't need a corresponding mechanism for defaulted copy or move constructors, since they can't affect whether a type is a literal type. Conversely, checking whether such functions are constexpr can require non-trivial effort, so we defer such checks until the copy or move constructor is required. Thus we now only compute whether a copy or move constructor is constexpr on demand, and only compute whether a default constructor is constexpr in advance. This is unfortunate, but seems like the best solution. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158290 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp40
1 files changed, 16 insertions, 24 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 648c0824d5..4bd1c3202c 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3897,8 +3897,17 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// In the definition of a constexpr constructor [...]
switch (CSM) {
case Sema::CXXDefaultConstructor:
+ // Since default constructor lookup is essentially trivial (and cannot
+ // involve, for instance, template instantiation), we compute whether a
+ // defaulted default constructor is constexpr directly within CXXRecordDecl.
+ //
+ // This is important for performance; we need to know whether the default
+ // constructor is constexpr to determine whether the type is a literal type.
+ return ClassDecl->defaultedDefaultConstructorIsConstexpr();
+
case Sema::CXXCopyConstructor:
case Sema::CXXMoveConstructor:
+ // For copy or move constructors, we need to perform overload resolution.
break;
case Sema::CXXCopyAssignment:
@@ -3911,11 +3920,12 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// -- if the class is a non-empty union, or for each non-empty anonymous
// union member of a non-union class, exactly one non-static data member
// shall be initialized; [DR1359]
+ //
+ // If we squint, this is guaranteed, since exactly one non-static data member
+ // will be initialized (if the constructor isn't deleted), we just don't know
+ // which one.
if (ClassDecl->isUnion())
- // FIXME: In the default constructor case, we should check that the
- // in-class initializer is actually a constant expression.
- return CSM != Sema::CXXDefaultConstructor ||
- ClassDecl->hasInClassInitializer();
+ return true;
// -- the class shall not have any virtual base classes;
if (ClassDecl->getNumVBases())
@@ -3943,29 +3953,11 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
F != FEnd; ++F) {
if (F->isInvalidDecl())
continue;
- if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) {
- // -- every assignment-expression that is an initializer-clause appearing
- // directly or indirectly within a brace-or-equal-initializer for a
- // non-static data member [...] shall be a constant expression;
- //
- // We consider this bullet to be a defect, since it results in this type
- // having a non-constexpr default constructor:
- // struct S {
- // int a = 0;
- // int b = a;
- // };
- // FIXME: We should still check that the constructor selected for this
- // initialization (if any) is constexpr.
- } else if (const RecordType *RecordTy =
- S.Context.getBaseElementType(F->getType())->
- getAs<RecordType>()) {
+ if (const RecordType *RecordTy =
+ S.Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, ConstArg))
return false;
- } else if (CSM == Sema::CXXDefaultConstructor) {
- // No in-class initializer, and not a class type. This member isn't going
- // to be initialized.
- return false;
}
}