From: Anders Carlsson Date: Tue, 1 Sep 2009 04:26:58 +0000 (+0000) Subject: Don't assert when instantiating member references to fields in anonymous structs. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d8b285fee4471f393da8ee30f552ceacdc362afa;p=clang Don't assert when instantiating member references to fields in anonymous structs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80657 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 5021655f33..01da133c07 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -196,6 +196,8 @@ class ASTContext { llvm::DenseMap InstantiatedFromUnresolvedUsingDecl; + llvm::DenseMap InstantiatedFromUnnamedFieldDecl; + TranslationUnitDecl *TUDecl; /// SourceMgr - The associated SourceManager object. @@ -267,12 +269,23 @@ public: /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl); + /// \brief If this using decl is instantiated from an unresolved using decl, + /// return it. UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); - void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, - UnresolvedUsingDecl *UUD); + + /// \brief Note that the using decl \p Inst is an instantiation of + /// the unresolved using decl \p Tmpl of a class template. + void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, + UnresolvedUsingDecl *Tmpl); + + + FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); + + void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } + const char *getCommentForDecl(const Decl *D); // Builtin Types. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index eebb11da99..1143b305ad 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -260,6 +260,25 @@ ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, InstantiatedFromUnresolvedUsingDecl[UD] = UUD; } +FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { + llvm::DenseMap::iterator Pos + = InstantiatedFromUnnamedFieldDecl.find(Field); + if (Pos == InstantiatedFromUnnamedFieldDecl.end()) + return 0; + + return Pos->second; +} + +void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, + FieldDecl *Tmpl) { + assert(!Inst->getDeclName() && "Instantiated field decl is not unnamed"); + assert(!Tmpl->getDeclName() && "Template field decl is not unnamed"); + assert(!InstantiatedFromUnnamedFieldDecl[Inst] && + "Already noted what unnamed field was instantiated from"); + + InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl; +} + namespace { class BeforeInTranslationUnit : std::binary_function { diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index c5b2894c49..84e464aba3 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -245,6 +245,11 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { if (Invalid) Field->setInvalidDecl(); + if (!Field->getDeclName()) { + // Keep track of where this decl came from. + SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); + } + Owner->addDecl(Field); } @@ -441,6 +446,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared); + Record->setAnonymousStructOrUnion(D->isAnonymousStructOrUnion()); + Owner->addDecl(Record); return Record; } @@ -1274,8 +1281,14 @@ static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { if (ClassTemplateDecl *Temp = dyn_cast(Other)) return isInstantiationOf(cast(D), Temp); - // FIXME: How can we find instantiations of anonymous unions? - + if (FieldDecl *Field = dyn_cast(Other)) { + if (!Field->getDeclName()) { + // This is an unnamed field. + return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) == + cast(D); + } + } + return D->getDeclName() && isa(Other) && D->getDeclName() == cast(Other)->getDeclName(); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 386a2c6d80..f1888c87a4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -840,6 +840,17 @@ public: SourceRange QualifierRange, SourceLocation MemberLoc, NamedDecl *Member) { + if (!Member->getDeclName()) { + // We have a reference to an unnamed field. + assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); + + MemberExpr *ME = + new (getSema().Context) MemberExpr(Base.takeAs(), isArrow, + Member, MemberLoc, + cast(Member)->getType()); + return getSema().Owned(ME); + } + CXXScopeSpec SS; if (Qualifier) { SS.setRange(QualifierRange); diff --git a/test/SemaTemplate/instantiate-anonymous-union.cpp b/test/SemaTemplate/instantiate-anonymous-union.cpp index 4eb5b0c24c..9c2467be64 100644 --- a/test/SemaTemplate/instantiate-anonymous-union.cpp +++ b/test/SemaTemplate/instantiate-anonymous-union.cpp @@ -6,3 +6,16 @@ template class A { struct { }; }; A a0; +template struct B { + union { + int a; + void* b; + }; + + void f() { + a = 10; + b = 0; + } +}; + +B b0;