diff options
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 75 | ||||
-rw-r--r-- | test/SemaCXX/constructor-initializer.cpp | 17 |
2 files changed, 28 insertions, 64 deletions
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<RecordType>(); assert(FieldClassType && "anonymous struct/union without record type"); - CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(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<CXXRecordDecl>(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 <typename T> S(T) : ptr_(0) { } - }; - - void f() { - MyStruct s(3); - } -} |