Make the type associated with a ClassTemplateSpecializationDecl be a
nicely sugared type that shows how the user wrote the actual
specialization. This sugared type won't actually show up until we
start doing instantiations.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65577 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 60d8b8b..2b4bc89 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1307,6 +1307,8 @@
                                                unsigned NumArgs,
                                                uintptr_t *Args, bool *ArgIsType,
                                                QualType Canon) {
+  Canon = getCanonicalType(Canon);
+
   llvm::FoldingSetNodeID ID;
   ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args, 
                                            ArgIsType);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 2732bf9..ab65492 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -374,22 +374,24 @@
 //===----------------------------------------------------------------------===//
 
 void TagDecl::startDefinition() {
-  cast<TagType>(TypeForDecl)->decl.setPointer(this);
-  cast<TagType>(TypeForDecl)->decl.setInt(1);
+  TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
+  TagT->decl.setPointer(this);
+  TagT->getAsTagType()->decl.setInt(1);
 }
 
 void TagDecl::completeDefinition() {
   assert((!TypeForDecl || 
-          cast<TagType>(TypeForDecl)->decl.getPointer() == this) &&
+          TypeForDecl->getAsTagType()->decl.getPointer() == this) &&
          "Attempt to redefine a tag definition?");
   IsDefinition = true;
-  cast<TagType>(TypeForDecl)->decl.setPointer(this);
-  cast<TagType>(TypeForDecl)->decl.setInt(0);
+  TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
+  TagT->decl.setPointer(this);
+  TagT->decl.setInt(0);
 }
 
 TagDecl* TagDecl::getDefinition(ASTContext& C) const {
   QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));
-  TagDecl* D = cast<TagDecl>(cast<TagType>(T)->getDecl());  
+  TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl());
   return D->isDefinition() ? D : 0;
 }
 
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index d6a0c35..574de16 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -446,8 +446,7 @@
     if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
       // If this is a tag type that has a definition or is currently
       // being defined, that definition is our primary context.
-      if (TagType *TagT 
-            = cast_or_null<TagType>(cast<TagDecl>(this)->TypeForDecl))
+      if (const TagType *TagT = cast<TagDecl>(this)->TypeForDecl->getAsTagType())
         if (TagT->isBeingDefined() || 
             (TagT->getDecl() && TagT->getDecl()->isDefinition()))
           return TagT->getDecl();
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 3ed4435..ed4fd44 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -179,7 +179,6 @@
   ClassTemplateSpecializationDecl *Result
     = new (Mem) ClassTemplateSpecializationDecl(DC, L, SpecializedTemplate,
                                                 TemplateArgs, NumTemplateArgs);
-  // FIXME: Do we want a prettier type here?
   Context.getTypeDeclType(Result, PrevDecl);
   return Result;
 }
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 210be03..327e623 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -331,7 +331,7 @@
 }
 
 const RecordType *Type::getAsRecordType() const {
-  // If this is directly a reference type, return it.
+  // If this is directly a record type, return it.
   if (const RecordType *RTy = dyn_cast<RecordType>(this))
     return RTy;
   
@@ -348,6 +348,24 @@
   return getDesugaredType()->getAsRecordType();
 }
 
+const TagType *Type::getAsTagType() const {
+  // If this is directly a tag type, return it.
+  if (const TagType *TagTy = dyn_cast<TagType>(this))
+    return TagTy;
+  
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<TagType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<TagType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsTagType();
+    return 0;
+  }
+
+  // If this is a typedef for a tag type, strip the typedef off without
+  // losing all typedef information.
+  return getDesugaredType()->getAsTagType();
+}
+
 const RecordType *Type::getAsStructureType() const {
   // If this is directly a structure type, return it.
   if (const RecordType *RT = dyn_cast<RecordType>(this)) {