Implement template instantiation for ClassTemplateSpecializationTypes,
such as replacing 'T' in vector<T>. There are a few aspects to this:

  - Extend TemplateArgument to allow arbitrary expressions (an
    Expr*), and switch ClassTemplateSpecializationType to store
    TemplateArguments rather than it's own type-or-expression
    representation.

  - ClassTemplateSpecializationType can now store dependent types. In
    that case, the canonical type is another
    ClassTemplateSpecializationType (with default template arguments
    expanded) rather than a declaration (we don't build Decls for
    dependent types).

  - Split ActOnClassTemplateId into ActOnClassTemplateId (called from
    the parser) and CheckClassTemplateId (called from
    ActOnClassTemplateId and InstantiateType). They're smart enough to
    handle dependent types, now.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66509 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4579fb5..a51f432 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1309,14 +1309,15 @@
 
 QualType 
 ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
+                                               const TemplateArgument *Args,
                                                unsigned NumArgs,
-                                               uintptr_t *Args, bool *ArgIsType,
                                                QualType Canon) {
-  Canon = getCanonicalType(Canon);
+  if (!Canon.isNull())
+    Canon = getCanonicalType(Canon);
 
   llvm::FoldingSetNodeID ID;
-  ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args, 
-                                           ArgIsType);
+  ClassTemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
+
   void *InsertPos = 0;
   ClassTemplateSpecializationType *Spec
     = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -1324,13 +1325,11 @@
   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);
+  void *Mem = Allocate((sizeof(ClassTemplateSpecializationType) + 
+                        sizeof(TemplateArgument) * NumArgs),
+                       8);
+  Spec = new (Mem) ClassTemplateSpecializationType(Template, Args, NumArgs, 
+                                                   Canon);
   Types.push_back(Spec);
   ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos);
 
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index ed4fd44..ac76c25 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -145,6 +145,15 @@
 }
 
 //===----------------------------------------------------------------------===//
+// TemplateArgument Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
+  TypeOrValue = reinterpret_cast<uintptr_t>(E);
+  StartLoc = E->getSourceRange().getBegin();
+}
+
+//===----------------------------------------------------------------------===//
 // ClassTemplateSpecializationDecl Implementation
 //===----------------------------------------------------------------------===//
 ClassTemplateSpecializationDecl::
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 3b06b4e..412b0cf 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -921,59 +921,77 @@
   return isa<EnumDecl>(TT->getDecl());
 }
 
-void 
+bool 
 ClassTemplateSpecializationType::
-packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words) {
-  const unsigned BitsPerWord = sizeof(uintptr_t) * 8;
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
+  for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
+    switch (Args[Idx].getKind()) {
+    case TemplateArgument::Type:
+      if (Args[Idx].getAsType()->isDependentType())
+        return true;
+      break;
+      
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+      // Never dependent
+      break;
 
-  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];
+    case TemplateArgument::Expression:
+      if (Args[Idx].getAsExpr()->isTypeDependent() ||
+          Args[Idx].getAsExpr()->isValueDependent())
+        return true;
+      break;
     }
-    Words[PW] = Word;
   }
+
+  return false;
 }
 
 ClassTemplateSpecializationType::
-ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
-                                uintptr_t *Args, bool *ArgIsType,
-                                QualType Canon)
-  : Type(ClassTemplateSpecialization, Canon, /*FIXME:Dependent=*/false),
-    Template(T), NumArgs(NumArgs) 
+ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args,
+                                unsigned NumArgs, QualType Canon)
+  : Type(ClassTemplateSpecialization, 
+         Canon.isNull()? QualType(this, 0) : Canon,
+         /*FIXME: Check for dependent template */
+         anyDependentTemplateArguments(Args, NumArgs)),
+    Template(T), NumArgs(NumArgs)
 {
-  uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1);
+  assert((!Canon.isNull() || 
+          anyDependentTemplateArguments(Args, NumArgs)) &&
+         "No canonical type for non-dependent class template specialization");
 
-  // 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);
+  TemplateArgument *TemplateArgs 
+    = reinterpret_cast<TemplateArgument *>(this + 1);
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
-    Data[Arg] = Args[Arg];
+    new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
 }
 
 void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
-    if (!isArgType(Arg))
-      getArgAsExpr(Arg)->Destroy(C);
+    if (Expr *E = getArg(Arg).getAsExpr())
+      E->Destroy(C);
 }
 
-uintptr_t
-ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
-  const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
-  Data += getNumPackedWords(NumArgs);
-  return Data[Arg];
+ClassTemplateSpecializationType::iterator
+ClassTemplateSpecializationType::end() const {
+  return begin() + getNumArgs();
 }
 
-bool ClassTemplateSpecializationType::isArgType(unsigned Arg) const {
-  const unsigned BitsPerWord = sizeof(uintptr_t) * 8;
-  const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
-  Data += Arg / BitsPerWord;
-  return (*Data >> ((NumArgs - Arg) % BitsPerWord - 1)) & 0x01;
+const TemplateArgument &
+ClassTemplateSpecializationType::getArg(unsigned Idx) const {
+  assert(Idx < getNumArgs() && "Template argument out of range");
+  return getArgs()[Idx];
+}
+
+void 
+ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, 
+                                         TemplateDecl *T, 
+                                         const TemplateArgument *Args, 
+                                         unsigned NumArgs) {
+  ID.AddPointer(T);
+
+  for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
+    Args[Idx].Profile(ID);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1280,11 +1298,24 @@
     
     // Print the argument into a string.
     std::string ArgString;
-    if (isArgType(Arg))
-      getArgAsType(Arg).getAsStringInternal(ArgString);
-    else {
+    switch (getArg(Arg).getKind()) {
+    case TemplateArgument::Type:
+      getArg(Arg).getAsType().getAsStringInternal(ArgString);
+      break;
+
+    case TemplateArgument::Declaration:
+      ArgString = cast<NamedDecl>(getArg(Arg).getAsDecl())->getNameAsString();
+      break;
+
+    case TemplateArgument::Integral:
+      ArgString = getArg(Arg).getAsIntegral()->toString(10, true);
+      break;
+
+    case TemplateArgument::Expression: {
       llvm::raw_string_ostream s(ArgString);
-      getArgAsExpr(Arg)->printPretty(s);
+      getArg(Arg).getAsExpr()->printPretty(s);
+      break;
+    }
     }
 
     // If this is the first argument and its string representation
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index b7a8f1a..1b9fed4 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -390,13 +390,7 @@
   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));
-  }
+  // FIXME: Serialize class template specialization types
 }
 
 Type* 
@@ -409,19 +403,10 @@
   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();
+  // FIXME: De-serialize class template specialization types
+  (void)Template;
+  (void)NumArgs;
+  return 0;
 }
 
 //===----------------------------------------------------------------------===//