From: Douglas Gregor Date: Fri, 24 Feb 2012 21:25:53 +0000 (+0000) Subject: C++11 [class.ctor]p5 says that X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=221c27f0d34c5938d84bbb8fafe1c3e3f1f87f2e;p=clang C++11 [class.ctor]p5 says that A defaulted default constructor for a class X is defined as deleted if [...] - X is a union and all of its variant members are of const-qualified type. A pedantic reading therefore says that union X { }; has a deleted default constructor, which is both silly and almost certainly unintended. Pretend as if this this read - X is a union with one or more variant members, and all of its variant members are of const-qualified type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151394 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6512929c2f..6d2f3b252b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4531,7 +4531,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { } // At least one member in each anonymous union must be non-const - if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst) + if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && + FieldRecord->field_begin() != FieldRecord->field_end()) return true; // Don't try to initialize the anonymous union @@ -4611,7 +4612,10 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { /// A defaulted default constructor for a class X is defined as deleted if /// X is a union and all of its variant members are of const-qualified type. bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { - return CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst; + // This is a silly definition, because it gives an empty union a deleted + // default constructor. Don't do that. + return CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst && + (MD->getParent()->field_begin() != MD->getParent()->field_end()); } /// Determine whether a defaulted special member function should be defined as diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index 0f0863515c..f6e5593d85 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -121,11 +121,11 @@ late_delete::late_delete() = default; // expected-error {{would delete it}} // See also rdar://problem/8125400. namespace empty { - static union {}; // expected-error {{implicitly-deleted default constructor}} expected-note {{here}} - static union { union {}; }; // expected-error {{implicitly-deleted default constructor}} expected-note {{here}} + static union {}; + static union { union {}; }; static union { struct {}; }; - static union { union { union {}; }; }; // expected-error {{implicitly-deleted default constructor}} expected-note {{here}} + static union { union { union {}; }; }; static union { union { struct {}; }; }; - static union { struct { union {}; }; }; // expected-error {{implicitly-deleted default constructor}} expected-note {{here}} + static union { struct { union {}; }; }; static union { struct { struct {}; }; }; }