Improve the representation of template type parameters. We now
canonicalize by template parameter depth, index, and name, and the
unnamed version of a template parameter serves as the canonical.

TemplateTypeParmDecl no longer needs to inherit from
TemplateParmPosition, since depth and index information is present
within the type.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63899 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7784aed..a87a902 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1144,9 +1144,9 @@
   
   if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl))
     return getTypedefType(Typedef);
-  else if (TemplateTypeParmDecl *TP = dyn_cast<TemplateTypeParmDecl>(Decl))
-    return getTemplateTypeParmType(TP);
-  else if (ObjCInterfaceDecl *ObjCInterface = dyn_cast<ObjCInterfaceDecl>(Decl))
+  else if (isa<TemplateTypeParmDecl>(Decl)) {
+    assert(false && "Template type parameter types are always available.");
+  } else if (ObjCInterfaceDecl *ObjCInterface = dyn_cast<ObjCInterfaceDecl>(Decl))
     return getObjCInterfaceType(ObjCInterface);
 
   if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Decl)) {
@@ -1185,16 +1185,6 @@
   return QualType(Decl->TypeForDecl, 0);
 }
 
-/// getTemplateTypeParmType - Return the unique reference to the type
-/// for the specified template type parameter declaration. 
-QualType ASTContext::getTemplateTypeParmType(TemplateTypeParmDecl *Decl) {
-  if (!Decl->TypeForDecl) {
-    Decl->TypeForDecl = new (*this,8) TemplateTypeParmType(Decl);
-    Types.push_back(Decl->TypeForDecl);
-  }
-  return QualType(Decl->TypeForDecl, 0);
-}
-
 /// getObjCInterfaceType - Return the unique reference to the type for the
 /// specified ObjC interface decl.
 QualType ASTContext::getObjCInterfaceType(ObjCInterfaceDecl *Decl) {
@@ -1205,6 +1195,31 @@
   return QualType(Decl->TypeForDecl, 0);
 }
 
+/// \brief Retrieve the template type parameter type for a template
+/// parameter with the given depth, index, and (optionally) name.
+QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, 
+                                             IdentifierInfo *Name) {
+  llvm::FoldingSetNodeID ID;
+  TemplateTypeParmType::Profile(ID, Depth, Index, Name);
+  void *InsertPos = 0;
+  TemplateTypeParmType *TypeParm 
+    = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+  if (TypeParm)
+    return QualType(TypeParm, 0);
+  
+  if (Name)
+    TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, Name,
+                                         getTemplateTypeParmType(Depth, Index));
+  else
+    TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index);
+
+  Types.push_back(TypeParm);
+  TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos);
+
+  return QualType(TypeParm, 0);
+}
+
 /// CmpProtocolNames - Comparison predicate for sorting protocols
 /// alphabetically.
 static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index dcb8cda..ea027df 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -598,21 +598,17 @@
 //===----------------------------------------------------------------------===//
 
 void TemplateTypeParmDecl::EmitImpl(Serializer& S) const {
-  S.EmitInt(Depth);
-  S.EmitInt(Position);
   S.EmitBool(Typename);
-  NamedDecl::EmitInRec(S);
+  TypeDecl::EmitInRec(S);
 }
 
 TemplateTypeParmDecl *
 TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) {
-  unsigned Depth = D.ReadInt();
-  unsigned Position = D.ReadInt();
   bool Typename = D.ReadBool();
   TemplateTypeParmDecl *decl
-    = new (C) TemplateTypeParmDecl(0, SourceLocation(), Depth, Position,
-                                   0, Typename);
-  decl->NamedDecl::ReadInRec(D, C);
+    = new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, Typename, 
+                                   QualType());
+  decl->TypeDecl::ReadInRec(D, C);
   return decl;
 }
 
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 08cd5b3..3949395 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -78,7 +78,8 @@
 TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
                              SourceLocation L, unsigned D, unsigned P,
                              IdentifierInfo *Id, bool Typename) {
-  return new (C) TemplateTypeParmDecl(DC, L, D, P, Id, Typename);
+  QualType Type = C.getTemplateTypeParmType(D, P, Id);
+  return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index f39a325..199ad29 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1138,7 +1138,12 @@
 void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const {
   if (!InnerString.empty())    // Prefix the basic type, e.g. 'parmname X'.
     InnerString = ' ' + InnerString;
-  InnerString = getDecl()->getIdentifier()->getName() + InnerString;
+
+  if (!Name)
+    InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' + 
+      llvm::utostr_32(Index) + InnerString;
+  else
+    InnerString = Name->getName() + InnerString;
 }
 
 void ObjCInterfaceType::getAsStringInternal(std::string &InnerString) const {
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 12c3d03..57598d3 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -127,7 +127,7 @@
       break;
 
     case Type::TemplateTypeParm:
-      D.RegisterPtr(PtrID,TemplateTypeParmType::CreateImpl(Context, D));
+      D.RegisterPtr(PtrID, TemplateTypeParmType::CreateImpl(Context, D));
       break;
 
     case Type::VariableArray:
@@ -364,20 +364,18 @@
 //===----------------------------------------------------------------------===//
 
 void TemplateTypeParmType::EmitImpl(Serializer& S) const {
-  S.EmitPtr(getDecl());
+  S.EmitInt(Depth);
+  S.EmitInt(Index);
+  S.EmitPtr(Name);
 }
 
 Type* TemplateTypeParmType::CreateImpl(ASTContext& Context, Deserializer& D) {
-  std::vector<Type*>& Types = 
-    const_cast<std::vector<Type*>&>(Context.getTypes());
-  
-  TemplateTypeParmType* T = new TemplateTypeParmType(NULL);
-  Types.push_back(T);
-  
-  D.ReadPtr(T->Decl); // May be backpatched.
-  return T;
+  unsigned Depth = D.ReadInt();
+  unsigned Index = D.ReadInt();
+  IdentifierInfo *Name = D.ReadPtr<IdentifierInfo>();
+  return Context.getTemplateTypeParmType(Depth, Index, Name).getTypePtr();
 }
-  
+
 //===----------------------------------------------------------------------===//
 // VariableArrayType
 //===----------------------------------------------------------------------===//