aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaDecl.cpp35
-rw-r--r--lib/Sema/SemaDeclCXX.cpp5
-rw-r--r--lib/Sema/SemaExpr.cpp12
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())