Parsing, semantic analysis, and template instantiation for typename
specifiers that terminate in a simple-template-id, e.g.,

  typename MetaFun::template apply<T1, T2>

Also, implement template instantiation for dependent
nested-name-specifiers that involve unresolved identifiers, e.g.,

  typename T::type::type





git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68166 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 422988d..cede0e5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1454,6 +1454,39 @@
   return QualType(T, 0);  
 }
 
+QualType 
+ASTContext::getTypenameType(NestedNameSpecifier *NNS, 
+                            const TemplateSpecializationType *TemplateId,
+                            QualType Canon) {
+  assert(NNS->isDependent() && "nested-name-specifier must be dependent");
+
+  if (Canon.isNull()) {
+    NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+    QualType CanonType = getCanonicalType(QualType(TemplateId, 0));
+    if (CanonNNS != NNS || CanonType != QualType(TemplateId, 0)) {
+      const TemplateSpecializationType *CanonTemplateId
+        = CanonType->getAsTemplateSpecializationType();
+      assert(CanonTemplateId &&
+             "Canonical type must also be a template specialization type");
+      Canon = getTypenameType(CanonNNS, CanonTemplateId);
+    }
+  }
+
+  llvm::FoldingSetNodeID ID;
+  TypenameType::Profile(ID, NNS, TemplateId);
+
+  void *InsertPos = 0;
+  TypenameType *T 
+    = TypenameTypes.FindNodeOrInsertPos(ID, InsertPos);
+  if (T)
+    return QualType(T, 0);
+
+  T = new (*this) TypenameType(NNS, TemplateId, Canon);
+  Types.push_back(T);
+  TypenameTypes.InsertNode(T, InsertPos);
+  return QualType(T, 0);    
+}
+
 /// CmpProtocolNames - Comparison predicate for sorting protocols
 /// alphabetically.
 static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,