Extend DependentNameType with a keyword enum that specifies whether
this was parsed as a typename-specifier, elaborated-type-specifier
(including the kind), or just a dependent qualified type name.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100039 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7fce55b..31c4370 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1962,19 +1962,24 @@
   return QualType(T, 0);
 }
 
-QualType ASTContext::getDependentNameType(NestedNameSpecifier *NNS,
-                                     const IdentifierInfo *Name,
-                                     QualType Canon) {
+QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
+                                          NestedNameSpecifier *NNS,
+                                          const IdentifierInfo *Name,
+                                          QualType Canon) {
   assert(NNS->isDependent() && "nested-name-specifier must be dependent");
 
   if (Canon.isNull()) {
     NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
-    if (CanonNNS != NNS)
-      Canon = getDependentNameType(CanonNNS, Name);
+    ElaboratedTypeKeyword CanonKeyword = Keyword;
+    if (Keyword == ETK_None)
+      CanonKeyword = ETK_Typename;
+    
+    if (CanonNNS != NNS || CanonKeyword != Keyword)
+      Canon = getDependentNameType(CanonKeyword, CanonNNS, Name);
   }
 
   llvm::FoldingSetNodeID ID;
-  DependentNameType::Profile(ID, NNS, Name);
+  DependentNameType::Profile(ID, Keyword, NNS, Name);
 
   void *InsertPos = 0;
   DependentNameType *T
@@ -1982,20 +1987,21 @@
   if (T)
     return QualType(T, 0);
 
-  T = new (*this) DependentNameType(NNS, Name, Canon);
+  T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
   Types.push_back(T);
   DependentNameTypes.InsertNode(T, InsertPos);
   return QualType(T, 0);
 }
 
 QualType
-ASTContext::getDependentNameType(NestedNameSpecifier *NNS,
-                            const TemplateSpecializationType *TemplateId,
-                            QualType Canon) {
+ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
+                                 NestedNameSpecifier *NNS,
+                                 const TemplateSpecializationType *TemplateId,
+                                 QualType Canon) {
   assert(NNS->isDependent() && "nested-name-specifier must be dependent");
 
   llvm::FoldingSetNodeID ID;
-  DependentNameType::Profile(ID, NNS, TemplateId);
+  DependentNameType::Profile(ID, Keyword, NNS, TemplateId);
 
   void *InsertPos = 0;
   DependentNameType *T
@@ -2006,12 +2012,16 @@
   if (Canon.isNull()) {
     NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
     QualType CanonType = getCanonicalType(QualType(TemplateId, 0));
-    if (CanonNNS != NNS || CanonType != QualType(TemplateId, 0)) {
+    ElaboratedTypeKeyword CanonKeyword = Keyword;
+    if (Keyword == ETK_None)
+      CanonKeyword = ETK_Typename;
+    if (CanonNNS != NNS || CanonKeyword != Keyword ||
+        CanonType != QualType(TemplateId, 0)) {
       const TemplateSpecializationType *CanonTemplateId
         = CanonType->getAs<TemplateSpecializationType>();
       assert(CanonTemplateId &&
              "Canonical type must also be a template specialization type");
-      Canon = getDependentNameType(CanonNNS, CanonTemplateId);
+      Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId);
     }
 
     DependentNameType *CheckT
@@ -2019,7 +2029,7 @@
     assert(!CheckT && "Typename canonical type is broken"); (void)CheckT;
   }
 
-  T = new (*this) DependentNameType(NNS, TemplateId, Canon);
+  T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon);
   Types.push_back(T);
   DependentNameTypes.InsertNode(T, InsertPos);
   return QualType(T, 0);
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index da0ac3f..4cf0922 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -572,7 +572,15 @@
   
   {
     llvm::raw_string_ostream OS(MyString);
-    OS << "typename ";
+    switch (T->getKeyword()) {
+    case ETK_None: break;
+    case ETK_Typename: OS << "typename "; break;
+    case ETK_Class: OS << "class "; break;
+    case ETK_Struct: OS << "struct "; break;
+    case ETK_Union: OS << "union "; break;
+    case ETK_Enum: OS << "enum "; break;
+    }
+    
     T->getQualifier()->print(OS, Policy);
     
     if (const IdentifierInfo *Ident = T->getIdentifier())