]> granicus.if.org Git - clang/commitdiff
Ensure that we delete default constructors in the right cases. Don't delete the
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 27 Feb 2012 06:07:25 +0000 (06:07 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 27 Feb 2012 06:07:25 +0000 (06:07 +0000)
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

lib/Sema/SemaDeclCXX.cpp
test/CXX/special/class.ctor/p5-0x.cpp

index 4f3035466e5138fa34adaa2ad0cfc4f7d41a3520..73df1c9457e30660b2c9cad92591ec78b58d6c6b 100644 (file)
@@ -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)
index b81755dcd33e62de1934fb4d89098e4e2be84755..6f434466746c2576f29d6039171c34d9ed42f866 100644 (file)
@@ -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