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;