Start processing template-ids as types when the template-name refers
to a class template. For example, the template-id 'vector<int>' now
has a nice, sugary type in the type system. What we can do now:

  - Parse template-ids like 'vector<int>' (where 'vector' names a
    class template) and form proper types for them in the type system.
  - Parse icky template-ids like 'A<5>' and 'A<(5 > 0)>' properly,
    using (sadly) a bool in the parser to tell it whether '>' should
    be treated as an operator or not.

This is a baby-step, with major problems and limitations:
  - There are currently two ways that we handle template arguments
  (whether they are types or expressions). These will be merged, and,
  most likely, TemplateArg will disappear.
  - We don't have any notion of the declaration of class template
  specializations or of template instantiations, so all template-ids
  are fancy names for 'int' :)



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64153 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a87a902..72aef42 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1220,6 +1220,34 @@
   return QualType(TypeParm, 0);
 }
 
+QualType 
+ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
+                                               unsigned NumArgs,
+                                               uintptr_t *Args, bool *ArgIsType,
+                                               QualType Canon) {
+  llvm::FoldingSetNodeID ID;
+  ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args, 
+                                           ArgIsType);
+  void *InsertPos = 0;
+  ClassTemplateSpecializationType *Spec
+    = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+  if (Spec)
+    return QualType(Spec, 0);
+  
+  void *Mem = Allocate(sizeof(ClassTemplateSpecializationType) + 
+                       (sizeof(uintptr_t) * 
+                        (ClassTemplateSpecializationType::
+                           getNumPackedWords(NumArgs) + 
+                         NumArgs)), 8);
+  Spec = new (Mem) ClassTemplateSpecializationType(Template, NumArgs, Args,
+                                                   ArgIsType, Canon);
+  Types.push_back(Spec);
+  ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+
+  return QualType(Spec, 0);  
+}
+
 /// CmpProtocolNames - Comparison predicate for sorting protocols
 /// alphabetically.
 static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index d005ca3..ab5a3bc 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/STLExtras.h"
@@ -43,6 +44,11 @@
                                          NumParams, RAngleLoc);
 }
 
+void TemplateArg::Destroy(ASTContext &C) {
+  if (Kind == ExprArg)
+    getAsExpr()->Destroy(C);
+}
+
 //===----------------------------------------------------------------------===//
 // TemplateDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 106d0eb..6ec5062 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -489,6 +489,14 @@
   return dyn_cast<TemplateTypeParmType>(CanonicalType);
 }
 
+const ClassTemplateSpecializationType *
+Type::getClassTemplateSpecializationType() const {
+  // There is no sugar for class template specialization types, so
+  // just return the canonical type pointer if it is the right class.
+  return dyn_cast<ClassTemplateSpecializationType>(CanonicalType);
+}
+
+
 bool Type::isIntegerType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Bool &&
@@ -882,6 +890,54 @@
   return isa<EnumDecl>(TT->getDecl());
 }
 
+void 
+ClassTemplateSpecializationType::
+packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words) {
+  const unsigned BitsPerWord = sizeof(uintptr_t) * CHAR_BIT;
+
+  for (unsigned PW = 0, NumPackedWords = getNumPackedWords(NumArgs), Arg = 0;
+       PW != NumPackedWords; ++PW) {
+    uintptr_t Word = 0;
+    for (unsigned Bit = 0; Bit < BitsPerWord && Arg < NumArgs; ++Bit, ++Arg) {
+      Word <<= 1;
+      Word |= Values[Arg];
+    }
+    Words[PW] = Word;
+  }
+}
+
+ClassTemplateSpecializationType::
+ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
+                                uintptr_t *Args, bool *ArgIsType,
+                                QualType Canon)
+  : Type(ClassTemplateSpecialization, Canon, /*FIXME:Dependent=*/false),
+    Template(T), NumArgs(NumArgs) 
+{
+  uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1);
+
+  // Pack the argument-is-type values into the words just after the
+  // class template specialization type.
+  packBooleanValues(NumArgs, ArgIsType, Data);
+
+  // Copy the template arguments after the packed words.
+  Data += getNumPackedWords(NumArgs);
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+    Data[Arg] = Args[Arg];
+}
+
+uintptr_t
+ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
+  const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
+  Data += getNumPackedWords(NumArgs);
+  return Data[Arg];
+}
+
+bool ClassTemplateSpecializationType::isArgType(unsigned Arg) const {
+  const unsigned BitsPerWord = sizeof(uintptr_t) * CHAR_BIT;
+  const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
+  Data += Arg / BitsPerWord;
+  return (*Data >> (Arg % BitsPerWord)) & 0x01;
+}
 
 //===----------------------------------------------------------------------===//
 // Type Printing
@@ -1146,6 +1202,47 @@
     InnerString = Name->getName() + InnerString;
 }
 
+void 
+ClassTemplateSpecializationType::
+getAsStringInternal(std::string &InnerString) const {
+  std::string SpecString = Template->getNameAsString();
+  SpecString += '<';
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+    if (Arg)
+      SpecString += ", ";
+    
+    // Print the argument into a string.
+    std::string ArgString;
+    if (isArgType(Arg))
+      getArgAsType(Arg).getAsStringInternal(ArgString);
+    else {
+      llvm::raw_string_ostream s(ArgString);
+      getArgAsExpr(Arg)->printPretty(s);
+    }
+
+    // If this is the first argument and its string representation
+    // begins with the global scope specifier ('::foo'), add a space
+    // to avoid printing the diagraph '<:'.
+    if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+      SpecString += ' ';
+
+    SpecString += ArgString;
+  }
+
+  // If the last character of our string is '>', add another space to
+  // keep the two '>''s separate tokens. We don't *have* to do this in
+  // C++0x, but it's still good hygiene.
+  if (SpecString[SpecString.size() - 1] == '>')
+    SpecString += ' ';
+
+  SpecString += '>';
+
+  if (InnerString.empty())
+    InnerString.swap(SpecString);
+  else
+    InnerString = SpecString + ' ' + InnerString;
+}
+
 void ObjCInterfaceType::getAsStringInternal(std::string &InnerString) const {
   if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
     InnerString = ' ' + InnerString;
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 57598d3..90bc67a 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/AST/Type.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ASTContext.h"
 #include "llvm/Bitcode/Serialize.h"
@@ -377,6 +378,48 @@
 }
 
 //===----------------------------------------------------------------------===//
+// ClassTemplateSpecializationType
+//===----------------------------------------------------------------------===//
+
+void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const {
+  S.Emit(getCanonicalTypeInternal());
+  S.EmitPtr(Template);
+  S.EmitInt(NumArgs);
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+    S.EmitBool(isArgType(Arg));
+    if (isArgType(Arg))
+      S.Emit(getArgAsType(Arg));
+    else
+      S.EmitOwnedPtr(getArgAsExpr(Arg));
+  }
+}
+
+Type* 
+ClassTemplateSpecializationType::
+CreateImpl(ASTContext& Context, Deserializer& D) {
+  llvm::SmallVector<uintptr_t, 16> Args;
+  llvm::SmallVector<bool, 16> ArgIsType;
+
+  QualType Canon = QualType::ReadVal(D);
+  TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>());
+  unsigned NumArgs = D.ReadInt();
+
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+    bool IsType = D.ReadBool();
+    ArgIsType.push_back(IsType);
+    if (IsType)
+      Args.push_back(
+         reinterpret_cast<uintptr_t>(QualType::ReadVal(D).getAsOpaquePtr()));
+    else
+      Args.push_back(reinterpret_cast<uintptr_t>(D.ReadOwnedPtr<Expr>(Context)));
+  }
+
+  return Context.getClassTemplateSpecializationType(Template, NumArgs,
+                                                    &Args[0], &ArgIsType[0],
+                                                    Canon).getTypePtr();
+}
+
+//===----------------------------------------------------------------------===//
 // VariableArrayType
 //===----------------------------------------------------------------------===//