summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-03-29 19:00:10 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-03-29 19:00:10 +0000
commitdf8dc86148a209792dfcbe7b05a00294ed3bcff4 (patch)
tree051219d58ee3aaa783227b5bacdb68bccbcc1226 /lib/Sema/SemaDeclCXX.cpp
parent882784d42e723dabacc821f9ce71bd79a899e2b9 (diff)
Refactor special member function deletion. No functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153673 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp72
1 files changed, 9 insertions, 63 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 703af2b6ab..c59e97af72 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4416,7 +4416,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
}
// C++11 [class.ctor]p5:
- // -- any direct or virtual base class [...] has class type M [...] and
+ // -- any direct or virtual base class, or non-static data member with no
+ // brace-or-equal-initializer, has class type M (or array thereof) and
// either M has no default constructor or overload resolution as applied
// to M's default constructor results in an ambiguity or in a function
// that is deleted or inaccessible
@@ -4425,8 +4426,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
// overload resolution, as applied to B's corresponding special member,
// results in an ambiguity or a function that is deleted or inaccessible
// from the defaulted special member
- // FIXME: in-class initializers should be handled here
- if (CSM != Sema::CXXDestructor) {
+ if (CSM != Sema::CXXDestructor &&
+ !(CSM == Sema::CXXDefaultConstructor &&
+ Field && Field->hasInClassInitializer())) {
Sema::SpecialMemberOverloadResult *SMOR = lookupIn(Class);
if (!SMOR->hasSuccess())
return true;
@@ -4521,6 +4523,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
FieldRecord->isAnonymousStructOrUnion()) {
bool AllVariantFieldsAreConst = true;
+ // FIXME: Handle anonymous unions declared within anonymous unions.
for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(),
UE = FieldRecord->field_end();
UI != UE; ++UI) {
@@ -4540,70 +4543,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
FieldRecord->field_begin() != FieldRecord->field_end())
return true;
- // Don't try to initialize the anonymous union
+ // Don't check the implicit member of the anonymous union type.
// This is technically non-conformant, but sanity demands it.
return false;
}
- // When checking a constructor, the field's destructor must be accessible
- // and not deleted.
- if (IsConstructor) {
- CXXDestructorDecl *FieldDtor = S.LookupDestructor(FieldRecord);
- if (FieldDtor->isDeleted())
- return true;
- if (S.CheckDestructorAccess(Loc, FieldDtor, S.PDiag()) !=
- Sema::AR_accessible)
- return true;
- }
-
- // Check that the corresponding member of the field is accessible,
- // unique, and non-deleted. We don't do this if it has an explicit
- // initialization when default-constructing.
- if (!(CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer())) {
- Sema::SpecialMemberOverloadResult *SMOR = lookupIn(FieldRecord);
- if (!SMOR->hasSuccess())
- return true;
-
- CXXMethodDecl *FieldMember = SMOR->getMethod();
-
- // We need the corresponding member of a union to be trivial so that
- // we can safely process all members simultaneously.
- if (inUnion() && !FieldMember->isTrivial())
- return true;
-
- if (IsConstructor) {
- CXXConstructorDecl *FieldCtor = cast<CXXConstructorDecl>(FieldMember);
- if (S.CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(),
- S.PDiag()) != Sema::AR_accessible)
- return true;
-
- // For a move operation, the corresponding operation must actually
- // be a move operation (and not a copy selected by overload
- // resolution) unless we are working on a trivially copyable class.
- if (IsMove && !FieldCtor->isMoveConstructor() &&
- !FieldRecord->isTriviallyCopyable())
- return true;
- } else if (CSM == Sema::CXXDestructor) {
- CXXDestructorDecl *FieldDtor = S.LookupDestructor(FieldRecord);
- if (FieldDtor->isDeleted())
- return true;
- if (S.CheckDestructorAccess(Loc, FieldDtor, S.PDiag()) !=
- Sema::AR_accessible)
- return true;
- } else {
- assert(IsAssignment && "unexpected kind of special member");
- if (S.CheckDirectMemberAccess(Loc, FieldMember, S.PDiag())
- != Sema::AR_accessible)
- return true;
-
- // -- for the move assignment operator, a non-static data member with a
- // type that does not have a move assignment operator and is not
- // trivially copyable.
- if (IsMove && !FieldMember->isMoveAssignmentOperator() &&
- !FieldRecord->isTriviallyCopyable())
- return true;
- }
- }
+ if (shouldDeleteForClassSubobject(FieldRecord, FD))
+ return true;
} else if (IsAssignment && FieldType.isConstQualified()) {
// C++11 [class.copy]p23:
// -- a non-static data member of const non-class type (or array thereof)