Track source information for template arguments and template specialization
types.  Preserve it through template instantiation.  Preserve it through PCH,
although TSTs themselves aren't serializable, so that's pretty much meaningless.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85500 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7be55eb..d60a820 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1765,6 +1765,19 @@
 
 QualType
 ASTContext::getTemplateSpecializationType(TemplateName Template,
+                                          const TemplateArgumentLoc *Args,
+                                          unsigned NumArgs,
+                                          QualType Canon) {
+  llvm::SmallVector<TemplateArgument, 4> ArgVec;
+  ArgVec.reserve(NumArgs);
+  for (unsigned i = 0; i != NumArgs; ++i)
+    ArgVec.push_back(Args[i].getArgument());
+
+  return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, Canon);
+}
+
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
                                           const TemplateArgument *Args,
                                           unsigned NumArgs,
                                           QualType Canon) {
@@ -2298,17 +2311,14 @@
       return Arg;
 
     case TemplateArgument::Declaration:
-      return TemplateArgument(SourceLocation(),
-                              Arg.getAsDecl()->getCanonicalDecl());
+      return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
 
     case TemplateArgument::Integral:
-      return TemplateArgument(SourceLocation(),
-                              *Arg.getAsIntegral(),
+      return TemplateArgument(*Arg.getAsIntegral(),
                               getCanonicalType(Arg.getIntegralType()));
 
     case TemplateArgument::Type:
-      return TemplateArgument(SourceLocation(),
-                              getCanonicalType(Arg.getAsType()));
+      return TemplateArgument(getCanonicalType(Arg.getAsType()));
 
     case TemplateArgument::Pack: {
       // FIXME: Allocate in ASTContext
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 49244e1..9ebc91a 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/STLExtras.h"
 using namespace clang;
@@ -209,8 +210,7 @@
        Param != ParamEnd; ++Param) {
     if (isa<TemplateTypeParmDecl>(*Param)) {
       QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
-      TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
-                                              ParamType));
+      TemplateArgs.push_back(TemplateArgument(ParamType));
     } else if (NonTypeTemplateParmDecl *NTTP =
                  dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
       Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
@@ -220,7 +220,7 @@
       TemplateArgs.push_back(TemplateArgument(E));
     } else {
       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
-      TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
+      TemplateArgs.push_back(TemplateArgument(TTP));
     }
   }
 
@@ -244,6 +244,10 @@
   return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
 }
 
+SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
+  return DefaultArgument->getTypeLoc().getFullSourceRange().getBegin();
+}
+
 unsigned TemplateTypeParmDecl::getDepth() const {
   return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
 }
@@ -454,12 +458,19 @@
        TemplateParameterList *Params,
        ClassTemplateDecl *SpecializedTemplate,
        TemplateArgumentListBuilder &Builder,
+       TemplateArgumentLoc *ArgInfos, unsigned N,
        ClassTemplatePartialSpecializationDecl *PrevDecl) {
+  TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
+  for (unsigned I = 0; I != N; ++I)
+    ClonedArgs[I] = ArgInfos[I];
+
   ClassTemplatePartialSpecializationDecl *Result
     = new (Context)ClassTemplatePartialSpecializationDecl(Context,
                                                           DC, L, Params,
                                                           SpecializedTemplate,
-                                                          Builder, PrevDecl);
+                                                          Builder,
+                                                          ClonedArgs, N,
+                                                          PrevDecl);
   Result->setSpecializationKind(TSK_ExplicitSpecialization);
   Context.getTypeDeclType(Result, PrevDecl);
   return Result;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index ad9c9cb..ad91cd3 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -35,7 +35,7 @@
                          NamedDecl *D, SourceLocation NameLoc,
                          bool HasExplicitTemplateArgumentList,
                          SourceLocation LAngleLoc,
-                         const TemplateArgument *ExplicitTemplateArgs,
+                         const TemplateArgumentLoc *ExplicitTemplateArgs,
                          unsigned NumExplicitTemplateArgs,
                          SourceLocation RAngleLoc,
                          QualType T, bool TD, bool VD)
@@ -58,9 +58,9 @@
     ETemplateArgs->RAngleLoc = RAngleLoc;
     ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs;
     
-    TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs();
+    TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
     for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I)
-      new (TemplateArgs + I) TemplateArgument(ExplicitTemplateArgs[I]);
+      new (TemplateArgs + I) TemplateArgumentLoc(ExplicitTemplateArgs[I]);
   }
 }
 
@@ -82,7 +82,7 @@
                                  SourceLocation NameLoc,
                                  bool HasExplicitTemplateArgumentList,
                                  SourceLocation LAngleLoc,
-                                 const TemplateArgument *ExplicitTemplateArgs,
+                                 const TemplateArgumentLoc *ExplicitTemplateArgs,
                                  unsigned NumExplicitTemplateArgs,
                                  SourceLocation RAngleLoc,
                                  QualType T, bool TD, bool VD) {
@@ -92,7 +92,7 @@
   
   if (HasExplicitTemplateArgumentList)
     Size += sizeof(ExplicitTemplateArgumentList) +
-            sizeof(TemplateArgument) * NumExplicitTemplateArgs;
+            sizeof(TemplateArgumentLoc) * NumExplicitTemplateArgs;
   
   void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
   return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
@@ -428,7 +428,7 @@
                        SourceRange qualrange, NamedDecl *memberdecl,
                        SourceLocation l, bool has_explicit,
                        SourceLocation langle,
-                       const TemplateArgument *targs, unsigned numtargs,
+                       const TemplateArgumentLoc *targs, unsigned numtargs,
                        SourceLocation rangle, QualType ty)
   : Expr(MemberExprClass, ty,
          base->isTypeDependent() || (qual && qual->isDependent()),
@@ -450,9 +450,9 @@
     ETemplateArgs->RAngleLoc = rangle;
     ETemplateArgs->NumTemplateArgs = numtargs;
 
-    TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs();
+    TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
     for (unsigned I = 0; I < numtargs; ++I)
-      new (TemplateArgs + I) TemplateArgument(targs[I]);
+      new (TemplateArgs + I) TemplateArgumentLoc(targs[I]);
   }
 }
 
@@ -463,7 +463,7 @@
                                SourceLocation l,
                                bool has_explicit,
                                SourceLocation langle,
-                               const TemplateArgument *targs,
+                               const TemplateArgumentLoc *targs,
                                unsigned numtargs,
                                SourceLocation rangle,
                                QualType ty) {
@@ -473,7 +473,7 @@
 
   if (has_explicit)
     Size += sizeof(ExplicitTemplateArgumentList) +
-    sizeof(TemplateArgument) * numtargs;
+    sizeof(TemplateArgumentLoc) * numtargs;
 
   void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
   return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index cba0e22..7c6fc41 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -151,7 +151,7 @@
                                      TemplateName Template,
                                      SourceLocation TemplateNameLoc,
                                      SourceLocation LAngleLoc,
-                                     const TemplateArgument *TemplateArgs,
+                                     const TemplateArgumentLoc *TemplateArgs,
                                      unsigned NumTemplateArgs,
                                      SourceLocation RAngleLoc)
   : Expr(TemplateIdRefExprClass, T,
@@ -164,10 +164,10 @@
     Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template),
     TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc),
     RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) {
-  TemplateArgument *StoredTemplateArgs
-    = reinterpret_cast<TemplateArgument *> (this+1);
+  TemplateArgumentLoc *StoredTemplateArgs
+    = reinterpret_cast<TemplateArgumentLoc *> (this+1);
   for (unsigned I = 0; I != NumTemplateArgs; ++I)
-    new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
+    new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
 }
 
 TemplateIdRefExpr *
@@ -176,19 +176,19 @@
                           SourceRange QualifierRange,
                           TemplateName Template, SourceLocation TemplateNameLoc,
                           SourceLocation LAngleLoc,
-                          const TemplateArgument *TemplateArgs,
+                          const TemplateArgumentLoc *TemplateArgs,
                           unsigned NumTemplateArgs, SourceLocation RAngleLoc) {
   void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
-                               sizeof(TemplateArgument) * NumTemplateArgs);
+                               sizeof(TemplateArgumentLoc) * NumTemplateArgs);
   return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
                                      TemplateNameLoc, LAngleLoc, TemplateArgs,
                                      NumTemplateArgs, RAngleLoc);
 }
 
 void TemplateIdRefExpr::DoDestroy(ASTContext &Context) {
-  const TemplateArgument *TemplateArgs = getTemplateArgs();
+  const TemplateArgumentLoc *TemplateArgs = getTemplateArgs();
   for (unsigned I = 0; I != NumTemplateArgs; ++I)
-    if (Expr *E = TemplateArgs[I].getAsExpr())
+    if (Expr *E = TemplateArgs[I].getArgument().getAsExpr())
       E->Destroy(Context);
   this->~TemplateIdRefExpr();
   Context.Deallocate(this);
@@ -528,7 +528,7 @@
                                                  SourceLocation MemberLoc,
                                                  bool HasExplicitTemplateArgs,
                                                  SourceLocation LAngleLoc,
-                                           const TemplateArgument *TemplateArgs,
+                                       const TemplateArgumentLoc *TemplateArgs,
                                                  unsigned NumTemplateArgs,
                                                  SourceLocation RAngleLoc)
   : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
@@ -545,9 +545,9 @@
     ETemplateArgs->RAngleLoc = RAngleLoc;
     ETemplateArgs->NumTemplateArgs = NumTemplateArgs;
 
-    TemplateArgument *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
+    TemplateArgumentLoc *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
     for (unsigned I = 0; I < NumTemplateArgs; ++I)
-      new (SavedTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
+      new (SavedTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
   }
 }
 
@@ -562,7 +562,7 @@
                                 SourceLocation MemberLoc,
                                 bool HasExplicitTemplateArgs,
                                 SourceLocation LAngleLoc,
-                                const TemplateArgument *TemplateArgs,
+                                const TemplateArgumentLoc *TemplateArgs,
                                 unsigned NumTemplateArgs,
                                 SourceLocation RAngleLoc) {
   if (!HasExplicitTemplateArgs)
@@ -573,7 +573,7 @@
 
   void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) +
                          sizeof(ExplicitTemplateArgumentList) +
-                         sizeof(TemplateArgument) * NumTemplateArgs,
+                         sizeof(TemplateArgumentLoc) * NumTemplateArgs,
                          llvm::alignof<CXXUnresolvedMemberExpr>());
   return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
                                            Qualifier, QualifierRange,
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index a6327c9..02e0c74 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -60,7 +60,10 @@
 
     /// \brief Visit template arguments that occur within an expression or
     /// statement.
-    void VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs);
+    void VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs);
+
+    /// \brief Visit a single template argument.
+    void VisitTemplateArgument(const TemplateArgument &Arg);
   };
 }
 
@@ -674,39 +677,42 @@
   Name.Profile(ID);
 }
 
-void StmtProfiler::VisitTemplateArguments(const TemplateArgument *Args,
+void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args,
                                           unsigned NumArgs) {
   ID.AddInteger(NumArgs);
-  for (unsigned I = 0; I != NumArgs; ++I) {
-    const TemplateArgument &Arg = Args[I];
+  for (unsigned I = 0; I != NumArgs; ++I)
+    VisitTemplateArgument(Args[I].getArgument());
+}
 
-    // Mostly repetitive with TemplateArgument::Profile!
-    ID.AddInteger(Arg.getKind());
-    switch (Arg.getKind()) {
-      case TemplateArgument::Null:
-        break;
+void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
+  // Mostly repetitive with TemplateArgument::Profile!
+  ID.AddInteger(Arg.getKind());
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    break;
 
-      case TemplateArgument::Type:
-        VisitType(Arg.getAsType());
-        break;
+  case TemplateArgument::Type:
+    VisitType(Arg.getAsType());
+    break;
 
-      case TemplateArgument::Declaration:
-        VisitDecl(Arg.getAsDecl());
-        break;
+  case TemplateArgument::Declaration:
+    VisitDecl(Arg.getAsDecl());
+    break;
 
-      case TemplateArgument::Integral:
-        Arg.getAsIntegral()->Profile(ID);
-        VisitType(Arg.getIntegralType());
-        break;
+  case TemplateArgument::Integral:
+    Arg.getAsIntegral()->Profile(ID);
+    VisitType(Arg.getIntegralType());
+    break;
 
-      case TemplateArgument::Expression:
-        Visit(Arg.getAsExpr());
-        break;
+  case TemplateArgument::Expression:
+    Visit(Arg.getAsExpr());
+    break;
 
-      case TemplateArgument::Pack:
-        VisitTemplateArguments(Arg.pack_begin(), Arg.pack_size());
-        break;
-    }
+  case TemplateArgument::Pack:
+    const TemplateArgument *Pack = Arg.pack_begin();
+    for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i)
+      VisitTemplateArgument(Pack[i]);
+    break;
   }
 }
 
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 3b3ec2b..b136fe0 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -16,6 +16,7 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -23,11 +24,6 @@
 // TemplateArgument Implementation
 //===----------------------------------------------------------------------===//
 
-TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
-  TypeOrValue = reinterpret_cast<uintptr_t>(E);
-  StartLoc = E->getSourceRange().getBegin();
-}
-
 /// \brief Construct a template argument pack.
 void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
                                        bool CopyArgs) {
@@ -77,3 +73,25 @@
       Args.Args[I].Profile(ID, Context);
   }
 }
+
+//===----------------------------------------------------------------------===//
+// TemplateArgumentLoc Implementation
+//===----------------------------------------------------------------------===//
+
+SourceLocation TemplateArgumentLoc::getLocation() const {
+  switch (Argument.getKind()) {
+  case TemplateArgument::Expression:
+    return getSourceExpression()->getExprLoc();
+  case TemplateArgument::Type:
+    return getSourceDeclaratorInfo()->
+      getTypeLoc().getFullSourceRange().getBegin();
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Pack:
+  case TemplateArgument::Null:
+    return SourceLocation();
+  }
+
+  // Silence bonus gcc warning.
+  return SourceLocation();
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 5fb0178..65ed767 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -791,40 +791,48 @@
   return isa<EnumDecl>(TT->getDecl());
 }
 
-bool
-TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
-  for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
-    switch (Args[Idx].getKind()) {
-    case TemplateArgument::Null:
-      assert(false && "Should not have a NULL template argument");
-      break;
+static bool isDependent(const TemplateArgument &Arg) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    assert(false && "Should not have a NULL template argument");
+    return false;
 
-    case TemplateArgument::Type:
-      if (Args[Idx].getAsType()->isDependentType())
-        return true;
-      break;
+  case TemplateArgument::Type:
+    return Arg.getAsType()->isDependentType();
 
-    case TemplateArgument::Declaration:
-    case TemplateArgument::Integral:
-      // Never dependent
-      break;
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Integral:
+    // Never dependent
+    return false;
 
-    case TemplateArgument::Expression:
-      if (Args[Idx].getAsExpr()->isTypeDependent() ||
-          Args[Idx].getAsExpr()->isValueDependent())
-        return true;
-      break;
+  case TemplateArgument::Expression:
+    return (Arg.getAsExpr()->isTypeDependent() ||
+            Arg.getAsExpr()->isValueDependent());
 
-    case TemplateArgument::Pack:
-      assert(0 && "FIXME: Implement!");
-      break;
-    }
+  case TemplateArgument::Pack:
+    assert(0 && "FIXME: Implement!");
+    return false;
   }
 
   return false;
 }
 
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
+  for (unsigned i = 0; i != N; ++i)
+    if (isDependent(Args[i].getArgument()))
+      return true;
+  return false;
+}
+
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
+  for (unsigned i = 0; i != N; ++i)
+    if (isDependent(Args[i]))
+      return true;
+  return false;
+}
+
 TemplateSpecializationType::
 TemplateSpecializationType(ASTContext &Context, TemplateName T,
                            const TemplateArgument *Args,
@@ -1260,6 +1268,38 @@
   getReplacementType().getAsStringInternal(InnerString, Policy);
 }
 
+static void PrintTemplateArgument(std::string &Buffer,
+                                  const TemplateArgument &Arg,
+                                  const PrintingPolicy &Policy) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    assert(false && "Null template argument");
+    break;
+    
+  case TemplateArgument::Type:
+    Arg.getAsType().getAsStringInternal(Buffer, Policy);
+    break;
+
+  case TemplateArgument::Declaration:
+    Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
+    break;
+
+  case TemplateArgument::Integral:
+    Buffer = Arg.getAsIntegral()->toString(10, true);
+    break;
+
+  case TemplateArgument::Expression: {
+    llvm::raw_string_ostream s(Buffer);
+    Arg.getAsExpr()->printPretty(s, 0, Policy);
+    break;
+  }
+
+  case TemplateArgument::Pack:
+    assert(0 && "FIXME: Implement!");
+    break;
+  }
+}
+
 std::string
 TemplateSpecializationType::PrintTemplateArgumentList(
                                                   const TemplateArgument *Args,
@@ -1273,32 +1313,41 @@
 
     // Print the argument into a string.
     std::string ArgString;
-    switch (Args[Arg].getKind()) {
-    case TemplateArgument::Null:
-      assert(false && "Null template argument");
-      break;
+    PrintTemplateArgument(ArgString, Args[Arg], Policy);
 
-    case TemplateArgument::Type:
-      Args[Arg].getAsType().getAsStringInternal(ArgString, Policy);
-      break;
+    // 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 += ' ';
 
-    case TemplateArgument::Declaration:
-      ArgString = cast<NamedDecl>(Args[Arg].getAsDecl())->getNameAsString();
-      break;
+    SpecString += ArgString;
+  }
 
-    case TemplateArgument::Integral:
-      ArgString = Args[Arg].getAsIntegral()->toString(10, true);
-      break;
+  // 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 += ' ';
 
-    case TemplateArgument::Expression: {
-      llvm::raw_string_ostream s(ArgString);
-      Args[Arg].getAsExpr()->printPretty(s, 0, Policy);
-      break;
-    }
-    case TemplateArgument::Pack:
-      assert(0 && "FIXME: Implement!");
-      break;
-    }
+  SpecString += '>';
+
+  return SpecString;
+}
+
+// Sadly, repeat all that with TemplateArgLoc.
+std::string TemplateSpecializationType::
+PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
+                          const PrintingPolicy &Policy) {
+  std::string SpecString;
+  SpecString += '<';
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+    if (Arg)
+      SpecString += ", ";
+
+    // Print the argument into a string.
+    std::string ArgString;
+    PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
 
     // If this is the first argument and its string representation
     // begins with the global scope specifier ('::foo'), add a space