Enumeration declarations that were instantiated from an enumeration
within a template now have a link back to the enumeration from which
they were instantiated. This means that we can now find the
instantiation of an anonymous enumeration.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72482 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index a30cf0f..eb38367 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1149,10 +1149,15 @@
   /// to for code generation purposes.  Note that the enumerator constants may
   /// have a different type than this does.
   QualType IntegerType;
-  
+
+  /// \brief If the enumeration was instantiated from an enumeration
+  /// within a class or function template, this pointer refers to the
+  /// enumeration declared within the template.
+  EnumDecl *InstantiatedFrom;
+
   EnumDecl(DeclContext *DC, SourceLocation L,
            IdentifierInfo *Id)
-    : TagDecl(Enum, TK_enum, DC, L, Id) {
+    : TagDecl(Enum, TK_enum, DC, L, Id), InstantiatedFrom(0) {
       IntegerType = QualType();
     }
 public:
@@ -1188,6 +1193,15 @@
   /// \brief Set the underlying integer type.
   void setIntegerType(QualType T) { IntegerType = T; }
 
+  /// \brief Returns the enumeration (declared within the template)
+  /// from which this enumeration type was instantiated, or NULL if
+  /// this enumeration was not instantiated from any template.
+  EnumDecl *getInstantiatedFromMemberEnum() const {
+    return InstantiatedFrom;
+  }
+
+  void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; }
+
   static bool classof(const Decl *D) { return D->getKind() == Enum; }
   static bool classof(const EnumDecl *D) { return true; }
 };
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index adf0d11..6856623 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -120,6 +120,7 @@
 void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
   VisitTagDecl(ED);
   ED->setIntegerType(Reader.GetType(Record[Idx++]));
+  // FIXME: C++ InstantiatedFrom
 }
 
 void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 5d08334..ef04104 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -116,6 +116,7 @@
 void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
   VisitTagDecl(D);
   Writer.AddTypeRef(D->getIntegerType(), Record);
+  // FIXME: C++ InstantiatedFrom
   Code = pch::DECL_ENUM;
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a5eb779..41c1944 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -208,6 +208,7 @@
   EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, 
                                     D->getLocation(), D->getIdentifier(),
                                     /*PrevDecl=*/0);
+  Enum->setInstantiationOfMemberEnum(D);
   Enum->setAccess(D->getAccess());
   Owner->addDecl(SemaRef.Context, Enum);
   Enum->startDefinition();
@@ -648,7 +649,9 @@
     return Ctx.getCanonicalDecl(Function->getInstantiatedFromMemberFunction())
              == Ctx.getCanonicalDecl(D);
 
-  // FIXME: Need something similar to the above for EnumDecls.
+  if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
+    return Ctx.getCanonicalDecl(Enum->getInstantiatedFromMemberEnum())
+             == Ctx.getCanonicalDecl(D);
 
   // FIXME: How can we find instantiations of anonymous unions?
 
diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp
index 2512df1..cceaed0 100644
--- a/test/SemaTemplate/instantiate-declref.cpp
+++ b/test/SemaTemplate/instantiate-declref.cpp
@@ -9,8 +9,7 @@
           typedef T type;
 
           static enum K1 { K1Val = sizeof(T) } Kind1;
-          // FIXME: Remove the name K2, below
-          static enum K2 { K2Val = sizeof(T)*2 } Kind2;
+          static enum { K2Val = sizeof(T)*2 } Kind2;
 
           void foo() {
             K1 k1 = K1Val;