diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 37 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 8 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 5 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 145 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 23 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 16 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 12 |
11 files changed, 198 insertions, 112 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 7b16809a1f..980e93c04d 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -98,6 +98,7 @@ namespace { Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D); Decl *VisitCXXConversionDecl(CXXConversionDecl *D); Decl *VisitFieldDecl(FieldDecl *D); + Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -2020,6 +2021,42 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return ToField; } +Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + // Import the major distinguishing characteristics of a variable. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + return 0; + + // Import the type. + QualType T = Importer.Import(D->getType()); + if (T.isNull()) + return 0; + + NamedDecl **NamedChain = + new (Importer.getToContext())NamedDecl*[D->getChainingSize()]; + + unsigned i = 0; + for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), + PE = D->chain_end(); PI != PE; ++PI) { + Decl* D = Importer.Import(*PI); + if (!D) + return 0; + NamedChain[i++] = cast<NamedDecl>(D); + } + + IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( + Importer.getToContext(), DC, + Loc, Name.getAsIdentifierInfo(), T, + NamedChain, D->getChainingSize()); + ToIndirectField->setAccess(D->getAccess()); + ToIndirectField->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToIndirectField); + LexicalDC->addDecl(ToIndirectField); + return ToIndirectField; +} + Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index c448116ed2..ef8f16861e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -768,7 +768,7 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); - if (isa<FieldDecl>(D)) + if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) return true; if (isa<CXXMethodDecl>(D)) return cast<CXXMethodDecl>(D)->isInstance(); @@ -2030,6 +2030,12 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, return new (C) EnumConstantDecl(CD, L, Id, T, E, V); } +IndirectFieldDecl *IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T, NamedDecl **CH, int CHS) { + return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); +} + SourceRange EnumConstantDecl::getSourceRange() const { SourceLocation End = getLocation(); if (Init) diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 5ba6623b20..7d8a92530e 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -249,6 +249,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCProperty: return IDNS_Ordinary; + case IndirectField: + return IDNS_Ordinary | IDNS_Member; + case ObjCCompatibleAlias: case ObjCInterface: return IDNS_Ordinary | IDNS_Type; @@ -524,8 +527,6 @@ bool DeclContext::isTransparentContext() const { return !cast<EnumDecl>(this)->isScoped(); else if (DeclKind == Decl::LinkageSpec) return true; - else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord) - return cast<RecordDecl>(this)->isAnonymousStructOrUnion(); return false; } diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index ba5970038d..bf26bd1f93 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -333,6 +333,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { islvalue = NTTParm->getType()->isReferenceType(); else islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || + isa<IndirectFieldDecl>(D) || (Ctx.getLangOptions().CPlusPlus && (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D))); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7c2a8fb105..2b970a34c4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1748,7 +1748,8 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, DeclContext *Owner, RecordDecl *AnonRecord, - AccessSpecifier AS) { + AccessSpecifier AS, + llvm::SmallVector<NamedDecl*, 2> &Chaining) { unsigned diagKind = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl : diag::err_anonymous_struct_member_redecl; @@ -1771,20 +1772,37 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, // definition, the members of the anonymous union are // considered to have been defined in the scope in which the // anonymous union is declared. - Owner->makeDeclVisibleInContext(*F); - S->AddDecl(*F); - SemaRef.IdResolver.AddDecl(*F); + Chaining.push_back(*F); + assert(Chaining.size() >= 2); + NamedDecl **NamedChain = + new (SemaRef.Context)NamedDecl*[Chaining.size()]; + for (unsigned i = 0; i < Chaining.size(); i++) + NamedChain[i] = Chaining[i]; + + IndirectFieldDecl* IndirectField = + IndirectFieldDecl::Create(SemaRef.Context, Owner, F->getLocation(), + F->getIdentifier(), F->getType(), + NamedChain, Chaining.size()); + + IndirectField->setAccess(AS); + IndirectField->setImplicit(); + SemaRef.PushOnScopeChains(IndirectField, S); // That includes picking up the appropriate access specifier. if (AS != AS_none) (*F)->setAccess(AS); + + Chaining.pop_back(); } } else if (const RecordType *InnerRecordType = (*F)->getType()->getAs<RecordType>()) { RecordDecl *InnerRecord = InnerRecordType->getDecl(); + + Chaining.push_back(*F); if (InnerRecord->isAnonymousStructOrUnion()) Invalid = Invalid || InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner, - InnerRecord, AS); + InnerRecord, AS, Chaining); + Chaining.pop_back(); } } @@ -1999,7 +2017,10 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Inject the members of the anonymous struct/union into the owning // context and into the identifier resolver chain for name lookup // purposes. - if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS)) + llvm::SmallVector<NamedDecl*, 2> Chain; + Chain.push_back(Anon); + + if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, Chain)) Invalid = true; // Mark this as an anonymous struct/union type. Note that we do not diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 2741c6de65..235b41e342 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1067,10 +1067,15 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, FieldDecl *Member = 0; DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); - if (Result.first != Result.second) + if (Result.first != Result.second) { Member = dyn_cast<FieldDecl>(*Result.first); - - // FIXME: Handle members of an anonymous union. + + // Handle anonymous union case. + if (!Member) + if (IndirectFieldDecl* IndirectField + = dyn_cast<IndirectFieldDecl>(*Result.first)) + Member = IndirectField->getAnonField(); + } if (Member) return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, @@ -2600,15 +2605,15 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // In addition, if class T has a user-declared constructor (12.1), every // non-static data member of class T shall have a name different from T. for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); - R.first != R.second; ++R.first) - if (FieldDecl *Field = dyn_cast<FieldDecl>(*R.first)) { - if (Record->hasUserDeclaredConstructor() || - !Field->getDeclContext()->Equals(Record)) { - Diag(Field->getLocation(), diag::err_member_name_of_class) - << Field->getDeclName(); + R.first != R.second; ++R.first) { + NamedDecl *D = *R.first; + if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) || + isa<IndirectFieldDecl>(D)) { + Diag(D->getLocation(), diag::err_member_name_of_class) + << D->getDeclName(); break; } - } + } } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bc811d0e77..37561028c2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -795,59 +795,18 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, D, NameInfo, Ty, VK)); } -/// \brief Given a field that represents a member of an anonymous -/// struct/union, build the path from that field's context to the -/// actual member. -/// -/// Construct the sequence of field member references we'll have to -/// perform to get to the field in the anonymous union/struct. The -/// list of members is built from the field outward, so traverse it -/// backwards to go from an object in the current context to the field -/// we found. -/// -/// \returns The variable from which the field access should begin, -/// for an anonymous struct/union that is not a member of another -/// class. Otherwise, returns NULL. -VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field, - llvm::SmallVectorImpl<FieldDecl *> &Path) { - assert(Field->getDeclContext()->isRecord() && - cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion() - && "Field must be stored inside an anonymous struct or union"); - - Path.push_back(Field); - VarDecl *BaseObject = 0; - DeclContext *Ctx = Field->getDeclContext(); - do { - RecordDecl *Record = cast<RecordDecl>(Ctx); - ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject(); - if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject)) - Path.push_back(AnonField); - else { - BaseObject = cast<VarDecl>(AnonObject); - break; - } - Ctx = Ctx->getParent(); - } while (Ctx->isRecord() && - cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()); - - return BaseObject; -} - ExprResult Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, - FieldDecl *Field, + IndirectFieldDecl *IndirectField, Expr *BaseObjectExpr, SourceLocation OpLoc) { - llvm::SmallVector<FieldDecl *, 4> AnonFields; - VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field, - AnonFields); - // Build the expression that refers to the base object, from // which we will build a sequence of member references to each // of the anonymous union objects and, eventually, the field we // found via name lookup. bool BaseObjectIsPointer = false; Qualifiers BaseQuals; + VarDecl *BaseObject = IndirectField->getVarDecl(); if (BaseObject) { // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). @@ -877,7 +836,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, if (!MD->isStatic()) { QualType AnonFieldType = Context.getTagDeclType( - cast<RecordDecl>(AnonFields.back()->getDeclContext())); + cast<RecordDecl>( + (*IndirectField->chain_begin())->getDeclContext())); QualType ThisType = Context.getTagDeclType(MD->getParent()); if ((Context.getCanonicalType(AnonFieldType) == Context.getCanonicalType(ThisType)) || @@ -890,24 +850,29 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, } } else { return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method) - << Field->getDeclName()); + << IndirectField->getDeclName()); } BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers()); } if (!BaseObjectExpr) return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use) - << Field->getDeclName()); + << IndirectField->getDeclName()); } // Build the implicit member references to the field of the // anonymous struct/union. Expr *Result = BaseObjectExpr; Qualifiers ResultQuals = BaseQuals; - for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator - FI = AnonFields.rbegin(), FIEnd = AnonFields.rend(); - FI != FIEnd; ++FI) { - FieldDecl *Field = *FI; + + IndirectFieldDecl::chain_iterator FI = IndirectField->chain_begin(), + FEnd = IndirectField->chain_end(); + + // Skip the first VarDecl if present. + if (BaseObject) + FI++; + for (; FI != FEnd; FI++) { + FieldDecl *Field = cast<FieldDecl>(*FI); QualType MemberType = Field->getType(); Qualifiers MemberTypeQuals = Context.getCanonicalType(MemberType).getQualifiers(); @@ -930,8 +895,9 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, MarkDeclarationReferenced(Loc, *FI); PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI); // FIXME: Might this end up being a qualified name? - Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, - OpLoc, MemberType, VK_LValue, + Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, + cast<FieldDecl>(*FI), OpLoc, + MemberType, VK_LValue, Field->isBitField() ? OK_BitField : OK_Ordinary); BaseObjectIsPointer = false; @@ -1048,10 +1014,6 @@ enum IMAKind { /// context is not an instance method. IMA_Unresolved_StaticContext, - /// The reference is to a member of an anonymous structure in a - /// non-class context. - IMA_AnonymousMember, - /// All possible referrents are instance members and the current /// context is not an instance method. IMA_Error_StaticContext, @@ -1084,16 +1046,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes; for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; + if (D->isCXXInstanceMember()) { CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); - - // If this is a member of an anonymous record, move out to the - // innermost non-anonymous struct or union. If there isn't one, - // that's a special case. - while (R->isAnonymousStructOrUnion()) { - R = dyn_cast<CXXRecordDecl>(R->getParent()); - if (!R) return IMA_AnonymousMember; - } Classes.insert(R->getCanonicalDecl()); } else @@ -1577,7 +1532,8 @@ ExprResult Sema::ActOnIdExpression(Scope *S, else if (R.isUnresolvableResult()) MightBeImplicitMember = true; else - MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()); + MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || + isa<IndirectFieldDecl>(R.getFoundDecl()); if (MightBeImplicitMember) return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); @@ -1598,11 +1554,6 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, case IMA_Instance: return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); - case IMA_AnonymousMember: - assert(R.isSingleResult()); - return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), - R.getAsSingle<FieldDecl>()); - case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: @@ -1959,9 +1910,9 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // (C++ [class.union]). // FIXME: This needs to happen post-isImplicitMemberReference? // FIXME: template-ids inside anonymous structs? - if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) - if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) - return BuildAnonymousStructUnionMemberReference(Loc, FD); + if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>()) + return BuildAnonymousStructUnionMemberReference(Loc, FD); + // If this is known to be an instance access, go ahead and build a // 'this' expression now. @@ -2153,6 +2104,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (VD->isInvalidDecl()) return ExprError(); + // Handle anonymous. + if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(VD)) + return BuildAnonymousStructUnionMemberReference(Loc, FD); + ExprValueKind VK = getValueKindForDecl(Context, VD); // If the identifier reference is inside a block, and it refers to a value @@ -3308,12 +3263,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { - // We may have found a field within an anonymous union or struct - // (C++ [class.union]). - if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion() && - !BaseType->getAs<RecordType>()->getDecl()->isAnonymousStructOrUnion()) - return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, - BaseExpr, OpLoc); // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note @@ -3356,6 +3305,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, MemberType, VK, OK)); } + if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) + // We may have found a field within an anonymous union or struct + // (C++ [class.union]). + return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, + BaseExpr, OpLoc); + if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, Var); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, @@ -7956,6 +7911,12 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); LookupQualifiedName(R, RD); FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>(); + IndirectFieldDecl *IndirectMemberDecl = 0; + if (!MemberDecl) { + if (IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()) + MemberDecl = IndirectMemberDecl->getAnonField(); + } + if (!MemberDecl) return ExprError(Diag(BuiltinLoc, diag::err_no_member) << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, @@ -7974,12 +7935,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, } RecordDecl *Parent = MemberDecl->getParent(); - bool AnonStructUnion = Parent->isAnonymousStructOrUnion(); - if (AnonStructUnion) { - do { - Parent = cast<RecordDecl>(Parent->getParent()); - } while (Parent->isAnonymousStructOrUnion()); - } + if (IndirectMemberDecl) + Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext()); // If the member was found in a base class, introduce OffsetOfNodes for // the base class indirections. @@ -7992,15 +7949,17 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, Comps.push_back(OffsetOfNode(B->Base)); } - if (AnonStructUnion) { - llvm::SmallVector<FieldDecl*, 4> Path; - BuildAnonymousStructUnionMemberPath(MemberDecl, Path); - unsigned n = Path.size(); - for (int j = n - 1; j > -1; --j) - Comps.push_back(OffsetOfNode(OC.LocStart, Path[j], OC.LocEnd)); - } else { + if (IndirectMemberDecl) { + for (IndirectFieldDecl::chain_iterator FI = + IndirectMemberDecl->chain_begin(), + FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) { + assert(isa<FieldDecl>(*FI)); + Comps.push_back(OffsetOfNode(OC.LocStart, + cast<FieldDecl>(*FI), OC.LocEnd)); + } + } else Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd)); - } + CurrentType = MemberDecl->getType().getNonReferenceType(); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 9458e3580c..1b47332c53 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1429,6 +1429,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, } else if (!KnownField) { // Determine whether we found a field at all. ReplacementField = dyn_cast<FieldDecl>(*Lookup.first); + + // Check if ReplacementField is an anonymous field. + if (!ReplacementField) + if (IndirectFieldDecl* IField = dyn_cast<IndirectFieldDecl>(*Lookup.first)) + ReplacementField = IField->getAnonField(); } if (!ReplacementField) { diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 436488ed26..fc298c10e4 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -456,6 +456,29 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { return Field; } +Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + NamedDecl **NamedChain = + new (SemaRef.Context)NamedDecl*[D->getChainingSize()]; + + int i = 0; + for (IndirectFieldDecl::chain_iterator PI = + D->chain_begin(), PE = D->chain_end(); + PI != PE; ++PI) + NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(), + *PI, TemplateArgs)); + + IndirectFieldDecl* IndirectField + = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), D->getType(), + NamedChain, D->getChainingSize()); + + + IndirectField->setImplicit(D->isImplicit()); + IndirectField->setAccess(D->getAccess()); + Owner->addDecl(IndirectField); + return IndirectField; +} + Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Handle friend type expressions by simply substituting template // parameters into the pattern type and checking the result. diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 9f5d0c11d1..b1e46a623e 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -107,6 +107,7 @@ namespace clang { void VisitCXXDestructorDecl(CXXDestructorDecl *D); void VisitCXXConversionDecl(CXXConversionDecl *D); void VisitFieldDecl(FieldDecl *FD); + void VisitIndirectFieldDecl(IndirectFieldDecl *FD); void VisitVarDecl(VarDecl *VD); void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); @@ -635,6 +636,17 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { } } +void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { + VisitValueDecl(FD); + + FD->ChainingSize = Record[Idx++]; + assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2"); + FD->Chaining = new (*Reader.getContext())NamedDecl*[FD->ChainingSize]; + + for (unsigned I = 0; I != FD->ChainingSize; ++I) + FD->Chaining[I] = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); +} + void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VisitDeclaratorDecl(VD); VisitRedeclarable(VD); @@ -1475,6 +1487,10 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0, false); break; + case DECL_INDIRECTFIELD: + D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), + 0, 0); + break; case DECL_VAR: D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, SC_None, SC_None); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index f7bb23764d..27adb26d71 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -72,6 +72,7 @@ namespace clang { void VisitCXXDestructorDecl(CXXDestructorDecl *D); void VisitCXXConversionDecl(CXXConversionDecl *D); void VisitFieldDecl(FieldDecl *D); + void VisitIndirectFieldDecl(IndirectFieldDecl *D); void VisitVarDecl(VarDecl *D); void VisitImplicitParamDecl(ImplicitParamDecl *D); void VisitParmVarDecl(ParmVarDecl *D); @@ -528,6 +529,17 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { Code = serialization::DECL_FIELD; } +void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + VisitValueDecl(D); + Record.push_back(D->getChainingSize()); + + for (IndirectFieldDecl::chain_iterator + P = D->chain_begin(), + PEnd = D->chain_end(); P != PEnd; ++P) + Writer.AddDeclRef(*P, Record); + Code = serialization::DECL_INDIRECTFIELD; +} + void ASTDeclWriter::VisitVarDecl(VarDecl *D) { VisitDeclaratorDecl(D); VisitRedeclarable(D); |