diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 35 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 |
3 files changed, 29 insertions, 23 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 72516fda80..cc19ce9959 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9735,13 +9735,18 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { // copy constructors. CXXSpecialMember member = CXXInvalid; - if (!RDecl->hasTrivialCopyConstructor()) + // We're required to check for any non-trivial constructors. Since the + // implicit default constructor is suppressed if there are any + // user-declared constructors, we just need to check that there is a + // trivial default constructor and a trivial copy constructor. (We don't + // worry about move constructors here, since this is a C++98 check.) + if (RDecl->hasNonTrivialCopyConstructor()) member = CXXCopyConstructor; else if (!RDecl->hasTrivialDefaultConstructor()) member = CXXDefaultConstructor; - else if (!RDecl->hasTrivialCopyAssignment()) + else if (RDecl->hasNonTrivialCopyAssignment()) member = CXXCopyAssignment; - else if (!RDecl->hasTrivialDestructor()) + else if (RDecl->hasNonTrivialDestructor()) member = CXXDestructor; if (member != CXXInvalid) { @@ -9789,6 +9794,8 @@ static bool diagnoseNonTrivialUserDeclaredCtor(Sema &S, QualType QT, /// DiagnoseNontrivial - Given that a class has a non-trivial /// special member, figure out why. +/// FIXME: These checks are not correct in C++11 mode. Currently, this is OK +/// since we only use this in C++11 for a -Wc++98-compat warning. void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { QualType QT(T, 0U); CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl()); @@ -9887,17 +9894,21 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { } } - bool (CXXRecordDecl::*hasTrivial)() const; + bool (CXXRecordDecl::*hasNonTrivial)() const; switch (member) { case CXXDefaultConstructor: - hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break; + hasNonTrivial = &CXXRecordDecl::hasNonTrivialDefaultConstructor; break; case CXXCopyConstructor: - hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break; + hasNonTrivial = &CXXRecordDecl::hasNonTrivialCopyConstructor; break; case CXXCopyAssignment: - hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break; + hasNonTrivial = &CXXRecordDecl::hasNonTrivialCopyAssignment; break; + case CXXMoveConstructor: + hasNonTrivial = &CXXRecordDecl::hasNonTrivialMoveConstructor; break; + case CXXMoveAssignment: + hasNonTrivial = &CXXRecordDecl::hasNonTrivialMoveAssignment; break; case CXXDestructor: - hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break; - default: + hasNonTrivial = &CXXRecordDecl::hasNonTrivialDestructor; break; + case CXXInvalid: llvm_unreachable("unexpected special member"); } @@ -9906,7 +9917,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { const RecordType *BaseRT = bi->getType()->getAs<RecordType>(); assert(BaseRT && "Don't know how to handle dependent bases"); CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl()); - if (!(BaseRecTy->*hasTrivial)()) { + if ((BaseRecTy->*hasNonTrivial)()) { SourceLocation BaseLoc = bi->getLocStart(); Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member; DiagnoseNontrivial(BaseRT, member); @@ -9922,7 +9933,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { if (const RecordType *EltRT = EltTy->getAs<RecordType>()) { CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl()); - if (!(EltRD->*hasTrivial)()) { + if ((EltRD->*hasNonTrivial)()) { SourceLocation FLoc = fi->getLocation(); Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member; DiagnoseNontrivial(EltRT, member); @@ -9945,8 +9956,6 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { } } } - - llvm_unreachable("found no explanation for non-trivial member"); } /// TranslateIvarVisibility - Translate visibility from a token ID to an diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a8ddc51f3f..e98f75ebe6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -8201,10 +8201,7 @@ hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) { if (BaseClass->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(BaseClass); - // If the class has both a trivial move assignment and a non-trivial move - // assignment, hasTrivialMoveAssignment() is false. - if (BaseClass->hasDeclaredMoveAssignment() && - !BaseClass->hasTrivialMoveAssignment()) + if (BaseClass->hasNonTrivialMoveAssignment()) return true; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index e419ba5a3f..840f04f0da 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -635,16 +635,16 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { if (Ty.isCXX98PODType(Context)) return VAK_Valid; - // C++0x [expr.call]p7: - // Passing a potentially-evaluated argument of class type (Clause 9) + // C++11 [expr.call]p7: + // Passing a potentially-evaluated argument of class type (Clause 9) // having a non-trivial copy constructor, a non-trivial move constructor, - // or a non-trivial destructor, with no corresponding parameter, + // or a non-trivial destructor, with no corresponding parameter, // is conditionally-supported with implementation-defined semantics. if (getLangOpts().CPlusPlus0x && !Ty->isDependentType()) if (CXXRecordDecl *Record = Ty->getAsCXXRecordDecl()) - if (Record->hasTrivialCopyConstructor() && - Record->hasTrivialMoveConstructor() && - Record->hasTrivialDestructor()) + if (!Record->hasNonTrivialCopyConstructor() && + !Record->hasNonTrivialMoveConstructor() && + !Record->hasNonTrivialDestructor()) return VAK_ValidInCXX11; if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType()) |