The injected-class-name of class templates and class template
specializations can be treated as a template. Finally, we can parse
and process the first implementation of Fibonacci I wrote!

Note that this code does not handle all of the cases where
injected-class-names can be treated as templates. In particular,
there's an ambiguity case that we should be able to handle (but
can't), e.g.,

  template <class T> struct Base { }; 
  template <class T> struct Derived : Base<int>, Base<char> {
    typename Derived::Base b;       // error: ambiguous
    typename Derived::Base<double> d;  // OK 
  };




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67720 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 835792e..88c08b0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3425,6 +3425,8 @@
                                 Record->getIdentifier(), Record);
       InjectedClassName->setImplicit();
       InjectedClassName->setAccess(AS_public);
+      if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
+        InjectedClassName->setDescribedClassTemplate(Template);
       PushOnScopeChains(InjectedClassName, S);
       assert(InjectedClassName->isInjectedClassName() && 
              "Broken injected-class-name");
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 24b35ee..c0476a8 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -42,6 +42,28 @@
         return TNK_Template_template_parm;
       else
         assert(false && "Unknown TemplateDecl");
+    } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(IIDecl)) {
+      // C++ [temp.local]p1:
+      //   Like normal (non-template) classes, class templates have an
+      //   injected-class-name (Clause 9). The injected-class-name
+      //   can be used with or without a template-argument-list. When
+      //   it is used without a template-argument-list, it is
+      //   equivalent to the injected-class-name followed by the
+      //   template-parameters of the class template enclosed in
+      //   <>. When it is used with a template-argument-list, it
+      //   refers to the specified class template specialization,
+      //   which could be the current specialization or another
+      //   specialization.
+      if (Record->isInjectedClassName()) {
+        Record = cast<CXXRecordDecl>(Context.getCanonicalDecl(Record));
+        if ((Template = Record->getDescribedClassTemplate()))
+          return TNK_Class_template;
+        else if (ClassTemplateSpecializationDecl *Spec
+                   = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
+          Template = Spec->getSpecializedTemplate();
+          return TNK_Class_template;
+        }
+      }
     }
 
     // FIXME: What follows is a gross hack.
@@ -469,7 +491,7 @@
   // If we had a scope specifier, we better have a previous template
   // declaration!
 
-  TagDecl *NewClass = 
+  CXXRecordDecl *NewClass = 
     CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name,
                           PrevClassTemplate? 
                             PrevClassTemplate->getTemplatedDecl() : 0);
@@ -478,7 +500,8 @@
     = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
                                 DeclarationName(Name), TemplateParams,
                                 NewClass, PrevClassTemplate);
-  
+  NewClass->setDescribedClassTemplate(NewTemplate);
+
   // Set the lexical context of these templates
   NewClass->setLexicalDeclContext(CurContext);
   NewTemplate->setLexicalDeclContext(CurContext);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 46076f2..adddb29 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -279,6 +279,8 @@
 
   if (!D->isInjectedClassName())
     Record->setInstantiationOfMemberClass(D);
+  else
+    Record->setDescribedClassTemplate(D->getDescribedClassTemplate());
 
   Owner->addDecl(Record);
   return Record;