Merged Elaborated and QualifiedName types.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103517 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 71ef09a..81b56ad 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -626,10 +626,6 @@
     return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
                        getReplacementType().getTypePtr());
 
-  case Type::Elaborated:
-    return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType()
-                         .getTypePtr());
-
   case Type::Typedef: {
     const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
     if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
@@ -652,8 +648,8 @@
     return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
                         .getTypePtr());
 
-  case Type::QualifiedName:
-    return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr());
+  case Type::Elaborated:
+    return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
 
   case Type::TemplateSpecialization:
     assert(getCanonicalType(T) != T &&
@@ -1890,29 +1886,28 @@
 }
 
 QualType
-ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS,
-                                 QualType NamedType) {
+ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
+                              NestedNameSpecifier *NNS,
+                              QualType NamedType) {
   llvm::FoldingSetNodeID ID;
-  QualifiedNameType::Profile(ID, NNS, NamedType);
+  ElaboratedType::Profile(ID, Keyword, NNS, NamedType);
 
   void *InsertPos = 0;
-  QualifiedNameType *T
-    = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos);
+  ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
   if (T)
     return QualType(T, 0);
 
   QualType Canon = NamedType;
   if (!Canon.isCanonical()) {
     Canon = getCanonicalType(NamedType);
-    QualifiedNameType *CheckT
-      = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(!CheckT && "Qualified name canonical type broken");
+    ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(!CheckT && "Elaborated canonical type broken");
     (void)CheckT;
   }
 
-  T = new (*this) QualifiedNameType(NNS, NamedType, Canon);
+  T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
   Types.push_back(T);
-  QualifiedNameTypes.InsertNode(T, InsertPos);
+  ElaboratedTypes.InsertNode(T, InsertPos);
   return QualType(T, 0);
 }
 
@@ -1989,30 +1984,6 @@
   return QualType(T, 0);
 }
 
-QualType
-ASTContext::getElaboratedType(QualType UnderlyingType,
-                              ElaboratedType::TagKind Tag) {
-  llvm::FoldingSetNodeID ID;
-  ElaboratedType::Profile(ID, UnderlyingType, Tag);
-
-  void *InsertPos = 0;
-  ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
-  if (T)
-    return QualType(T, 0);
-
-  QualType Canon = UnderlyingType;
-  if (!Canon.isCanonical()) {
-    Canon = getCanonicalType(Canon);
-    ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(!CheckT && "Elaborated canonical type is broken"); (void)CheckT;
-  }
-
-  T = new (*this) ElaboratedType(UnderlyingType, Tag, Canon);
-  Types.push_back(T);
-  ElaboratedTypes.InsertNode(T, InsertPos);
-  return QualType(T, 0);
-}
-
 /// CmpProtocolNames - Comparison predicate for sorting protocols
 /// alphabetically.
 static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
@@ -2813,7 +2784,7 @@
 QualType ASTContext::getCFConstantStringType() {
   if (!CFConstantStringTypeDecl) {
     CFConstantStringTypeDecl =
-      CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+      CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                        &Idents.get("NSConstantString"));
     CFConstantStringTypeDecl->startDefinition();
 
@@ -2855,7 +2826,7 @@
 QualType ASTContext::getNSConstantStringType() {
   if (!NSConstantStringTypeDecl) {
     NSConstantStringTypeDecl =
-    CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+    CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                      &Idents.get("__builtin_NSString"));
     NSConstantStringTypeDecl->startDefinition();
     
@@ -2894,7 +2865,7 @@
 QualType ASTContext::getObjCFastEnumerationStateType() {
   if (!ObjCFastEnumerationStateTypeDecl) {
     ObjCFastEnumerationStateTypeDecl =
-      CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+      CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                        &Idents.get("__objcFastEnumerationState"));
     ObjCFastEnumerationStateTypeDecl->startDefinition();
 
@@ -2929,7 +2900,7 @@
 
   RecordDecl *T;
   // FIXME: Needs the FlagAppleBlock bit.
-  T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+  T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                        &Idents.get("__block_descriptor"));
   T->startDefinition();
   
@@ -2974,7 +2945,7 @@
 
   RecordDecl *T;
   // FIXME: Needs the FlagAppleBlock bit.
-  T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+  T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                        &Idents.get("__block_descriptor_withcopydispose"));
   T->startDefinition();
   
@@ -3046,7 +3017,7 @@
   llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
                                   ++UniqueBlockByRefTypeID << '_' << DeclName;
   RecordDecl *T;
-  T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+  T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                        &Idents.get(Name.str()));
   T->startDefinition();
   QualType Int32Ty = IntTy;
@@ -3097,7 +3068,7 @@
   llvm::raw_svector_ostream(Name) << "__block_literal_"
                                   << ++UniqueBlockParmTypeID;
   RecordDecl *T;
-  T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+  T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
                        &Idents.get(Name.str()));
   T->startDefinition();
   QualType FieldTypes[] = {
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index e4cd2a9..23aae39 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -50,12 +50,6 @@
       QT = cast<ElaboratedType>(Ty)->desugar();
       continue;
     }
-    
-    // ...or a qualified name type...
-    if (isa<QualifiedNameType>(Ty)) {
-      QT = cast<QualifiedNameType>(Ty)->desugar();
-      continue;
-    }
 
     // ...or a substituted template type parameter.
     if (isa<SubstTemplateTypeParmType>(Ty)) {
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 083c1bf..aae02a4 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -68,11 +68,10 @@
     // FIXME: DependentDecltypeType
     QualType VisitRecordType(RecordType *T);
     QualType VisitEnumType(EnumType *T);
-    QualType VisitElaboratedType(ElaboratedType *T);
     // FIXME: TemplateTypeParmType
     // FIXME: SubstTemplateTypeParmType
     // FIXME: TemplateSpecializationType
-    QualType VisitQualifiedNameType(QualifiedNameType *T);
+    QualType VisitElaboratedType(ElaboratedType *T);
     // FIXME: DependentNameType
     QualType VisitObjCInterfaceType(ObjCInterfaceType *T);
     QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T);
@@ -532,19 +531,7 @@
                                   cast<TagType>(T2)->getDecl()))
       return false;
     break;
-      
-  case Type::Elaborated: {
-    const ElaboratedType *Elab1 = cast<ElaboratedType>(T1);
-    const ElaboratedType *Elab2 = cast<ElaboratedType>(T2);
-    if (Elab1->getTagKind() != Elab2->getTagKind())
-      return false;
-    if (!IsStructurallyEquivalent(Context, 
-                                  Elab1->getUnderlyingType(),
-                                  Elab2->getUnderlyingType()))
-      return false;
-    break;
-  }
-   
+
   case Type::TemplateTypeParm: {
     const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1);
     const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2);
@@ -594,16 +581,19 @@
     break;
   }
       
-  case Type::QualifiedName: {
-    const QualifiedNameType *Qual1 = cast<QualifiedNameType>(T1);
-    const QualifiedNameType *Qual2 = cast<QualifiedNameType>(T2);
+  case Type::Elaborated: {
+    const ElaboratedType *Elab1 = cast<ElaboratedType>(T1);
+    const ElaboratedType *Elab2 = cast<ElaboratedType>(T2);
+    // CHECKME: what if a keyword is ETK_None or ETK_typename ?
+    if (Elab1->getKeyword() != Elab2->getKeyword())
+      return false;
     if (!IsStructurallyEquivalent(Context, 
-                                  Qual1->getQualifier(), 
-                                  Qual2->getQualifier()))
+                                  Elab1->getQualifier(), 
+                                  Elab2->getQualifier()))
       return false;
     if (!IsStructurallyEquivalent(Context,
-                                  Qual1->getNamedType(),
-                                  Qual2->getNamedType()))
+                                  Elab1->getNamedType(),
+                                  Elab2->getNamedType()))
       return false;
     break;
   }
@@ -1293,24 +1283,20 @@
 }
 
 QualType ASTNodeImporter::VisitElaboratedType(ElaboratedType *T) {
-  QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
-  if (ToUnderlyingType.isNull())
-    return QualType();
-
-  return Importer.getToContext().getElaboratedType(ToUnderlyingType,
-                                                   T->getTagKind());
-}
-
-QualType ASTNodeImporter::VisitQualifiedNameType(QualifiedNameType *T) {
-  NestedNameSpecifier *ToQualifier = Importer.Import(T->getQualifier());
-  if (!ToQualifier)
-    return QualType();
+  NestedNameSpecifier *ToQualifier = 0;
+  // Note: the qualifier in an ElaboratedType is optional.
+  if (T->getQualifier()) {
+    ToQualifier = Importer.Import(T->getQualifier());
+    if (!ToQualifier)
+      return QualType();
+  }
 
   QualType ToNamedType = Importer.Import(T->getNamedType());
   if (ToNamedType.isNull())
     return QualType();
 
-  return Importer.getToContext().getQualifiedNameType(ToQualifier, ToNamedType);
+  return Importer.getToContext().getElaboratedType(T->getKeyword(),
+                                                   ToQualifier, ToNamedType);
 }
 
 QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 25f5fb7..28332bd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -23,7 +23,7 @@
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/Specifiers.h"
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace clang;
@@ -1520,16 +1520,6 @@
   return 0;
 }
 
-TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) {
-  switch (TypeSpec) {
-  default: llvm_unreachable("unexpected type specifier");
-  case DeclSpec::TST_struct: return TK_struct;
-  case DeclSpec::TST_class: return TK_class;
-  case DeclSpec::TST_union: return TK_union;
-  case DeclSpec::TST_enum: return TK_enum;
-  }
-}
-
 void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
                                SourceRange QualifierRange) {
   if (Qualifier) {
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index a279eda..8d9be13 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -137,7 +137,7 @@
 
     data().VBases[I] =
       CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
-                       VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
+                       VBaseClassDecl->getTagKind() == TTK_Class,
                        VBases[I]->getAccessSpecifier(), VBaseType);
   }
 }
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 45518e9..d6594cd 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -145,14 +145,14 @@
     InnerPolicy.SuppressScope = true;
 
     // Nested-name-specifiers are intended to contain minimally-qualified
-    // types. An actual QualifiedNameType will not occur, since we'll store
+    // types. An actual ElaboratedType will not occur, since we'll store
     // just the type that is referred to in the nested-name-specifier (e.g.,
     // a TypedefType, TagType, etc.). However, when we are dealing with
     // dependent template-id types (e.g., Outer<T>::template Inner<U>),
     // the type requires its own nested-name-specifier for uniqueness, so we
     // suppress that nested-name-specifier during printing.
-    assert(!isa<QualifiedNameType>(T) &&
-           "Qualified name type in nested-name-specifier");
+    assert(!isa<ElaboratedType>(T) &&
+           "Elaborated type in nested-name-specifier");
     if (const TemplateSpecializationType *SpecType
           = dyn_cast<TemplateSpecializationType>(T)) {
       // Print the template name without its corresponding
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 73f0e91..843785e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -764,36 +765,105 @@
   case TemplateTypeParm:
   case SubstTemplateTypeParm:
   case TemplateSpecialization:
-  case QualifiedName:
+  case Elaborated:
   case DependentName:
   case ObjCInterface:
   case ObjCObjectPointer:
-  case Elaborated:
     return true;
   default:
     return false;
   }
 }
 
-bool Type::isElaboratedTypeSpecifier() const {
-  if (getTypeClass() == Elaborated)
-    return true;
-  
-  if (const DependentNameType *Dependent = dyn_cast<DependentNameType>(this)) {
-    switch (Dependent->getKeyword()) {
-    case ETK_None:
-    case ETK_Typename:
-      return false;
-        
-    case ETK_Class:
-    case ETK_Struct:
-    case ETK_Union:
-    case ETK_Enum:
-      return true;
-    }
+TypeWithKeyword::~TypeWithKeyword() {
+}
+
+ElaboratedTypeKeyword
+TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
+  switch (TypeSpec) {
+  default: return ETK_None;
+  case TST_typename: return ETK_Typename;
+  case TST_class: return ETK_Class;
+  case TST_struct: return ETK_Struct;
+  case TST_union: return ETK_Union;
+  case TST_enum: return ETK_Enum;
   }
-  
-  return false;
+}
+
+TagTypeKind
+TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
+  switch(TypeSpec) {
+  case TST_class: return TTK_Class;
+  case TST_struct: return TTK_Struct;
+  case TST_union: return TTK_Union;
+  case TST_enum: return TTK_Enum;
+  default: llvm_unreachable("Type specifier is not a tag type kind.");
+  }
+}
+
+ElaboratedTypeKeyword
+TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
+  switch (Kind) {
+  case TTK_Class: return ETK_Class;
+  case TTK_Struct: return ETK_Struct;
+  case TTK_Union: return ETK_Union;
+  case TTK_Enum: return ETK_Enum;
+  }
+  llvm_unreachable("Unknown tag type kind.");
+}
+
+TagTypeKind
+TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
+  switch (Keyword) {
+  case ETK_Class: return TTK_Class;
+  case ETK_Struct: return TTK_Struct;
+  case ETK_Union: return TTK_Union;
+  case ETK_Enum: return TTK_Enum;
+  case ETK_None: // Fall through.
+  case ETK_Typename:
+    llvm_unreachable("Elaborated type keyword is not a tag type kind.");
+  }
+  llvm_unreachable("Unknown elaborated type keyword.");
+}
+
+bool
+TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
+  switch (Keyword) {
+  case ETK_None:
+  case ETK_Typename:
+    return false;
+  case ETK_Class:
+  case ETK_Struct:
+  case ETK_Union:
+  case ETK_Enum:
+    return true;
+  }
+  llvm_unreachable("Unknown elaborated type keyword.");
+}
+
+const char*
+TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
+  switch (Keyword) {
+  default: llvm_unreachable("Unknown elaborated type keyword.");
+  case ETK_None: return "";
+  case ETK_Typename: return "typename";
+  case ETK_Class:  return "class";
+  case ETK_Struct: return "struct";
+  case ETK_Union:  return "union";
+  case ETK_Enum:   return "enum";
+  }
+}
+
+bool Type::isElaboratedTypeSpecifier() const {
+  ElaboratedTypeKeyword Keyword;
+  if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this))
+    Keyword = Elab->getKeyword();
+  else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this))
+    Keyword = DepName->getKeyword();
+  else
+    return false;
+
+  return TypeWithKeyword::KeywordIsTagTypeKind(Keyword);
 }
 
 const char *Type::getTypeClassName() const {
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 915d7af..0478d4e 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -497,16 +497,6 @@
   PrintTag(T->getDecl(), S);
 }
 
-void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { 
-  Print(T->getUnderlyingType(), S);
-
-  // We don't actually make these in C, but the language options
-  // sometimes lie to us -- for example, if someone calls
-  // QualType::getAsString().  Just suppress the redundant tag if so.
-  if (Policy.LangOpts.CPlusPlus)
-    S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S;  
-}
-
 void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, 
                                         std::string &S) { 
   if (!S.empty())    // Prefix the basic type, e.g. 'parmname X'.
@@ -549,13 +539,17 @@
   PrintTemplateSpecialization(T->getInjectedTST(), S);
 }
 
-void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, 
-                                     std::string &S) { 
+void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
   std::string MyString;
   
   {
     llvm::raw_string_ostream OS(MyString);
-    T->getQualifier()->print(OS, Policy);
+    OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+    if (T->getKeyword() != ETK_None)
+      OS << " ";
+    NestedNameSpecifier* Qualifier = T->getQualifier();
+    if (Qualifier)
+      Qualifier->print(OS, Policy);
   }
   
   std::string TypeStr;
@@ -575,14 +569,9 @@
   
   {
     llvm::raw_string_ostream OS(MyString);
-    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;
-    }
+    OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+    if (T->getKeyword() != ETK_None)
+      OS << " ";
     
     T->getQualifier()->print(OS, Policy);