diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-10 07:07:24 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-10 07:07:24 +0000 |
commit | d3861ce75a308c65b58c0159e2cee58aea2dff1c (patch) | |
tree | d0f7d334fee6c47ce05d686e6f38921c89dbeaf5 /lib/Sema | |
parent | 7756afa6273cf708b5e3fbd6a6478eb2cada27e2 (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')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 40 |
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; } } |