summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-27 06:07:25 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-27 06:07:25 +0000
commit79363f5e612c17cd05e1fa888632ee7860ced1ab (patch)
tree6db72405f1415645715e0aa39ef7637dcd7ecec9
parentd8e4daca4a44d25a9c09d51def9e3d485d4f302c (diff)
Ensure that we delete default constructors in the right cases. Don't delete the
default constructor of a union if it has a const member with no user-provided default constructor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151516 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclCXX.cpp20
-rw-r--r--test/CXX/special/class.ctor/p5-0x.cpp27
2 files changed, 25 insertions, 22 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4f3035466e..73df1c9457 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4485,6 +4485,15 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
if (inUnion() && !FieldType.isConstQualified())
AllFieldsAreConst = false;
+
+ // C++11 [class.ctor]p5: any non-variant non-static data member of
+ // const-qualified type (or array thereof) with no
+ // brace-or-equal-initializer does not have a user-provided default
+ // constructor.
+ if (!inUnion() && FieldType.isConstQualified() &&
+ !FD->hasInClassInitializer() &&
+ (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor()))
+ return true;
} else if (CSM == Sema::CXXCopyConstructor) {
// For a copy constructor, data members must not be of rvalue reference
// type.
@@ -4497,13 +4506,6 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
}
if (FieldRecord) {
- // For a default constructor, a const member must have a user-provided
- // default constructor or else be explicitly initialized.
- if (CSM == Sema::CXXDefaultConstructor && FieldType.isConstQualified() &&
- !FD->hasInClassInitializer() &&
- !FieldRecord->hasUserProvidedDefaultConstructor())
- return true;
-
// Some additional restrictions exist on the variant members.
if (!inUnion() && FieldRecord->isUnion() &&
FieldRecord->isAnonymousStructOrUnion()) {
@@ -4592,10 +4594,6 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
return true;
}
}
- } else if (CSM == Sema::CXXDefaultConstructor && !inUnion() &&
- FieldType.isConstQualified() && !FD->hasInClassInitializer()) {
- // We can't initialize a const member of non-class type to any value.
- 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)
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index b81755dcd3..6f43446674 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -35,10 +35,16 @@ class Deleted2a { // expected-note {{defined here}}
int &a;
};
Deleted2a d2a; // expected-error {{implicitly-deleted default constructor}}
+struct Deleted2b { // expected-note {{here}}
+ int &&b;
+};
+Deleted2b d2b; // expected-error {{deleted default constructor}}
class NotDeleted2a { int &a = n; };
NotDeleted2a nd2a;
class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
NotDeleted2b nd2b;
+class NotDeleted2c { int &&a = 0; };
+NotDeleted2c nd2c;
// - any non-variant non-static data member of const qualified type (or array
// thereof) with no brace-or-equal-initializer does not have a user-provided
@@ -59,27 +65,26 @@ class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); };
NotDeleted3c nd3c;
union NotDeleted3d { const int a; int b; };
NotDeleted3d nd3d;
-// FIXME: this class should not have a deleted default constructor.
-union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; // unexpected-note {{here}}
-NotDeleted3e nd3e; // unexpected-error {{implicitly-deleted default constructor}}
-// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2 is
-// non-trivial.
-union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; // unexpected-note {{here}}
-NotDeleted3f nd3f; // unexpected-error {{implicitly-deleted default constructor}}
+union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; };
+NotDeleted3e nd3e;
+union NotDeleted3f { const DefaultedDefCtor2 a; int b; };
+NotDeleted3f nd3f;
+struct NotDeleted3g { union { const int a; int b; }; };
+NotDeleted3g nd3g;
// - X is a union and all of its variant members are of const-qualified type (or
// array thereof),
union Deleted4a { const int a; const int b; const UserProvidedDefCtor c; }; // expected-note {{here}}
Deleted4a d4a; // expected-error {{implicitly-deleted default constructor}}
-union Deleted4b { const int a; int b; };
-Deleted4b d4b;
+union NotDeleted4a { const int a; int b; };
+NotDeleted4a nd4a;
// - X is a non-union class and all members of any anonymous union member are of
// const-qualified type (or array thereof),
struct Deleted5a { union { const int a; }; union { int b; }; }; // expected-note {{here}}
Deleted5a d5a; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted5b { union { const int a; int b; }; union { const int c; int d; }; };
-Deleted5b d5b;
+struct NotDeleted5a { union { const int a; int b; }; union { const int c; int d; }; };
+NotDeleted5a nd5a;
// - 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