diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-09-01 04:26:58 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-09-01 04:26:58 +0000 |
| commit | 5da848427adeedacf39f1edf6700b15dc165c916 (patch) | |
| tree | 41f19d4c50c1d835d07abf99707b4128e325df35 | |
| parent | da9817cdddd4bdded105f7e58e4f62d35248f402 (diff) | |
| download | bcm5719-llvm-5da848427adeedacf39f1edf6700b15dc165c916.tar.gz bcm5719-llvm-5da848427adeedacf39f1edf6700b15dc165c916.zip | |
Don't assert when instantiating member references to fields in anonymous structs.
llvm-svn: 80657
| -rw-r--r-- | clang/include/clang/AST/ASTContext.h | 17 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 11 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/instantiate-anonymous-union.cpp | 13 |
5 files changed, 73 insertions, 4 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 5021655f331..01da133c07c 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -196,6 +196,8 @@ class ASTContext { llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *> InstantiatedFromUnresolvedUsingDecl; + llvm::DenseMap<FieldDecl *, FieldDecl *> 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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index eebb11da998..1143b305add 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -260,6 +260,25 @@ ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, InstantiatedFromUnresolvedUsingDecl[UD] = UUD; } +FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { + llvm::DenseMap<FieldDecl *, FieldDecl *>::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<SourceRange, SourceRange, bool> { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index c5b2894c498..84e464aba30 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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<ClassTemplateDecl>(Other)) return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp); - // FIXME: How can we find instantiations of anonymous unions? - + if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) { + if (!Field->getDeclName()) { + // This is an unnamed field. + return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) == + cast<FieldDecl>(D); + } + } + return D->getDeclName() && isa<NamedDecl>(Other) && D->getDeclName() == cast<NamedDecl>(Other)->getDeclName(); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 386a2c6d806..f1888c87a43 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/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<Expr>(), isArrow, + Member, MemberLoc, + cast<FieldDecl>(Member)->getType()); + return getSema().Owned(ME); + } + CXXScopeSpec SS; if (Qualifier) { SS.setRange(QualifierRange); diff --git a/clang/test/SemaTemplate/instantiate-anonymous-union.cpp b/clang/test/SemaTemplate/instantiate-anonymous-union.cpp index 4eb5b0c24cb..9c2467be645 100644 --- a/clang/test/SemaTemplate/instantiate-anonymous-union.cpp +++ b/clang/test/SemaTemplate/instantiate-anonymous-union.cpp @@ -6,3 +6,16 @@ template <typename T> class A { struct { }; }; A<int> a0; +template <typename T> struct B { + union { + int a; + void* b; + }; + + void f() { + a = 10; + b = 0; + } +}; + +B<int> b0; |

