From: Francois Pichet Date: Sat, 4 Dec 2010 09:14:42 +0000 (+0000) Subject: More anonymous struct/union redesign. This one deals with anonymous field used in... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66b;p=clang More anonymous struct/union redesign. This one deals with anonymous field used in a constructor initializer list: struct X { X() : au_i1(123) {} union { int au_i1; float au_f1; }; }; clang will now deal with au_i1 explicitly as an IndirectFieldDecl. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120900 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index e52f6add1e..79832a4118 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1108,9 +1108,9 @@ public: /// }; /// @endcode class CXXBaseOrMemberInitializer { - /// \brief Either the base class name (stored as a TypeSourceInfo*) or the - /// field being initialized. - llvm::PointerUnion BaseOrMember; + /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal + /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being initialized. + llvm::PointerUnion3 BaseOrMember; /// \brief The source location for the field name. SourceLocation MemberLocation; @@ -1118,26 +1118,6 @@ class CXXBaseOrMemberInitializer { /// \brief The argument used to initialize the base or member, which may /// end up constructing an object (when multiple arguments are involved). Stmt *Init; - - /// \brief Stores either the constructor to call to initialize this base or - /// member (a CXXConstructorDecl pointer), or stores the anonymous union of - /// which the initialized value is a member. - /// - /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's - /// anonymous union data member, this field holds the FieldDecl for the - /// member of the anonymous union being initialized. - /// @code - /// struct X { - /// X() : au_i1(123) {} - /// union { - /// int au_i1; - /// float au_f1; - /// }; - /// }; - /// @endcode - /// In above example, BaseOrMember holds the field decl. for anonymous union - /// and AnonUnionMember holds field decl for au_i1. - FieldDecl *AnonUnionMember; /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -1152,6 +1132,7 @@ class CXXBaseOrMemberInitializer { /// IsWritten - Whether or not the initializer is explicitly written /// in the sources. bool IsWritten : 1; + /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this /// number keeps track of the textual order of this initializer in the /// original sources, counting from 0; otherwise, if IsWritten is false, @@ -1184,6 +1165,14 @@ public: Expr *Init, SourceLocation R); + explicit + CXXBaseOrMemberInitializer(ASTContext &Context, + IndirectFieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R); + /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. static CXXBaseOrMemberInitializer *Create(ASTContext &Context, @@ -1203,6 +1192,14 @@ public: /// initializing a non-static data member. bool isMemberInitializer() const { return BaseOrMember.is(); } + bool isAnyMemberInitializer() const { + return isMemberInitializer() || isIndirectMemberInitializer(); + } + + bool isIndirectMemberInitializer() const { + return BaseOrMember.is(); + } + /// If this is a base class initializer, returns the type of the /// base class with location information. Otherwise, returns an NULL /// type location. @@ -1234,14 +1231,24 @@ public: else return 0; } + FieldDecl *getAnyMember() const { + if (isMemberInitializer()) + return BaseOrMember.get(); + else if (isIndirectMemberInitializer()) + return BaseOrMember.get()->getAnonField(); + else + return 0; + } - SourceLocation getMemberLocation() const { - return MemberLocation; + IndirectFieldDecl *getIndirectMember() const { + if (isIndirectMemberInitializer()) + return BaseOrMember.get(); + else + return 0; } - void setMember(FieldDecl *Member) { - assert(isMemberInitializer()); - BaseOrMember = Member; + SourceLocation getMemberLocation() const { + return MemberLocation; } /// \brief Determine the source location of the initializer. @@ -1273,15 +1280,7 @@ public: IsWritten = true; SourceOrderOrNumArrayIndices = static_cast(pos); } - - FieldDecl *getAnonUnionMember() const { - return AnonUnionMember; - } - void setAnonUnionMember(FieldDecl *anonMember) { - AnonUnionMember = anonMember; - } - SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index c72d124d0d..a8ab472427 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -217,6 +217,12 @@ public: return InitializedEntity(Member, Parent); } + /// \brief Create the initialization entity for a member subobject. + static InitializedEntity InitializeMember(IndirectFieldDecl *Member, + const InitializedEntity *Parent = 0) { + return InitializedEntity(Member->getAnonField(), Parent); + } + /// \brief Create the initialization entity for an array element. static InitializedEntity InitializeElement(ASTContext &Context, unsigned Index, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 65ba72e3b1..512e4fdba4 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2530,7 +2530,8 @@ public: Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); - MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args, + template + MemInitResult BuildMemberInitializer(T *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 9e9b5ab7ea..58cc50b97a 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1004,7 +1004,7 @@ CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0), + : BaseOrMember(TInfo), Init(Init), LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false), SourceOrderOrNumArrayIndices(0) { @@ -1015,7 +1015,17 @@ CXXBaseOrMemberInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), - AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsVirtual(false), + IsWritten(false), SourceOrderOrNumArrayIndices(0) +{ +} + +CXXBaseOrMemberInitializer:: +CXXBaseOrMemberInitializer(ASTContext &Context, + IndirectFieldDecl *Member, SourceLocation MemberLoc, + SourceLocation L, Expr *Init, SourceLocation R) + : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1027,7 +1037,7 @@ CXXBaseOrMemberInitializer(ASTContext &Context, VarDecl **Indices, unsigned NumIndices) : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), - AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) { VarDecl **MyIndices = reinterpret_cast (this + 1); @@ -1072,7 +1082,7 @@ const Type *CXXBaseOrMemberInitializer::getBaseClass() const { } SourceLocation CXXBaseOrMemberInitializer::getSourceLocation() const { - if (isMemberInitializer()) + if (isAnyMemberInitializer()) return getMemberLocation(); return getBaseClassLoc().getLocalSourceRange().getBegin(); diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 143238b4ae..dc1a9dc888 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -436,8 +436,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { CXXBaseOrMemberInitializer * BMInitializer = (*B); if (B != CDecl->init_begin()) Out << ", "; - if (BMInitializer->isMemberInitializer()) { - FieldDecl *FD = BMInitializer->getMember(); + if (BMInitializer->isAnyMemberInitializer()) { + FieldDecl *FD = BMInitializer->getAnyMember(); Out << FD; } else { Out << QualType(BMInitializer->getBaseClass(), diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index b382d9be58..9ff4e3897d 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -553,7 +553,7 @@ CFGBlock *CFGBuilder::addInitializer(CXXBaseOrMemberInitializer *I) { // after initialization finishes. Expr *Init = I->getInit(); if (Init) { - if (FieldDecl *FD = I->getMember()) + if (FieldDecl *FD = I->getAnyMember()) IsReference = FD->getType()->isReferenceType(); HasTemporaries = isa(Init); @@ -3093,7 +3093,7 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, CXXBaseOrMemberInitializer* I = IE; if (I->isBaseInitializer()) OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); - else OS << I->getMember()->getName(); + else OS << I->getAnyMember()->getName(); OS << "("; if (Expr* IE = I->getInit()) diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index e737eed8d1..c40c34118e 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -687,7 +687,7 @@ void GRExprEngine::ProcessInitializer(const CFGInitializer Init, ExplodedNode *Pred = builder.getBasePredecessor(); const LocationContext *LC = Pred->getLocationContext(); - if (BMI->isMemberInitializer()) { + if (BMI->isAnyMemberInitializer()) { ExplodedNodeSet Dst; // Evaluate the initializer. @@ -697,7 +697,7 @@ void GRExprEngine::ProcessInitializer(const CFGInitializer Init, ExplodedNode *Pred = *I; const GRState *state = Pred->getState(); - const FieldDecl *FD = BMI->getMember(); + const FieldDecl *FD = BMI->getAnyMember(); const RecordDecl *RD = FD->getParent(); const CXXThisRegion *ThisR = getCXXThisRegion(cast(RD), cast(LC)); diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index ae99e03c35..e2a3f27a1d 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -512,21 +512,21 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, CXXBaseOrMemberInitializer *MemberInit, const CXXConstructorDecl *Constructor, FunctionArgList &Args) { - assert(MemberInit->isMemberInitializer() && + assert(MemberInit->isAnyMemberInitializer() && "Must have member initializer!"); // non-static data member initializers. - FieldDecl *Field = MemberInit->getMember(); + FieldDecl *Field = MemberInit->getAnyMember(); QualType FieldType = CGF.getContext().getCanonicalType(Field->getType()); llvm::Value *ThisPtr = CGF.LoadCXXThis(); LValue LHS; // If we are initializing an anonymous union field, drill down to the field. - if (MemberInit->getAnonUnionMember()) { - Field = MemberInit->getAnonUnionMember(); - LHS = CGF.EmitLValueForAnonRecordField(ThisPtr, Field, 0); - FieldType = Field->getType(); + if (MemberInit->isIndirectMemberInitializer()) { + LHS = CGF.EmitLValueForAnonRecordField(ThisPtr, + MemberInit->getIndirectMember(), 0); + FieldType = MemberInit->getIndirectMember()->getAnonField()->getType(); } else { LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0); } diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 35ba2543ef..5697c5f1a4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1574,23 +1574,13 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value *BaseValue, /// that the base value is a pointer to the enclosing record, derive /// an lvalue for the ultimate field. LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue, - const FieldDecl *Field, + const IndirectFieldDecl *Field, unsigned CVRQualifiers) { - llvm::SmallVector Path; - Path.push_back(Field); - - while (Field->getParent()->isAnonymousStructOrUnion()) { - const ValueDecl *VD = Field->getParent()->getAnonymousStructOrUnionObject(); - if (!isa(VD)) break; - Field = cast(VD); - Path.push_back(Field); - } - - llvm::SmallVectorImpl::reverse_iterator - I = Path.rbegin(), E = Path.rend(); + IndirectFieldDecl::chain_iterator I = Field->chain_begin(), + IEnd = Field->chain_end(); while (true) { - LValue LV = EmitLValueForField(BaseValue, *I, CVRQualifiers); - if (++I == E) return LV; + LValue LV = EmitLValueForField(BaseValue, cast(*I), CVRQualifiers); + if (++I == IEnd) return LV; assert(LV.isSimple()); BaseValue = LV.getAddress(); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index a8acb2b72f..b7a6224000 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -432,7 +432,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, if (ctor) { for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) { CXXBaseOrMemberInitializer *IvarInit = IvarInitializers[I]; - FieldDecl *Field = IvarInit->getMember(); + FieldDecl *Field = IvarInit->getAnyMember(); QualType FieldType = Field->getType(); ObjCIvarDecl *Ivar = cast(Field); LValue LV = EmitLValueForIvar(TypeOfSelfObject(), @@ -448,7 +448,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, } else { // dtor for (size_t i = IvarInitializers.size(); i > 0; --i) { - FieldDecl *Field = IvarInitializers[i - 1]->getMember(); + FieldDecl *Field = IvarInitializers[i - 1]->getAnyMember(); QualType FieldType = Field->getType(); const ConstantArrayType *Array = getContext().getAsConstantArrayType(FieldType); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 9730b0d4a8..3799c6309c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1429,7 +1429,7 @@ public: llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); LValue EmitLValueForAnonRecordField(llvm::Value* Base, - const FieldDecl* Field, + const IndirectFieldDecl* Field, unsigned CVRQualifiers); LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field, unsigned CVRQualifiers); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3d458e76f1..6d40fb8d29 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3608,7 +3608,8 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, InitializedBases.insert( Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); else - InitializedFields.insert(cast(Initializers[I]->getMember())); + InitializedFields.insert(cast( + Initializers[I]->getAnyMember())); } // Add completions for base classes. @@ -3670,8 +3671,8 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, if (!InitializedFields.insert(cast(Field->getCanonicalDecl()))) { SawLastInitializer = NumInitializers > 0 && - Initializers[NumInitializers - 1]->isMemberInitializer() && - Initializers[NumInitializers - 1]->getMember() == *Field; + Initializers[NumInitializers - 1]->isAnyMemberInitializer() && + Initializers[NumInitializers - 1]->getAnyMember() == *Field; continue; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d30faccf24..49cc993096 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1070,16 +1070,16 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, if (Result.first != Result.second) { Member = dyn_cast(*Result.first); - // Handle anonymous union case. - if (!Member) + if (Member) + return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, + LParenLoc, RParenLoc); + // Handle anonymous union case. if (IndirectFieldDecl* IndirectField - = dyn_cast(*Result.first)) - Member = IndirectField->getAnonField(); + = dyn_cast(*Result.first)) + return BuildMemberInitializer(IndirectField, (Expr**)Args, + NumArgs, IdLoc, + LParenLoc, RParenLoc); } - - if (Member) - return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, - LParenLoc, RParenLoc); } // It didn't name a member, so see if it names a class. QualType BaseType; @@ -1195,8 +1195,10 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, /// uninitialized field was used an updates the SourceLocation parameter; false /// otherwise. static bool InitExprContainsUninitializedFields(const Stmt *S, - const FieldDecl *LhsField, + const ValueDecl *LhsField, SourceLocation *L) { + assert(isa(LhsField) || isa(LhsField)); + if (isa(S)) { // Do not descend into function calls or constructors, as the use // of an uninitialized field may be valid. One would have to inspect @@ -1257,11 +1259,15 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, return false; } +template MemInitResult -Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, +Sema::BuildMemberInitializer(T *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { + assert((isa(Member) || isa(Member)) || + "Member must be a FieldDecl or IndirectFieldDecl"); + if (Member->isInvalidDecl()) return true; @@ -1750,26 +1756,12 @@ 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. if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(Field)) { - RecordFieldInitializer(Info, Top, Field, Init); + Info.AllToInit.push_back(Init); return false; } @@ -1789,7 +1781,7 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, 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); + Info.AllToInit.push_back(Init); // Once we've initialized a field of an anonymous union, the union // field in the class is also initialized, so exit immediately. @@ -1826,7 +1818,9 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init)) return true; - RecordFieldInitializer(Info, Top, Field, Init); + if (Init) + Info.AllToInit.push_back(Init); + return false; } @@ -1866,7 +1860,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, if (Member->isBaseInitializer()) Info.AllBaseFields[Member->getBaseClass()->getAs()] = Member; else - Info.AllBaseFields[Member->getMember()] = Member; + Info.AllBaseFields[Member->getAnyMember()] = Member; } // Keep track of the direct virtual bases. @@ -1965,21 +1959,14 @@ static void *GetKeyForBase(ASTContext &Context, QualType BaseType) { } static void *GetKeyForMember(ASTContext &Context, - CXXBaseOrMemberInitializer *Member, - bool MemberMaybeAnon = false) { - if (!Member->isMemberInitializer()) + CXXBaseOrMemberInitializer *Member) { + if (!Member->isAnyMemberInitializer()) return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); // For fields injected into the class via declaration of an anonymous union, // use its anonymous union class declaration as the unique key. - FieldDecl *Field = Member->getMember(); - - // After SetBaseOrMemberInitializers call, Field is the anonymous union - // data member of the class. Data member used in the initializer list is - // in AnonUnionMember field. - if (MemberMaybeAnon && Field->isAnonymousStructOrUnion()) - Field = Member->getAnonUnionMember(); - + FieldDecl *Field = Member->getAnyMember(); + // If the field is a member of an anonymous struct or union, our key // is the anonymous record decl that's a direct child of the class. RecordDecl *RD = Field->getParent(); @@ -2042,7 +2029,7 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, CXXBaseOrMemberInitializer *PrevInit = 0; for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { CXXBaseOrMemberInitializer *Init = Inits[InitIndex]; - void *InitKey = GetKeyForMember(SemaRef.Context, Init, true); + void *InitKey = GetKeyForMember(SemaRef.Context, Init); // Scan forward to try to find this initializer in the idealized // initializers list. @@ -2058,13 +2045,13 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, SemaRef.Diag(PrevInit->getSourceLocation(), diag::warn_initializer_out_of_order); - if (PrevInit->isMemberInitializer()) - D << 0 << PrevInit->getMember()->getDeclName(); + if (PrevInit->isAnyMemberInitializer()) + D << 0 << PrevInit->getAnyMember()->getDeclName(); else D << 1 << PrevInit->getBaseClassInfo()->getType(); - if (Init->isMemberInitializer()) - D << 0 << Init->getMember()->getDeclName(); + if (Init->isAnyMemberInitializer()) + D << 0 << Init->getAnyMember()->getDeclName(); else D << 1 << Init->getBaseClassInfo()->getType(); @@ -2115,7 +2102,7 @@ typedef llvm::DenseMap RedundantUnionMap; bool CheckRedundantUnionInit(Sema &S, CXXBaseOrMemberInitializer *Init, RedundantUnionMap &Unions) { - FieldDecl *Field = Init->getMember(); + FieldDecl *Field = Init->getAnyMember(); RecordDecl *Parent = Field->getParent(); if (!Parent->isAnonymousStructOrUnion()) return false; @@ -2182,8 +2169,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, // Set the source order index. Init->setSourceOrder(i); - if (Init->isMemberInitializer()) { - FieldDecl *Field = Init->getMember(); + if (Init->isAnyMemberInitializer()) { + FieldDecl *Field = Init->getAnyMember(); if (CheckRedundantInit(*this, Init, Members[Field]) || CheckRedundantUnionInit(*this, Init, MemberUnions)) HadError = true; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index e299be9879..5b50d0d172 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2341,22 +2341,27 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Init->getRParenLoc(), New->getParent()); } else if (Init->isMemberInitializer()) { - FieldDecl *Member; - - // Is this an anonymous union? - if (FieldDecl *UnionInit = Init->getAnonUnionMember()) - Member = cast(FindInstantiatedDecl(Init->getMemberLocation(), - UnionInit, TemplateArgs)); - else - Member = cast(FindInstantiatedDecl(Init->getMemberLocation(), - Init->getMember(), - TemplateArgs)); + FieldDecl *Member = cast(FindInstantiatedDecl( + Init->getMemberLocation(), + Init->getMember(), + TemplateArgs)); NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), NewArgs.size(), Init->getSourceLocation(), Init->getLParenLoc(), Init->getRParenLoc()); + } else if (Init->isIndirectMemberInitializer()) { + IndirectFieldDecl *IndirectMember = + cast(FindInstantiatedDecl( + Init->getMemberLocation(), + Init->getIndirectMember(), TemplateArgs)); + + NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getSourceLocation(), + Init->getLParenLoc(), + Init->getRParenLoc()); } if (NewInit.isInvalid()) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 26d2ed250b..2d320e994d 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4270,18 +4270,21 @@ ASTReader::ReadCXXBaseOrMemberInitializers(PerFileData &F, TypeSourceInfo *BaseClassInfo = 0; bool IsBaseVirtual = false; FieldDecl *Member = 0; + IndirectFieldDecl *IndirectMember = 0; bool IsBaseInitializer = Record[Idx++]; if (IsBaseInitializer) { BaseClassInfo = GetTypeSourceInfo(F, Record, Idx); IsBaseVirtual = Record[Idx++]; } else { - Member = cast(GetDecl(Record[Idx++])); + bool IsIndirectMemberInitializer = Record[Idx++]; + if (IsIndirectMemberInitializer) + IndirectMember = cast(GetDecl(Record[Idx++])); + else + Member = cast(GetDecl(Record[Idx++])); } SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx); Expr *Init = ReadExpr(F); - FieldDecl *AnonUnionMember - = cast_or_null(GetDecl(Record[Idx++])); SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); bool IsWritten = Record[Idx++]; @@ -4302,8 +4305,14 @@ ASTReader::ReadCXXBaseOrMemberInitializers(PerFileData &F, IsBaseVirtual, LParenLoc, Init, RParenLoc); } else if (IsWritten) { - BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc, - LParenLoc, Init, RParenLoc); + if (Member) + BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc, + LParenLoc, Init, + RParenLoc); + else + BOMInit = new (C) CXXBaseOrMemberInitializer(C, IndirectMember, + MemberLoc, LParenLoc, + Init, RParenLoc); } else { BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc, LParenLoc, Init, RParenLoc, @@ -4313,7 +4322,6 @@ ASTReader::ReadCXXBaseOrMemberInitializers(PerFileData &F, if (IsWritten) BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); - BOMInit->setAnonUnionMember(AnonUnionMember); BaseOrMemberInitializers[i] = BOMInit; } } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 77d99cd6b3..ea63e7b9d8 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3255,11 +3255,15 @@ void ASTWriter::AddCXXBaseOrMemberInitializers( AddTypeSourceInfo(Init->getBaseClassInfo(), Record); Record.push_back(Init->isBaseVirtual()); } else { - AddDeclRef(Init->getMember(), Record); + Record.push_back(Init->isIndirectMemberInitializer()); + if (Init->isIndirectMemberInitializer()) + AddDeclRef(Init->getIndirectMember(), Record); + else + AddDeclRef(Init->getMember(), Record); } + AddSourceLocation(Init->getMemberLocation(), Record); AddStmt(Init->getInit()); - AddDeclRef(Init->getAnonUnionMember(), Record); AddSourceLocation(Init->getLParenLoc(), Record); AddSourceLocation(Init->getRParenLoc(), Record); Record.push_back(Init->isWritten()); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index b22cac0e7d..81280f4866 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -740,8 +740,8 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { // Visit the initializers in source order for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) { CXXBaseOrMemberInitializer *Init = WrittenInits[I]; - if (Init->isMemberInitializer()) { - if (Visit(MakeCursorMemberRef(Init->getMember(), + if (Init->isAnyMemberInitializer()) { + if (Visit(MakeCursorMemberRef(Init->getAnyMember(), Init->getMemberLocation(), TU))) return true; } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) {