From: Chandler Carruth Date: Wed, 30 Jun 2010 02:06:16 +0000 (+0000) Subject: Revert r107235, it had a silly typo in it, and fixing the typo breaks something X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ec29b352b7ab2a2e99f7a9b78ce27c5e2a08d0e1;p=clang Revert r107235, it had a silly typo in it, and fixing the typo breaks something else. Get the build bots happy while I debug. Very sorry for the delay fixing this... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107239 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1757c84551..29455087ae 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1753,64 +1753,38 @@ struct BaseAndFieldInfo { }; } -static void RecordFieldInitializer(BaseAndFieldInfo &Info, - FieldDecl *Top, FieldDecl *Field, - CXXBaseOrMemberInitializer *Init) { - // If the member doesn't need to be initialized, Init will still be null. - if (!Init) - return; - - Info.AllToInit.push_back(Init); - if (Field != Top) { - Init->setMember(Top); - Init->setAnonUnionMember(Field); - } -} - static bool CollectFieldInitializer(BaseAndFieldInfo &Info, FieldDecl *Top, FieldDecl *Field) { - // Overwhelmingly common case: we have a direct initializer for this field. + // Overwhelmingly common case: we have a direct initializer for this field. if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(Field)) { - RecordFieldInitializer(Info, Top, Field, Init); + Info.AllToInit.push_back(Init); + + if (Field != Top) { + Init->setMember(Top); + Init->setAnonUnionMember(Field); + } return false; } if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) { const RecordType *FieldClassType = Field->getType()->getAs(); assert(FieldClassType && "anonymous struct/union without record type"); - CXXRecordDecl *FieldClassDecl - = cast(FieldClassType->getDecl()); - // Even though union members never have non-trivial default - // constructions in C++03, we still build member initializers for aggregate - // record types which can be union members, and C++0x allows non-trivial - // default constructors for union members, so we ensure that only one - // member is initialized for these. - if (FieldClassDecl->isUnion()) { - // First check for an explicit initializer for one field. - for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), - EA = FieldClassDecl->field_end(); FA != EA; FA++) { - if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(*FA)) { - RecordFieldInitializer(Info, Top, *FA, Init); - break; - } - } + // Walk through the members, tying in any initializers for fields + // we find. The earlier semantic checks should prevent redundant + // initialization of union members, given the requirement that + // union members never have non-trivial default constructors. - // Fallthrough and construct a default initializer for the union as - // a whole, which can call its default constructor if such a thing exists - // (C++0x perhaps). FIXME: It's not clear that this is the correct - // behavior going forward with C++0x, when anonymous unions there are - // finalized, we should revisit this. - } else { - // For structs, we simply descend through to initialize all members where - // necessary. - for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), - EA = FieldClassDecl->field_end(); FA != EA; FA++) { - if (CollectFieldInitializer(Info, Top, *FA)) - return true; - } - } + // TODO: in C++0x, it might be legal to have union members with + // non-trivial default constructors in unions. Revise this + // implementation then with the appropriate semantics. + CXXRecordDecl *FieldClassDecl + = cast(FieldClassType->getDecl()); + for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), + EA = FieldClassDecl->field_end(); FA != EA; FA++) + if (CollectFieldInitializer(Info, Top, *FA)) + return true; } // Don't try to build an implicit initializer if there were semantic @@ -1822,8 +1796,15 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, CXXBaseOrMemberInitializer *Init = 0; if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init)) return true; + + // If the member doesn't need to be initialized, Init will still be null. + if (!Init) return false; - RecordFieldInitializer(Info, Top, Field, Init); + Info.AllToInit.push_back(Init); + if (Top != Field) { + Init->setMember(Top); + Init->setAnonUnionMember(Field); + } return false; } diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index bf4b289a90..8e9e133d94 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -204,20 +204,3 @@ C f(C c) { } } - -// Don't build implicit initializers for anonymous union fields when we already -// have an explicit initializer for another field in the union. -namespace PR7402 { - struct S { - union { - void* ptr_; - struct { int i_; }; - }; - - template S(T) : ptr_(0) { } - }; - - void f() { - MyStruct s(3); - } -}