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 5021655..01da133 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -196,6 +196,8 @@
llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>
InstantiatedFromUnresolvedUsingDecl;
+ llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
+
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
@@ -267,12 +269,23 @@
/// 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 eebb11d..1143b30 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -260,6 +260,25 @@
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/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c5b2894..84e464a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -245,6 +245,11 @@
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 @@
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 @@
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/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 386a2c6..f1888c8 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -840,6 +840,17 @@
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/test/SemaTemplate/instantiate-anonymous-union.cpp b/test/SemaTemplate/instantiate-anonymous-union.cpp
index 4eb5b0c..9c2467b 100644
--- a/test/SemaTemplate/instantiate-anonymous-union.cpp
+++ b/test/SemaTemplate/instantiate-anonymous-union.cpp
@@ -6,3 +6,16 @@
A<int> a0;
+template <typename T> struct B {
+ union {
+ int a;
+ void* b;
+ };
+
+ void f() {
+ a = 10;
+ b = 0;
+ }
+};
+
+B<int> b0;