Implement the semantics of the injected-class-name within a class
template. The injected-class-name is either a type or a template,
depending on whether a '<' follows it. As a type, the
injected-class-name's template argument list contains its template
parameters in declaration order.

As part of this, add logic for canonicalizing declarations, and be
sure to canonicalize declarations used in template names and template
arguments. 

A TagType is dependent if the declaration it references is dependent.

I'm not happy about the rather complicated protocol needed to use
ASTContext::getTemplateSpecializationType.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71408 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ea69137..d9e883f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -123,8 +123,23 @@
     if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
       // Check whether we can use this type
       (void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-      
-      T = Context.getTypeDeclType(TD);
+  
+      if (getLangOptions().CPlusPlus) {
+        // C++ [temp.local]p2:
+        //   Within the scope of a class template specialization or
+        //   partial specialization, when the injected-class-name is
+        //   not followed by a <, it is equivalent to the
+        //   injected-class-name followed by the template-argument s
+        //   of the class template specialization or partial
+        //   specialization enclosed in <>.
+        if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
+          if (RD->isInjectedClassName())
+            if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
+              T = Template->getInjectedClassNameType(Context);
+      }
+
+      if (T.isNull())
+        T = Context.getTypeDeclType(TD);
     } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
       // Check whether we can use this interface.
       (void)DiagnoseUseOfDecl(IIDecl, NameLoc);