Add pretty-printing for class template specializations, e.g.,

  'struct A<double, int>'

In the "template instantiation depth exceeded" message, print
"-ftemplate-depth-N" rather than "-ftemplate-depth=N".

An unnamed tag type that is declared with a typedef, e.g., 

  typedef struct { int x, y; } Point;

can be used as a template argument. Allow this, and check that we get
sensible pretty-printing for such things.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66560 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index f9cf847..205ebef 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1287,10 +1287,11 @@
     InnerString = Name->getName() + InnerString;
 }
 
-void 
-ClassTemplateSpecializationType::
-getAsStringInternal(std::string &InnerString) const {
-  std::string SpecString = Template->getNameAsString();
+/// \brief Print a template argument list, including the '<' and '>'
+/// enclosing the template arguments.
+static std::string printTemplateArgumentList(const TemplateArgument *Args,
+                                             unsigned NumArgs) {
+  std::string SpecString;
   SpecString += '<';
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
     if (Arg)
@@ -1298,22 +1299,22 @@
     
     // Print the argument into a string.
     std::string ArgString;
-    switch (getArg(Arg).getKind()) {
+    switch (Args[Arg].getKind()) {
     case TemplateArgument::Type:
-      getArg(Arg).getAsType().getAsStringInternal(ArgString);
+      Args[Arg].getAsType().getAsStringInternal(ArgString);
       break;
 
     case TemplateArgument::Declaration:
-      ArgString = cast<NamedDecl>(getArg(Arg).getAsDecl())->getNameAsString();
+      ArgString = cast<NamedDecl>(Args[Arg].getAsDecl())->getNameAsString();
       break;
 
     case TemplateArgument::Integral:
-      ArgString = getArg(Arg).getAsIntegral()->toString(10, true);
+      ArgString = Args[Arg].getAsIntegral()->toString(10, true);
       break;
 
     case TemplateArgument::Expression: {
       llvm::raw_string_ostream s(ArgString);
-      getArg(Arg).getAsExpr()->printPretty(s);
+      Args[Arg].getAsExpr()->printPretty(s);
       break;
     }
     }
@@ -1335,6 +1336,14 @@
 
   SpecString += '>';
 
+  return SpecString;
+}
+
+void 
+ClassTemplateSpecializationType::
+getAsStringInternal(std::string &InnerString) const {
+  std::string SpecString = Template->getNameAsString();
+  SpecString += printTemplateArgumentList(getArgs(), getNumArgs());
   if (InnerString.empty())
     InnerString.swap(SpecString);
   else
@@ -1395,6 +1404,16 @@
   } else
     ID = "<anonymous>";
 
+  // If this is a class template specialization, print the template
+  // arguments.
+  if (ClassTemplateSpecializationDecl *Spec 
+        = dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
+    std::string TemplateArgs 
+      = printTemplateArgumentList(Spec->getTemplateArgs(),
+                                  Spec->getNumTemplateArgs());
+    InnerString = TemplateArgs + InnerString;
+  }
+
   if (Kind)
     InnerString = std::string(Kind) + " " + ID + InnerString;
   else