diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-05-07 03:19:20 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-05-07 03:19:20 +0000 |
| commit | 99005e65cd99854ef6844146f8110fc08dba6fe3 (patch) | |
| tree | 9cba3f4c76910141c3c6bf415657df46c2c9919f /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | badcd986bb569b6643a53d9d9d77377673981f2c (diff) | |
| download | bcm5719-llvm-99005e65cd99854ef6844146f8110fc08dba6fe3.tar.gz bcm5719-llvm-99005e65cd99854ef6844146f8110fc08dba6fe3.zip | |
C++1y: an assignment operator is implicitly 'constexpr' if it would only call 'constexpr' assignment operators for a literal class type.
llvm-svn: 181284
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e6a131a0761..a4e65ee7656 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4278,6 +4278,7 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor [...] + bool Ctor = true; switch (CSM) { case Sema::CXXDefaultConstructor: // Since default constructor lookup is essentially trivial (and cannot @@ -4295,6 +4296,12 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, case Sema::CXXCopyAssignment: case Sema::CXXMoveAssignment: + if (!S.getLangOpts().CPlusPlus1y) + return false; + // In C++1y, we need to perform overload resolution. + Ctor = false; + break; + case Sema::CXXDestructor: case Sema::CXXInvalid: return false; @@ -4307,15 +4314,22 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // 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()) + if (Ctor && ClassDecl->isUnion()) return true; // -- the class shall not have any virtual base classes; - if (ClassDecl->getNumVBases()) + if (Ctor && ClassDecl->getNumVBases()) + return false; + + // C++1y [class.copy]p26: + // -- [the class] is a literal type, and + if (!Ctor && !ClassDecl->isLiteral()) return false; // -- every constructor involved in initializing [...] base class // sub-objects shall be a constexpr constructor; + // -- the assignment operator selected to copy/move each direct base + // class is a constexpr function, and for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), BEnd = ClassDecl->bases_end(); B != BEnd; ++B) { @@ -4331,6 +4345,9 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // [...] shall be a constexpr constructor; // -- every non-static data member and base class sub-object shall be // initialized + // -- for each non-stastic data member of X that is of class type (or array + // thereof), the assignment operator selected to copy/move that member is + // a constexpr function for (RecordDecl::field_iterator F = ClassDecl->field_begin(), FEnd = ClassDecl->field_end(); F != FEnd; ++F) { @@ -4461,7 +4478,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // A defaulted special member cannot have cv-qualifiers. if (Type->getTypeQuals()) { Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) - << (CSM == CXXMoveAssignment); + << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus1y; HadError = true; } } @@ -4506,13 +4523,16 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // would have been implicitly declared as constexpr, // Do not apply this rule to members of class templates, since core issue 1358 // makes such functions always instantiate to constexpr functions. For - // non-constructors, this is checked elsewhere. + // functions which cannot be constexpr (for non-constructors in C++11 and for + // destructors in C++1y), this is checked elsewhere. bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM, HasConstParam); - if (isa<CXXConstructorDecl>(MD) && MD->isConstexpr() && !Constexpr && + if ((getLangOpts().CPlusPlus1y ? !isa<CXXDestructorDecl>(MD) + : isa<CXXConstructorDecl>(MD)) && + MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; - // FIXME: Explain why the constructor can't be constexpr. + // FIXME: Explain why the special member can't be constexpr. HadError = true; } @@ -8736,21 +8756,24 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); - if (ClassDecl->implicitCopyAssignmentHasConstParam()) + bool Const = ClassDecl->implicitCopyAssignmentHasConstParam(); + if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); + bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, + CXXCopyAssignment, + Const); + // An implicitly-declared copy assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXMethodDecl *CopyAssignment - = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, - /*StorageClass=*/SC_None, - /*isInline=*/true, /*isConstexpr=*/false, - SourceLocation()); + CXXMethodDecl *CopyAssignment = + CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), + /*TInfo=*/ 0, /*StorageClass=*/ SC_None, + /*isInline=*/ true, Constexpr, SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); CopyAssignment->setImplicit(); @@ -8775,7 +8798,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) : ClassDecl->hasTrivialCopyAssignment()); - // C++0x [class.copy]p19: + // C++11 [class.copy]p19: // .... If the class definition does not explicitly declare a copy // assignment operator, there is no user-declared move constructor, and // there is no user-declared move assignment operator, a copy assignment @@ -9188,18 +9211,19 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { QualType RetType = Context.getLValueReferenceType(ArgType); ArgType = Context.getRValueReferenceType(ArgType); + bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, + CXXMoveAssignment, + false); + // An implicitly-declared move assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXMethodDecl *MoveAssignment - = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, - /*StorageClass=*/SC_None, - /*isInline=*/true, - /*isConstexpr=*/false, - SourceLocation()); + CXXMethodDecl *MoveAssignment = + CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), + /*TInfo=*/0, /*StorageClass=*/SC_None, + /*isInline=*/true, Constexpr, SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); MoveAssignment->setImplicit(); @@ -9732,7 +9756,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - // C++0x [class.copy]p11: + // C++11 [class.copy]p11: // An implicitly-declared copy/move constructor is an inline public // member of its class. CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( |

