Add type information to integral template argument if required.
authorPratyush Das <reikdas@gmail.com>
Wed, 12 May 2021 17:28:41 +0000 (17:28 +0000)
committerVassil Vassilev <v.g.vassilev@gmail.com>
Wed, 12 May 2021 19:00:08 +0000 (19:00 +0000)
Non-comprehensive list of cases:
 * Dumping template arguments;
 * Corresponding parameter contains a deduced type;
 * Template arguments are for a DeclRefExpr that hadMultipleCandidates()

Type information is added in the form of prefixes (u8, u, U, L),
suffixes (U, L, UL, LL, ULL) or explicit casts to printed integral template
argument, if MSVC codeview mode is disabled.

Differential revision: https://reviews.llvm.org/D77598

38 files changed:
clang-tools-extra/clangd/Hover.cpp
clang/include/clang/AST/DeclTemplate.h
clang/include/clang/AST/Expr.h
clang/include/clang/AST/StmtDataCollectors.td
clang/include/clang/AST/TemplateBase.h
clang/lib/AST/ASTTypeTraits.cpp
clang/lib/AST/DeclPrinter.cpp
clang/lib/AST/DeclTemplate.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/NestedNameSpecifier.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/TemplateBase.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/Analysis/PathDiagnostic.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/test/Analysis/eval-predefined-exprs.cpp
clang/test/CXX/lex/lex.literal/lex.ext/p12.cpp
clang/test/CXX/lex/lex.literal/lex.ext/p13.cpp [new file with mode: 0644]
clang/test/CXX/lex/lex.literal/lex.ext/p14.cpp [new file with mode: 0644]
clang/test/CodeGenCXX/debug-info-codeview-template-literal.cpp [new file with mode: 0644]
clang/test/CodeGenCXX/debug-info-codeview-template-type.cpp [new file with mode: 0644]
clang/test/SemaCXX/builtin-align-cxx.cpp
clang/test/SemaCXX/cxx11-ast-print.cpp
clang/test/SemaCXX/cxx1z-ast-print.cpp [new file with mode: 0644]
clang/test/SemaCXX/matrix-type-builtins.cpp
clang/test/SemaCXX/matrix-type-operators.cpp
clang/test/SemaTemplate/address_space-dependent.cpp
clang/test/SemaTemplate/default-arguments-ast-print.cpp [new file with mode: 0644]
clang/test/SemaTemplate/delegating-constructors.cpp
clang/test/SemaTemplate/matrix-type.cpp
clang/test/SemaTemplate/temp_arg_enum_printing.cpp
clang/test/SemaTemplate/temp_arg_nontype.cpp
clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
clang/tools/libclang/CIndex.cpp
clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp

index c58dab2..3651a34 100644 (file)
@@ -223,7 +223,8 @@ fetchTemplateParameters(const TemplateParameterList *Params,
       if (TTPD->hasDefaultArgument()) {
         P.Default.emplace();
         llvm::raw_string_ostream Out(*P.Default);
-        TTPD->getDefaultArgument().getArgument().print(PP, Out);
+        TTPD->getDefaultArgument().getArgument().print(PP, Out,
+                                                       /*IncludeType*/ false);
       }
     }
     TempParameters.push_back(std::move(P));
index 7fbf629..0cd8f00 100644 (file)
@@ -204,6 +204,9 @@ public:
              bool OmitTemplateKW = false) const;
   void print(raw_ostream &Out, const ASTContext &Context,
              const PrintingPolicy &Policy, bool OmitTemplateKW = false) const;
+
+  static bool shouldIncludeTypeForArgument(const TemplateParameterList *TPL,
+                                           unsigned Idx);
 };
 
 /// Stores a list of template parameters and the associated
index a44d069..589199d 100644 (file)
@@ -1615,6 +1615,8 @@ public:
     return T->getStmtClass() == CharacterLiteralClass;
   }
 
+  static void print(unsigned val, CharacterKind Kind, raw_ostream &OS);
+
   // Iterators
   child_range children() {
     return child_range(child_iterator(), child_iterator());
index 7cb9f16..922dd2a 100644 (file)
@@ -51,7 +51,7 @@ class CallExpr {
         // Print all template arguments into ArgString
         llvm::raw_string_ostream OS(ArgString);
         for (unsigned i = 0; i < Args->size(); ++i) {
-          Args->get(i).print(Context.getLangOpts(), OS);
+          Args->get(i).print(Context.getLangOpts(), OS, /*IncludeType*/ true);
           // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
           OS << '\n';
         }
index 19f2cad..fa27a12 100644 (file)
@@ -389,7 +389,8 @@ public:
   TemplateArgument getPackExpansionPattern() const;
 
   /// Print this template argument to the given output stream.
-  void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
+  void print(const PrintingPolicy &Policy, raw_ostream &Out,
+             bool IncludeType) const;
 
   /// Debugging aid that dumps the template argument.
   void dump(raw_ostream &Out) const;
index 8f9ceea..4a033bf 100644 (file)
@@ -140,9 +140,9 @@ ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
 void DynTypedNode::print(llvm::raw_ostream &OS,
                          const PrintingPolicy &PP) const {
   if (const TemplateArgument *TA = get<TemplateArgument>())
-    TA->print(PP, OS);
+    TA->print(PP, OS, /*IncludeType*/ true);
   else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
-    TAL->getArgument().print(PP, OS);
+    TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
   else if (const TemplateName *TN = get<TemplateName>())
     TN->print(OS, PP);
   else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
index 7ba31c4..90391ca 100644 (file)
@@ -110,8 +110,12 @@ namespace {
 
     void printTemplateParameters(const TemplateParameterList *Params,
                                  bool OmitTemplateKW = false);
-    void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args);
-    void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args);
+    void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,
+                                const TemplateParameterList *Params,
+                                bool TemplOverloaded);
+    void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
+                                const TemplateParameterList *Params,
+                                bool TemplOverloaded);
     void prettyPrintAttributes(Decl *D);
     void prettyPrintPragmas(Decl *D);
     void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
@@ -644,11 +648,16 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
     llvm::raw_string_ostream POut(Proto);
     DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
     const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
+    const TemplateParameterList *TPL = D->getTemplateSpecializationInfo()
+                                           ->getTemplate()
+                                           ->getTemplateParameters();
     if (TArgAsWritten && !Policy.PrintCanonicalTypes)
-      TArgPrinter.printTemplateArguments(TArgAsWritten->arguments());
+      TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), TPL,
+                                         /*TemplOverloaded*/ true);
     else if (const TemplateArgumentList *TArgs =
                  D->getTemplateSpecializationArgs())
-      TArgPrinter.printTemplateArguments(TArgs->asArray());
+      TArgPrinter.printTemplateArguments(TArgs->asArray(), TPL,
+                                         /*TemplOverloaded*/ true);
   }
 
   QualType Ty = D->getType();
@@ -988,7 +997,9 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
           if (const auto *TST =
                   dyn_cast<TemplateSpecializationType>(TSI->getType()))
             Args = TST->template_arguments();
-      printTemplateArguments(Args);
+      printTemplateArguments(
+          Args, S->getSpecializedTemplate()->getTemplateParameters(),
+          /*TemplOverloaded*/ false);
     }
   }
 
@@ -1080,22 +1091,36 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
     Out << ' ';
 }
 
-void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args) {
+void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
+                                         const TemplateParameterList *Params,
+                                         bool TemplOverloaded) {
   Out << "<";
   for (size_t I = 0, E = Args.size(); I < E; ++I) {
     if (I)
       Out << ", ";
-    Args[I].print(Policy, Out);
+    if (TemplOverloaded || !Params)
+      Args[I].print(Policy, Out, /*IncludeType*/ true);
+    else
+      Args[I].print(
+          Policy, Out,
+          TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
   }
   Out << ">";
 }
 
-void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args) {
+void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
+                                         const TemplateParameterList *Params,
+                                         bool TemplOverloaded) {
   Out << "<";
   for (size_t I = 0, E = Args.size(); I < E; ++I) {
     if (I)
       Out << ", ";
-    Args[I].getArgument().print(Policy, Out);
+    if (TemplOverloaded)
+      Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
+    else
+      Args[I].getArgument().print(
+          Policy, Out,
+          TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
   }
   Out << ">";
 }
index 25235c5..4b3a406 100644 (file)
@@ -167,6 +167,18 @@ bool TemplateParameterList::hasAssociatedConstraints() const {
   return HasRequiresClause || HasConstrainedParameters;
 }
 
+bool TemplateParameterList::shouldIncludeTypeForArgument(
+    const TemplateParameterList *TPL, unsigned Idx) {
+  if (!TPL || Idx >= TPL->size())
+    return true;
+  const NamedDecl *TemplParam = TPL->getParam(Idx);
+  if (const auto *ParamValueDecl =
+          dyn_cast<NonTypeTemplateParmDecl>(TemplParam))
+    if (ParamValueDecl->getType()->getContainedDeducedType())
+      return true;
+  return false;
+}
+
 namespace clang {
 
 void *allocateDefaultArgStorageChain(const ASTContext &C) {
@@ -1420,8 +1432,9 @@ void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const {
   ConceptName.printName(OS, Policy);
   if (hasExplicitTemplateArgs()) {
     OS << "<";
+    // FIXME: Find corresponding parameter for argument
     for (auto &ArgLoc : ArgsAsWritten->arguments())
-      ArgLoc.getArgument().print(Policy, OS);
+      ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false);
     OS << ">";
   }
 }
index a4a70be..fe2cdc9 100644 (file)
@@ -32,6 +32,7 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cstring>
@@ -705,7 +706,9 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
         StringRef Param = Params->getParam(i)->getName();
         if (Param.empty()) continue;
         TOut << Param << " = ";
-        Args.get(i).print(Policy, TOut);
+        Args.get(i).print(
+            Policy, TOut,
+            TemplateParameterList::shouldIncludeTypeForArgument(Params, i));
         TOut << ", ";
       }
     }
@@ -721,7 +724,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
         StringRef Param = Params->getParam(i)->getName();
         if (Param.empty()) continue;
         TOut << Param << " = ";
-        Args->get(i).print(Policy, TOut);
+        Args->get(i).print(Policy, TOut, /*IncludeType*/ true);
         TOut << ", ";
       }
     }
@@ -865,6 +868,76 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
   return std::string(S.str());
 }
 
+void CharacterLiteral::print(unsigned Val, CharacterKind Kind,
+                             raw_ostream &OS) {
+  switch (Kind) {
+  case CharacterLiteral::Ascii:
+    break; // no prefix.
+  case CharacterLiteral::Wide:
+    OS << 'L';
+    break;
+  case CharacterLiteral::UTF8:
+    OS << "u8";
+    break;
+  case CharacterLiteral::UTF16:
+    OS << 'u';
+    break;
+  case CharacterLiteral::UTF32:
+    OS << 'U';
+    break;
+  }
+
+  switch (Val) {
+  case '\\':
+    OS << "'\\\\'";
+    break;
+  case '\'':
+    OS << "'\\''";
+    break;
+  case '\a':
+    // TODO: K&R: the meaning of '\\a' is different in traditional C
+    OS << "'\\a'";
+    break;
+  case '\b':
+    OS << "'\\b'";
+    break;
+  // Nonstandard escape sequence.
+  /*case '\e':
+    OS << "'\\e'";
+    break;*/
+  case '\f':
+    OS << "'\\f'";
+    break;
+  case '\n':
+    OS << "'\\n'";
+    break;
+  case '\r':
+    OS << "'\\r'";
+    break;
+  case '\t':
+    OS << "'\\t'";
+    break;
+  case '\v':
+    OS << "'\\v'";
+    break;
+  default:
+    // A character literal might be sign-extended, which
+    // would result in an invalid \U escape sequence.
+    // FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF'
+    // are not correctly handled.
+    if ((Val & ~0xFFu) == ~0xFFu && Kind == CharacterLiteral::Ascii)
+      Val &= 0xFFu;
+    if (Val < 256 && isPrintable((unsigned char)Val))
+      OS << "'" << (char)Val << "'";
+    else if (Val < 256)
+      OS << "'\\x" << llvm::format("%02x", Val) << "'";
+    else if (Val <= 0xFFFF)
+      OS << "'\\u" << llvm::format("%04x", Val) << "'";
+    else
+      OS << "'\\U" << llvm::format("%08x", Val) << "'";
+  }
+}
+
 FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
                                  bool isexact, QualType Type, SourceLocation L)
     : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary), Loc(L) {
index 08e8819..3f8fb7a 100644 (file)
@@ -288,8 +288,9 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
     if (ResolveTemplateArguments && Record) {
         // Print the type trait with resolved template parameters.
         Record->printName(OS);
-        printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
-                                  Policy);
+        printTemplateArgumentList(
+            OS, Record->getTemplateArgs().asArray(), Policy,
+            Record->getSpecializedTemplate()->getTemplateParameters());
         break;
     }
     const Type *T = getAsType();
index 9a7e40f..58afc02 100644 (file)
@@ -51,7 +51,6 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <string>
@@ -1003,8 +1002,13 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
   if (Node->hasTemplateKeyword())
     OS << "template ";
   OS << Node->getNameInfo();
-  if (Node->hasExplicitTemplateArgs())
-    printTemplateArgumentList(OS, Node->template_arguments(), Policy);
+  if (Node->hasExplicitTemplateArgs()) {
+    const TemplateParameterList *TPL = nullptr;
+    if (!Node->hadMultipleCandidates())
+      if (auto *TD = dyn_cast<TemplateDecl>(Node->getDecl()))
+        TPL = TD->getTemplateParameters();
+    printTemplateArgumentList(OS, Node->template_arguments(), Policy, TPL);
+  }
 }
 
 void StmtPrinter::VisitDependentScopeDeclRefExpr(
@@ -1082,65 +1086,7 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
 }
 
 void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
-  unsigned value = Node->getValue();
-
-  switch (Node->getKind()) {
-  case CharacterLiteral::Ascii: break; // no prefix.
-  case CharacterLiteral::Wide:  OS << 'L'; break;
-  case CharacterLiteral::UTF8:  OS << "u8"; break;
-  case CharacterLiteral::UTF16: OS << 'u'; break;
-  case CharacterLiteral::UTF32: OS << 'U'; break;
-  }
-
-  switch (value) {
-  case '\\':
-    OS << "'\\\\'";
-    break;
-  case '\'':
-    OS << "'\\''";
-    break;
-  case '\a':
-    // TODO: K&R: the meaning of '\\a' is different in traditional C
-    OS << "'\\a'";
-    break;
-  case '\b':
-    OS << "'\\b'";
-    break;
-  // Nonstandard escape sequence.
-  /*case '\e':
-    OS << "'\\e'";
-    break;*/
-  case '\f':
-    OS << "'\\f'";
-    break;
-  case '\n':
-    OS << "'\\n'";
-    break;
-  case '\r':
-    OS << "'\\r'";
-    break;
-  case '\t':
-    OS << "'\\t'";
-    break;
-  case '\v':
-    OS << "'\\v'";
-    break;
-  default:
-    // A character literal might be sign-extended, which
-    // would result in an invalid \U escape sequence.
-    // FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF'
-    // are not correctly handled.
-    if ((value & ~0xFFu) == ~0xFFu && Node->getKind() == CharacterLiteral::Ascii)
-      value &= 0xFFu;
-    if (value < 256 && isPrintable((unsigned char)value))
-      OS << "'" << (char)value << "'";
-    else if (value < 256)
-      OS << "'\\x" << llvm::format("%02x", value) << "'";
-    else if (value <= 0xFFFF)
-      OS << "'\\u" << llvm::format("%04x", value) << "'";
-    else
-      OS << "'\\U" << llvm::format("%08x", value) << "'";
-  }
+  CharacterLiteral::print(Node->getValue(), Node->getKind(), OS);
 }
 
 /// Prints the given expression using the original source text. Returns true on
@@ -1466,8 +1412,16 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
   if (Node->hasTemplateKeyword())
     OS << "template ";
   OS << Node->getMemberNameInfo();
+  const TemplateParameterList *TPL = nullptr;
+  if (auto *FD = dyn_cast<FunctionDecl>(Node->getMemberDecl())) {
+    if (!Node->hadMultipleCandidates())
+      if (auto *FTD = FD->getPrimaryTemplate())
+        TPL = FTD->getTemplateParameters();
+  } else if (auto *VTSD =
+                 dyn_cast<VarTemplateSpecializationDecl>(Node->getMemberDecl()))
+    TPL = VTSD->getSpecializedTemplate()->getTemplateParameters();
   if (Node->hasExplicitTemplateArgs())
-    printTemplateArgumentList(OS, Node->template_arguments(), Policy);
+    printTemplateArgumentList(OS, Node->template_arguments(), Policy, TPL);
 }
 
 void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
@@ -1881,8 +1835,12 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
     assert(Args);
 
     if (Args->size() != 1) {
+      const TemplateParameterList *TPL = nullptr;
+      if (!DRE->hadMultipleCandidates())
+        if (const auto *TD = dyn_cast<TemplateDecl>(DRE->getDecl()))
+          TPL = TD->getTemplateParameters();
       OS << "operator\"\"" << Node->getUDSuffix()->getName();
-      printTemplateArgumentList(OS, Args->asArray(), Policy);
+      printTemplateArgumentList(OS, Args->asArray(), Policy, TPL);
       OS << "()";
       return;
     }
@@ -2332,7 +2290,8 @@ void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
     OS << "template ";
   OS << E->getFoundDecl()->getName();
   printTemplateArgumentList(OS, E->getTemplateArgsAsWritten()->arguments(),
-                            Policy);
+                            Policy,
+                            E->getNamedConcept()->getTemplateParameters());
 }
 
 void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) {
index b1816ff..7be72cb 100644 (file)
@@ -50,8 +50,11 @@ using namespace clang;
 /// \param Out the raw_ostream instance to use for printing.
 ///
 /// \param Policy the printing policy for EnumConstantDecl printing.
-static void printIntegral(const TemplateArgument &TemplArg,
-                          raw_ostream &Out, const PrintingPolicy& Policy) {
+///
+/// \param IncludeType If set, ensure that the type of the expression printed
+/// matches the type of the template argument.
+static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
+                          const PrintingPolicy &Policy, bool IncludeType) {
   const Type *T = TemplArg.getIntegralType().getTypePtr();
   const llvm::APSInt &Val = TemplArg.getAsIntegral();
 
@@ -68,16 +71,66 @@ static void printIntegral(const TemplateArgument &TemplArg,
     }
   }
 
-  if (T->isBooleanType() && !Policy.MSVCFormatting) {
-    Out << (Val.getBoolValue() ? "true" : "false");
+  if (Policy.MSVCFormatting)
+    IncludeType = false;
+
+  if (T->isBooleanType()) {
+    if (!Policy.MSVCFormatting)
+      Out << (Val.getBoolValue() ? "true" : "false");
+    else
+      Out << Val;
   } else if (T->isCharType()) {
-    const char Ch = Val.getZExtValue();
-    Out << ((Ch == '\'') ? "'\\" : "'");
-    Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
-    Out << "'";
-  } else {
+    if (IncludeType) {
+      if (T->isSpecificBuiltinType(BuiltinType::SChar))
+        Out << "(signed char)";
+      else if (T->isSpecificBuiltinType(BuiltinType::UChar))
+        Out << "(unsigned char)";
+    }
+    CharacterLiteral::print(Val.getZExtValue(), CharacterLiteral::Ascii, Out);
+  } else if (T->isAnyCharacterType() && !Policy.MSVCFormatting) {
+    CharacterLiteral::CharacterKind Kind;
+    if (T->isWideCharType())
+      Kind = CharacterLiteral::Wide;
+    else if (T->isChar8Type())
+      Kind = CharacterLiteral::UTF8;
+    else if (T->isChar16Type())
+      Kind = CharacterLiteral::UTF16;
+    else if (T->isChar32Type())
+      Kind = CharacterLiteral::UTF32;
+    else
+      Kind = CharacterLiteral::Ascii;
+    CharacterLiteral::print(Val.getExtValue(), Kind, Out);
+  } else if (IncludeType) {
+    if (const auto *BT = T->getAs<BuiltinType>()) {
+      switch (BT->getKind()) {
+      case BuiltinType::ULongLong:
+        Out << Val << "ULL";
+        break;
+      case BuiltinType::LongLong:
+        Out << Val << "LL";
+        break;
+      case BuiltinType::ULong:
+        Out << Val << "UL";
+        break;
+      case BuiltinType::Long:
+        Out << Val << "L";
+        break;
+      case BuiltinType::UInt:
+        Out << Val << "U";
+        break;
+      case BuiltinType::Int:
+        Out << Val;
+        break;
+      default:
+        Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
+            << Val;
+        break;
+      }
+    } else
+      Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
+          << Val;
+  } else
     Out << Val;
-  }
 }
 
 static unsigned getArrayDepth(QualType type) {
@@ -360,8 +413,9 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
   llvm_unreachable("Invalid TemplateArgument Kind!");
 }
 
-void TemplateArgument::print(const PrintingPolicy &Policy,
-                             raw_ostream &Out) const {
+void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
+                             bool IncludeType) const {
+
   switch (getKind()) {
   case Null:
     Out << "(no value)";
@@ -375,10 +429,10 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
   }
 
   case Declaration: {
+    // FIXME: Include the type if it's not obvious from the context.
     NamedDecl *ND = getAsDecl();
     if (getParamTypeForDecl()->isRecordType()) {
       if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
-        // FIXME: Include the type if it's not obvious from the context.
         TPO->printAsInit(Out);
         break;
       }
@@ -392,6 +446,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
   }
 
   case NullPtr:
+    // FIXME: Include the type if it's not obvious from the context.
     Out << "nullptr";
     break;
 
@@ -405,7 +460,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
     break;
 
   case Integral:
-    printIntegral(*this, Out, Policy);
+    printIntegral(*this, Out, Policy, IncludeType);
     break;
 
   case Expression:
@@ -421,7 +476,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
       else
         Out << ", ";
 
-      P.print(Policy, Out);
+      P.print(Policy, Out, IncludeType);
     }
     Out << ">";
     break;
@@ -432,7 +487,7 @@ void TemplateArgument::dump(raw_ostream &Out) const {
   LangOptions LO; // FIXME! see also TemplateName::dump().
   LO.CPlusPlus = true;
   LO.Bool = true;
-  print(PrintingPolicy(LO), Out);
+  print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
 }
 
 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
@@ -527,7 +582,7 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
     LangOptions LangOpts;
     LangOpts.CPlusPlus = true;
     PrintingPolicy Policy(LangOpts);
-    Arg.print(Policy, OS);
+    Arg.print(Policy, OS, /*IncludeType*/ true);
     return DB << OS.str();
   }
   }
index 9000976..59549db 100644 (file)
@@ -1843,16 +1843,17 @@ static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
 }
 
 static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
-                          llvm::raw_ostream &OS) {
-  A.print(PP, OS);
+                          llvm::raw_ostream &OS, bool IncludeType) {
+  A.print(PP, OS, IncludeType);
 }
 
 static void printArgument(const TemplateArgumentLoc &A,
-                          const PrintingPolicy &PP, llvm::raw_ostream &OS) {
+                          const PrintingPolicy &PP, llvm::raw_ostream &OS,
+                          bool IncludeType) {
   const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
   if (Kind == TemplateArgument::ArgKind::Type)
     return A.getTypeSourceInfo()->getType().print(OS, PP);
-  return A.getArgument().print(PP, OS);
+  return A.getArgument().print(PP, OS, IncludeType);
 }
 
 static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
@@ -1989,13 +1990,14 @@ static bool isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
   return false;
 }
 
-template<typename TA>
+template <typename TA>
 static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
                     const PrintingPolicy &Policy, bool SkipBrackets,
-                    const TemplateParameterList *TPL) {
+                    const TemplateParameterList *TPL, bool IsPack,
+                    unsigned ParmIndex) {
   // Drop trailing template arguments that match default arguments.
   if (TPL && Policy.SuppressDefaultTemplateArgs &&
-      !Policy.PrintCanonicalTypes && !Args.empty() &&
+      !Policy.PrintCanonicalTypes && !Args.empty() && !IsPack &&
       Args.size() <= TPL->size()) {
     ASTContext &Ctx = TPL->getParam(0)->getASTContext();
     llvm::SmallVector<TemplateArgument, 8> OrigArgs;
@@ -2022,12 +2024,15 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
     if (Argument.getKind() == TemplateArgument::Pack) {
       if (Argument.pack_size() && !FirstArg)
         OS << Comma;
-      printTo(ArgOS, Argument.getPackAsArray(), Policy, true, nullptr);
+      printTo(ArgOS, Argument.getPackAsArray(), Policy, true, TPL,
+              /*IsPack*/ true, ParmIndex);
     } else {
       if (!FirstArg)
         OS << Comma;
       // Tries to print the argument with location info if exists.
-      printArgument(Arg, Policy, ArgOS);
+      printArgument(
+          Arg, Policy, ArgOS,
+          TemplateParameterList::shouldIncludeTypeForArgument(TPL, ParmIndex));
     }
     StringRef ArgString = ArgOS.str();
 
@@ -2044,6 +2049,10 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
     NeedSpace = Policy.SplitTemplateClosers && !ArgString.empty() &&
                 ArgString.back() == '>';
     FirstArg = false;
+
+    // Use same template parameter for all elements of Pack
+    if (!IsPack)
+      ParmIndex++;
   }
 
   if (NeedSpace)
@@ -2064,14 +2073,14 @@ void clang::printTemplateArgumentList(raw_ostream &OS,
                                       ArrayRef<TemplateArgument> Args,
                                       const PrintingPolicy &Policy,
                                       const TemplateParameterList *TPL) {
-  printTo(OS, Args, Policy, false, TPL);
+  printTo(OS, Args, Policy, false, TPL, /*isPack*/ false, /*parmIndex*/ 0);
 }
 
 void clang::printTemplateArgumentList(raw_ostream &OS,
                                       ArrayRef<TemplateArgumentLoc> Args,
                                       const PrintingPolicy &Policy,
                                       const TemplateParameterList *TPL) {
-  printTo(OS, Args, Policy, false, TPL);
+  printTo(OS, Args, Policy, false, TPL, /*isPack*/ false, /*parmIndex*/ 0);
 }
 
 std::string Qualifiers::getAsString() const {
index b42f47f..ee8185c 100644 (file)
@@ -898,7 +898,7 @@ static void describeTemplateParameter(raw_ostream &Out,
   if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
     describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
   } else {
-    TArg.print(PrintingPolicy(LO), Out);
+    TArg.print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
   }
 }
 
index e166599..1a8ef40 100644 (file)
@@ -976,15 +976,20 @@ static bool checkComplexDecomposition(Sema &S,
 }
 
 static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy,
-                                     TemplateArgumentListInfo &Args) {
+                                     TemplateArgumentListInfo &Args,
+                                     const TemplateParameterList *Params) {
   SmallString<128> SS;
   llvm::raw_svector_ostream OS(SS);
   bool First = true;
+  unsigned I = 0;
   for (auto &Arg : Args.arguments()) {
     if (!First)
       OS << ", ";
-    Arg.getArgument().print(PrintingPolicy, OS);
+    Arg.getArgument().print(
+        PrintingPolicy, OS,
+        TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
     First = false;
+    I++;
   }
   return std::string(OS.str());
 }
@@ -996,7 +1001,7 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
   auto DiagnoseMissing = [&] {
     if (DiagID)
       S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(),
-                                               Args);
+                                               Args, /*Params*/ nullptr);
     return true;
   };
 
@@ -1034,7 +1039,8 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
     if (DiagID)
       S.RequireCompleteType(
           Loc, TraitTy, DiagID,
-          printTemplateArgs(S.Context.getPrintingPolicy(), Args));
+          printTemplateArgs(S.Context.getPrintingPolicy(), Args,
+                            TraitTD->getTemplateParameters()));
     return true;
   }
 
@@ -1089,7 +1095,8 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
     Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
                                                SourceLocation Loc) override {
       return S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
-          << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
+             << printTemplateArgs(S.Context.getPrintingPolicy(), Args,
+                                  /*Params*/ nullptr);
     }
   } Diagnoser(R, Args);
 
@@ -1125,7 +1132,8 @@ static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc,
   if (!TD) {
     R.suppressDiagnostics();
     S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized)
-      << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
+        << printTemplateArgs(S.Context.getPrintingPolicy(), Args,
+                             /*Params*/ nullptr);
     if (!R.empty())
       S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at);
     return QualType();
index a208281..dfd4297 100644 (file)
@@ -3570,7 +3570,9 @@ public:
       OS << VD->getName();
       if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
         // This is a template variable, print the expanded template arguments.
-        printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
+        printTemplateArgumentList(
+            OS, IV->getTemplateArgs().asArray(), Policy,
+            IV->getSpecializedTemplate()->getTemplateParameters());
       }
       return true;
     }
@@ -10908,7 +10910,9 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
     }
 
     Out << " = ";
-    Args[I].print(getPrintingPolicy(), Out);
+    Args[I].print(
+        getPrintingPolicy(), Out,
+        TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
   }
 
   Out << ']';
index 3c66c8e..08e7983 100644 (file)
@@ -4705,10 +4705,9 @@ CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
     llvm::raw_string_ostream OS(Buf);
     OS << "'" << Concept->getName();
     if (TypeLoc.hasExplicitTemplateArgs()) {
-      OS << "<";
-      for (const auto &Arg : Type.getTypeConstraintArguments())
-        Arg.print(S.getPrintingPolicy(), OS);
-      OS << ">";
+      printTemplateArgumentList(
+          OS, Type.getTypeConstraintArguments(), S.getPrintingPolicy(),
+          Type.getTypeConstraintConcept()->getTemplateParameters());
     }
     OS << "'";
     OS.flush();
index 578a77a..a4cbb2e 100644 (file)
@@ -805,9 +805,10 @@ void Sema::PrintInstantiationStack() {
       SmallString<128> TemplateArgsStr;
       llvm::raw_svector_ostream OS(TemplateArgsStr);
       cast<NamedDecl>(Active->Entity)->printName(OS);
-      if (!isa<FunctionDecl>(Active->Entity))
+      if (!isa<FunctionDecl>(Active->Entity)) {
         printTemplateArgumentList(OS, Active->template_arguments(),
                                   getPrintingPolicy());
+      }
       Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
         << Active->InstantiationRange;
       break;
index 57e4c5a..1eec447 100644 (file)
@@ -14,7 +14,7 @@ void func(U param) {
   clang_analyzer_dump(__PRETTY_FUNCTION__);
   // expected-warning@-3 {{&Element{"func",0 S64b,char}}}
   // expected-warning@-3 {{&Element{"func",0 S64b,char}}}
-  // expected-warning@-3 {{&Element{"void func(U) [T = Class, Value = 42, U = char]",0 S64b,char}}}
+  // expected-warning@-3 {{&Element{"void func(U) [T = Class, Value = 42ULL, U = char]",0 S64b,char}}}
 
 #ifdef ANALYZER_MS
   clang_analyzer_dump(__FUNCDNAME__);
@@ -23,8 +23,8 @@ void func(U param) {
   clang_analyzer_dump(L__FUNCSIG__);
   // expected-warning@-4 {{&Element{"??$func@UClass@?1??foo@@YAXXZ@$0CK@D@@YAXD@Z",0 S64b,char}}}
   // expected-warning@-4 {{&Element{L"func",0 S64b,wchar_t}}}
-  // expected-warning@-4 {{&Element{"void __cdecl func(U) [T = Class, Value = 42, U = char]",0 S64b,char}}}
-  // expected-warning@-4 {{&Element{L"void __cdecl func(U) [T = Class, Value = 42, U = char]",0 S64b,wchar_t}}}
+  // expected-warning@-4 {{&Element{"void __cdecl func(U) [T = Class, Value = 42ULL, U = char]",0 S64b,char}}}
+  // expected-warning@-4 {{&Element{L"void __cdecl func(U) [T = Class, Value = 42ULL, U = char]",0 S64b,wchar_t}}}
 #endif
 }
 
index 34a2f5c..75d92a7 100644 (file)
@@ -8,7 +8,8 @@ struct check<char16_t, 34, 1090, 1077, 1089, 1090, 32, 55296, 56320>{};
 template<>
 struct check<char32_t, 34, 1090, 1077, 1089, 1090, 32, 65536>{};
 template<typename T, T... str> int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}}
-    check<T, str...> chars; // expected-error {{implicit instantiation of undefined template 'check<char, 't', 'e', 's', 't'>'}} expected-error {{implicit instantiation of undefined template 'check<char32_t, 34, 1090, 1077, 1089, 1090, 95, 65536>'}}
+    check<T, str...> chars; // expected-error {{implicit instantiation of undefined template 'check<char, 't', 'e', 's', 't'>'}} \
+                            // expected-error {{implicit instantiation of undefined template 'check<char32_t, U'"', U'\u0442', U'\u0435', U'\u0441', U'\u0442', U'_', U'\U00010000'>'}}
     return 1;
 }
 void *operator""_x(const char*); // #2
@@ -18,4 +19,4 @@ int c = u8R"("тест 𐀀)"_x; // ok, calls #1
 int d = "test"_x; // expected-note {{in instantiation of function template specialization 'operator""_x<char, 't', 'e', 's', 't'>' requested here}}
 int e = uR"("тест 𐀀)"_x;
 int f = UR"("тест 𐀀)"_x;
-int g = UR"("тест_𐀀)"_x; // expected-note {{in instantiation of function template specialization 'operator""_x<char32_t, 34, 1090, 1077, 1089, 1090, 95, 65536>' requested here}}
+int g = UR"("тест_𐀀)"_x; // expected-note {{in instantiation of function template specialization 'operator""_x<char32_t, U'"', U'\u0442', U'\u0435', U'\u0441', U'\u0442', U'_', U'\U00010000'>' requested here}}
diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p13.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p13.cpp
new file mode 100644 (file)
index 0000000..1cfe86f
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template <typename T, T... cs> struct check; // expected-note {{template is declared here}}
+template <>
+struct check<char8_t, 34, 209, 130, 208, 181, 209, 129, 209, 130, 32, 240, 144, 128, 128> {};
+template <typename T, T... str> int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}}
+  check<T, str...> chars;                            // expected-error {{implicit instantiation of undefined template 'check<char8_t, u8'"', u8'\xd1', u8'\x82', u8'\xd0', u8'\xb5', u8'\xd1', u8'\x81', u8'\xd1', u8'\x82', u8'_', u8'\xf0', u8'\x90', u8'\x80', u8'\x80'>'}}
+  return 1;
+}
+int a = u8"\"тест 𐀀"_x;
+int b = u8"\"тест_𐀀"_x; // expected-note {{in instantiation of function template specialization 'operator""_x<char8_t, u8'"', u8'\xd1', u8'\x82', u8'\xd0', u8'\xb5', u8'\xd1', u8'\x81', u8'\xd1', u8'\x82', u8'_', u8'\xf0', u8'\x90', u8'\x80', u8'\x80'>' requested here}}
+
+template <auto> struct C{};
+C<u8'x'>::D d; // expected-error {{no type named 'D' in 'C<u8'x'>'}}
diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p14.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p14.cpp
new file mode 100644 (file)
index 0000000..4f0277f
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-unknown-linux %s
+
+template <typename T, T... cs> struct check; // expected-note {{template is declared here}}
+template <>
+struct check<wchar_t, 34, 1090, 1077, 1089, 1090, 32, 65536> {};
+template <typename T, T... str> int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}}
+  check<T, str...> chars;                            // expected-error {{implicit instantiation of undefined template 'check<wchar_t, L'"', L'\u0442', L'\u0435', L'\u0441', L'\u0442', L'_', L'\U00010000'>'}}
+  return 1;
+}
+void *operator""_x(const char *); // #2
+int h = LR"("тест_𐀀)"_x;          // expected-note {{in instantiation of function template specialization 'operator""_x<wchar_t, L'"', L'\u0442', L'\u0435', L'\u0441', L'\u0442', L'_', L'\U00010000'>' requested here}}
diff --git a/clang/test/CodeGenCXX/debug-info-codeview-template-literal.cpp b/clang/test/CodeGenCXX/debug-info-codeview-template-literal.cpp
new file mode 100644 (file)
index 0000000..49827f7
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang -g -std=c++2a -target x86_64-windows-msvc -Wno-gnu-string-literal-operator-template %s -S -emit-llvm -o - | FileCheck %s
+
+template <typename T, T... cs> struct check;
+template <typename T, T... str> int operator""_x() {
+  return 1;
+}
+
+int b = u8"\"тест_𐀀"_x;
+// CHECK: _x<char8_t,34,209,130,208,181,209,129,209,130,95,240,144,128,128>
diff --git a/clang/test/CodeGenCXX/debug-info-codeview-template-type.cpp b/clang/test/CodeGenCXX/debug-info-codeview-template-type.cpp
new file mode 100644 (file)
index 0000000..be37190
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang -std=c++11 -g -target x86_64-windows-msvc -S -emit-llvm -o - %s | FileCheck %s
+
+template <unsigned N>
+void foo() {
+}
+
+void instantiate_foo() {
+  foo<10>();
+  // CHECK: foo<10>
+  foo<true>();
+  // CHECK: foo<1>
+}
index 848ed86..1c05e2f 100644 (file)
@@ -31,10 +31,10 @@ void test_templated_arguments() {
 void test() {
   test_templated_arguments<int, 32>(); // fine
   test_templated_arguments<struct fwddecl, 16>();
-  // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments<fwddecl, 16, 16>'}}
+  // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments<fwddecl, 16L, 16L>'}}
   // expected-note@-2{{forward declaration of 'fwddecl'}}
   test_templated_arguments<int, 7>(); // invalid alignment value
-  // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments<int, 7, 16>'}}
+  // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments<int, 7L, 16L>'}}
 }
 
 template <typename T, long ArraySize>
index 17dcbcb..593c98f 100644 (file)
@@ -40,7 +40,7 @@ const char *p9 = 0x42e3F_fritz;
 const char *p10 = 3.300e+15_fritz;
 
 template <class C, C...> const char *operator"" _suffix();
-// CHECK: const char *PR23120 = operator""_suffix<char32_t, 66615>();
+// CHECK: const char *PR23120 = operator""_suffix<char32_t, U'\U00010437'>();
 const char *PR23120 = U"𐐷"_suffix;
 
 // PR28885
diff --git a/clang/test/SemaCXX/cxx1z-ast-print.cpp b/clang/test/SemaCXX/cxx1z-ast-print.cpp
new file mode 100644 (file)
index 0000000..42b3cd3
--- /dev/null
@@ -0,0 +1,11 @@
+//RUN: %clang_cc1 -std=c++1z -verify -ast-print %s | FileCheck %s
+
+struct TypeSuffix {
+  template <long> static int x; // expected-note {{forward declaration of template entity is here}}
+  template <auto> static int y; // expected-note {{forward declaration of template entity is here}}
+};
+// CHECK: int k = TypeSuffix().x + TypeSuffix().y;
+int k = TypeSuffix().x<0L> + TypeSuffix().y<0L>; // expected-warning {{instantiation of variable 'TypeSuffix::x<0>' required here, but no definition is available}} \
+                                                 // expected-note {{add an explicit instantiation declaration to suppress this warning if 'TypeSuffix::x<0>' is explicitly instantiated in another translation unit}} \
+                                                 // expected-warning {{instantiation of variable 'TypeSuffix::y<0L>' required here, but no definition is available}} \
+                                                 // expected-note {{add an explicit instantiation declaration to suppress this warning if 'TypeSuffix::y<0L>' is explicitly instantiated in another translation unit}}
index fce4d6f..97aa046 100644 (file)
@@ -30,14 +30,14 @@ void test_transpose_template(unsigned *Ptr1, float *Ptr2) {
   MyMatrix<unsigned, 3, 3> Mat2;
   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
   Mat1.value = transpose<unsigned, 2, 3, unsigned, 2, 3>(Mat1);
-  // expected-note@-1 {{in instantiation of function template specialization 'transpose<unsigned int, 2, 3, unsigned int, 2, 3>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'transpose<unsigned int, 2U, 3U, unsigned int, 2U, 3U>' requested here}}
 
   Mat1.value = transpose<unsigned, 3, 3, unsigned, 2, 3>(Mat2);
-  // expected-note@-1 {{in instantiation of function template specialization 'transpose<unsigned int, 3, 3, unsigned int, 2, 3>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'transpose<unsigned int, 3U, 3U, unsigned int, 2U, 3U>' requested here}}
 
   MyMatrix<float, 3, 3> Mat3;
   Mat3.value = transpose<unsigned, 3, 3, float, 3, 3>(Mat2);
-  // expected-note@-1 {{in instantiation of function template specialization 'transpose<unsigned int, 3, 3, float, 3, 3>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'transpose<unsigned int, 3U, 3U, float, 3U, 3U>' requested here}}
 }
 
 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1>
@@ -55,13 +55,13 @@ typename MyMatrix<EltTy1, R1, C1>::matrix_t column_major_load(MyMatrix<EltTy0, R
 void test_column_major_loads_template(unsigned *Ptr1, float *Ptr2) {
   MyMatrix<unsigned, 2, 3> Mat1;
   Mat1.value = column_major_load<unsigned, 2, 3, unsigned, 2, 3>(Mat1, Ptr1);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_load<unsigned int, 2, 3, unsigned int, 2, 3>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_load<unsigned int, 2U, 3U, unsigned int, 2U, 3U>' requested here}}
   column_major_load<unsigned, 2, 3, unsigned, 5, 5>(Mat1, Ptr1);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_load<unsigned int, 2, 3, unsigned int, 5, 5>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_load<unsigned int, 2U, 3U, unsigned int, 5U, 5U>' requested here}}
 
   MyMatrix<float, 2, 3> Mat2;
   Mat1.value = column_major_load<float, 2, 3, unsigned, 2, 3>(Mat2, Ptr2);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_load<float, 2, 3, unsigned int, 2, 3>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_load<float, 2U, 3U, unsigned int, 2U, 3U>' requested here}}
 }
 
 constexpr int constexpr1() { return 1; }
@@ -116,10 +116,10 @@ void column_major_store(MTy &A, PtrTy Ptr) {
 
 void test_column_major_stores_template(MyMatrix<unsigned, 2, 3> &M1, unsigned *Ptr1, MyMatrix<float, 3, 4> &M2, float *Ptr2) {
   column_major_store(M1, Ptr2, 10);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<unsigned int, 2, 3, float *>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<unsigned int, 2U, 3U, float *>' requested here}}
 
   column_major_store<decltype(M2), float *, 1>(M2, Ptr2);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<MyMatrix<float, 3, 4> &, float *, 1>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<MyMatrix<float, 3, 4> &, float *, 1U>' requested here}}
 }
 
 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1>
@@ -139,13 +139,13 @@ void column_major_store(MyMatrix<EltTy0, R0, C0> &A, EltTy1 *Ptr) {
 void test_column_major_store_template(unsigned *Ptr1, float *Ptr2) {
   MyMatrix<unsigned, 2, 3> Mat1;
   column_major_store<unsigned, 2, 3, unsigned>(Mat1, Ptr1);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<unsigned int, 2, 3, unsigned int>'}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<unsigned int, 2U, 3U, unsigned int>'}}
   column_major_store<unsigned, 2, 3, float>(Mat1, Ptr2);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<unsigned int, 2, 3, float>'}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<unsigned int, 2U, 3U, float>'}}
 
   MyMatrix<float, 2, 3> Mat2;
   column_major_store<float, 2, 3, unsigned>(Mat2, Ptr1);
-  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<float, 2, 3, unsigned int>'}}
+  // expected-note@-1 {{in instantiation of function template specialization 'column_major_store<float, 2U, 3U, unsigned int>'}}
 }
 
 void test_column_major_store_constexpr(unsigned *Ptr, MyMatrix<unsigned, 3, 3> &M) {
index 808e474..52aa0ba 100644 (file)
@@ -28,13 +28,13 @@ void test_add_template(unsigned *Ptr1, float *Ptr2) {
   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
   unsigned v1 = add<unsigned, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat1, Mat1);
   // expected-error@-1 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix<unsigned int, 2U, 2U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
-  // expected-note@-2 {{in instantiation of function template specialization 'add<unsigned int, 2, 2, unsigned int, 2, 2, unsigned int, 2, 2>' requested here}}
+  // expected-note@-2 {{in instantiation of function template specialization 'add<unsigned int, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
 
   Mat1.value = add<unsigned, 2, 2, unsigned, 3, 3, unsigned, 2, 2>(Mat1, Mat2);
-  // expected-note@-1 {{in instantiation of function template specialization 'add<unsigned int, 2, 2, unsigned int, 3, 3, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'add<unsigned int, 2U, 2U, unsigned int, 3U, 3U, unsigned int, 2U, 2U>' requested here}}
 
   Mat1.value = add<unsigned, 3, 3, float, 2, 2, unsigned, 2, 2>(Mat2, Mat3);
-  // expected-note@-1 {{in instantiation of function template specialization 'add<unsigned int, 3, 3, float, 2, 2, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'add<unsigned int, 3U, 3U, float, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
 }
 
 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1, typename EltTy2, unsigned R2, unsigned C2>
@@ -56,13 +56,13 @@ void test_subtract_template(unsigned *Ptr1, float *Ptr2) {
   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
   unsigned v1 = subtract<unsigned, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat1, Mat1);
   // expected-error@-1 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix<unsigned int, 2U, 2U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
-  // expected-note@-2 {{in instantiation of function template specialization 'subtract<unsigned int, 2, 2, unsigned int, 2, 2, unsigned int, 2, 2>' requested here}}
+  // expected-note@-2 {{in instantiation of function template specialization 'subtract<unsigned int, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
 
   Mat1.value = subtract<unsigned, 2, 2, unsigned, 3, 3, unsigned, 2, 2>(Mat1, Mat2);
-  // expected-note@-1 {{in instantiation of function template specialization 'subtract<unsigned int, 2, 2, unsigned int, 3, 3, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'subtract<unsigned int, 2U, 2U, unsigned int, 3U, 3U, unsigned int, 2U, 2U>' requested here}}
 
   Mat1.value = subtract<unsigned, 3, 3, float, 2, 2, unsigned, 2, 2>(Mat2, Mat3);
-  // expected-note@-1 {{in instantiation of function template specialization 'subtract<unsigned int, 3, 3, float, 2, 2, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'subtract<unsigned int, 3U, 3U, float, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
 }
 
 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1, typename EltTy2, unsigned R2, unsigned C2>
@@ -89,15 +89,15 @@ void test_multiply_template(unsigned *Ptr1, float *Ptr2) {
   MyMatrix<float, 2, 2> Mat3;
   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
   unsigned v1 = multiply<unsigned, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat1, Mat1);
-  // expected-note@-1 {{in instantiation of function template specialization 'multiply<unsigned int, 2, 2, unsigned int, 2, 2, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'multiply<unsigned int, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
   // expected-error@-2 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix<unsigned int, 2U, 2U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
 
   MyMatrix<unsigned, 3, 2> Mat4;
   Mat1.value = multiply<unsigned, 3, 2, unsigned, 3, 3, unsigned, 2, 2>(Mat4, Mat2);
-  // expected-note@-1 {{in instantiation of function template specialization 'multiply<unsigned int, 3, 2, unsigned int, 3, 3, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'multiply<unsigned int, 3U, 2U, unsigned int, 3U, 3U, unsigned int, 2U, 2U>' requested here}}
 
   Mat1.value = multiply<float, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat3, Mat1);
-  // expected-note@-1 {{in instantiation of function template specialization 'multiply<float, 2, 2, unsigned int, 2, 2, unsigned int, 2, 2>' requested here}}
+  // expected-note@-1 {{in instantiation of function template specialization 'multiply<float, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
 
   Mat4.value = Mat4.value * Mat1;
   // expected-error@-1 {{no viable conversion from 'MyMatrix<unsigned int, 2, 2>' to 'unsigned int'}}
index a42e4da..821703b 100644 (file)
@@ -102,7 +102,7 @@ int main() {
   HasASTemplateFields<1> HASTF;
   neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}}
   correct<0x7FFFED>();
-  tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650>' requested here}}
+  tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650L>' requested here}}
 
   __attribute__((address_space(1))) char *x;
   __attribute__((address_space(2))) char *y;
diff --git a/clang/test/SemaTemplate/default-arguments-ast-print.cpp b/clang/test/SemaTemplate/default-arguments-ast-print.cpp
new file mode 100644 (file)
index 0000000..9ed17a7
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -ast-print %s | FileCheck %s
+
+template <typename T, typename U = double> class Foo;
+
+template <> class Foo<int, double> { int method1(); };
+
+using int_type = int;
+
+int Foo<int_type, double>::method1() {
+  // CHECK: int Foo<int_type, double>::method1()
+  return 10;
+}
index 852b89d..db3939d 100644 (file)
@@ -9,7 +9,7 @@ namespace PR10457 {
   public:
     template <unsigned N>
     string(const char (&str)[N])
-      : string(str) {} // expected-error{{constructor for 'string<6>' creates a delegation cycle}}
+      : string(str) {} // expected-error{{constructor for 'string<6U>' creates a delegation cycle}}
   };
 
   void f() {
index 0ced57c..1843c0a 100644 (file)
@@ -17,7 +17,7 @@ void matrix_template_3() {
 
 void instantiate_template_3() {
   matrix_template_3<1, 10>();
-  matrix_template_3<0, 10>(); // expected-note{{in instantiation of function template specialization 'matrix_template_3<0, 10>' requested here}}
+  matrix_template_3<0, 10>(); // expected-note{{in instantiation of function template specialization 'matrix_template_3<0U, 10U>' requested here}}
 }
 
 template <int Rows, unsigned Cols>
@@ -27,7 +27,7 @@ void matrix_template_4() {
 
 void instantiate_template_4() {
   matrix_template_4<2, 10>();
-  matrix_template_4<-3, 10>(); // expected-note{{in instantiation of function template specialization 'matrix_template_4<-3, 10>' requested here}}
+  matrix_template_4<-3, 10>(); // expected-note{{in instantiation of function template specialization 'matrix_template_4<-3, 10U>' requested here}}
 }
 
 template <class T, unsigned long R, unsigned long C>
index dbb4db8..c5570af 100644 (file)
@@ -17,7 +17,7 @@ void test() {
   NamedEnumNS::foo<Val0>();
   // CHECK: template<> void foo<NamedEnumNS::Val1>()
   NamedEnumNS::foo<(NamedEnum)1>();
-  // CHECK: template<> void foo<2>()
+  // CHECK: template<> void foo<(NamedEnumNS::NamedEnum)2>()
   NamedEnumNS::foo<(NamedEnum)2>();
 }
   
index 2be815d..a735e92 100644 (file)
@@ -270,6 +270,23 @@ namespace PR9227 {
   void test_char_possibly_negative() { enable_if_char<'\x02'>::type i; } // expected-error{{enable_if_char<'\x02'>'; did you mean 'enable_if_char<'a'>::type'?}}
   void test_char_single_quote() { enable_if_char<'\''>::type i; } // expected-error{{enable_if_char<'\''>'; did you mean 'enable_if_char<'a'>::type'?}}
   void test_char_backslash() { enable_if_char<'\\'>::type i; } // expected-error{{enable_if_char<'\\'>'; did you mean 'enable_if_char<'a'>::type'?}}
+
+  template <int N> struct enable_if_int {};
+  template <> struct enable_if_int<1> { typedef int type; }; // expected-note{{'enable_if_int<1>::type' declared here}}
+  void test_int() { enable_if_int<2>::type i; } // expected-error{{enable_if_int<2>'; did you mean 'enable_if_int<1>::type'?}}
+
+  template <unsigned int N> struct enable_if_unsigned_int {};
+  template <> struct enable_if_unsigned_int<1> { typedef int type; }; // expected-note{{'enable_if_unsigned_int<1>::type' declared here}}
+  void test_unsigned_int() { enable_if_unsigned_int<2>::type i; } // expected-error{{enable_if_unsigned_int<2>'; did you mean 'enable_if_unsigned_int<1>::type'?}}
+
+  template <unsigned long long N> struct enable_if_unsigned_long_long {};
+  template <> struct enable_if_unsigned_long_long<1> { typedef int type; }; // expected-note{{'enable_if_unsigned_long_long<1>::type' declared here}}
+  void test_unsigned_long_long() { enable_if_unsigned_long_long<2>::type i; } // expected-error{{enable_if_unsigned_long_long<2>'; did you mean 'enable_if_unsigned_long_long<1>::type'?}}
+
+  template <long long N> struct enable_if_long_long {};
+  template <> struct enable_if_long_long<1> { typedef int type; }; // expected-note{{'enable_if_long_long<1>::type' declared here}}
+  void test_long_long() { enable_if_long_long<2>::type i; } // expected-error{{enable_if_long_long<2>'; did you mean 'enable_if_long_long<1>::type'?}}
+
 }
 
 namespace PR10579 {
index 245504f..cfb5bba 100644 (file)
@@ -528,3 +528,33 @@ namespace decay {
     x1.f(x2);
   }
 }
+
+namespace TypeSuffix {
+  template <auto N> struct A {};
+  template <> struct A<1> { using type = int; }; // expected-note {{'A<1>::type' declared here}}
+  A<1L>::type a;                                 // expected-error {{no type named 'type' in 'TypeSuffix::A<1L>'; did you mean 'A<1>::type'?}}
+
+  template <auto N> struct B {};
+  template <> struct B<1> { using type = int; }; // expected-note {{'B<1>::type' declared here}}
+  B<2>::type b;                                  // expected-error {{no type named 'type' in 'TypeSuffix::B<2>'; did you mean 'B<1>::type'?}}
+
+  template <auto N> struct C {};
+  template <> struct C<'a'> { using type = signed char; }; // expected-note {{'C<'a'>::type' declared here}}
+  C<(signed char)'a'>::type c;                             // expected-error {{no type named 'type' in 'TypeSuffix::C<(signed char)'a'>'; did you mean 'C<'a'>::type'?}}
+
+  template <auto N> struct D {};
+  template <> struct D<'a'> { using type = signed char; }; // expected-note {{'D<'a'>::type' declared here}}
+  D<'b'>::type d;                                          // expected-error {{no type named 'type' in 'TypeSuffix::D<'b'>'; did you mean 'D<'a'>::type'?}}
+
+  template <auto N> struct E {};
+  template <> struct E<'a'> { using type = unsigned char; }; // expected-note {{'E<'a'>::type' declared here}}
+  E<(unsigned char)'a'>::type e;                             // expected-error {{no type named 'type' in 'TypeSuffix::E<(unsigned char)'a'>'; did you mean 'E<'a'>::type'?}}
+
+  template <auto N> struct F {};
+  template <> struct F<'a'> { using type = unsigned char; }; // expected-note {{'F<'a'>::type' declared here}}
+  F<'b'>::type f;                                            // expected-error {{no type named 'type' in 'TypeSuffix::F<'b'>'; did you mean 'F<'a'>::type'?}}
+
+  template <auto... N> struct X {};
+  X<1, 1u>::type y; // expected-error {{no type named 'type' in 'TypeSuffix::X<1, 1U>'}}
+  X<1, 1>::type z; // expected-error {{no type named 'type' in 'TypeSuffix::X<1, 1>'}}
+}
index a6a9cfc..5ce74e5 100644 (file)
@@ -5185,8 +5185,9 @@ CXString clang_getCursorDisplayName(CXCursor C) {
     SmallString<128> Str;
     llvm::raw_svector_ostream OS(Str);
     OS << *ClassSpec;
-    printTemplateArgumentList(OS, ClassSpec->getTemplateArgs().asArray(),
-                              Policy);
+    printTemplateArgumentList(
+        OS, ClassSpec->getTemplateArgs().asArray(), Policy,
+        ClassSpec->getSpecializedTemplate()->getTemplateParameters());
     return cxstring::createDup(OS.str());
   }
 
index ae427a0..5eee19f 100644 (file)
@@ -20,7 +20,7 @@ public:
     llvm::raw_string_ostream Stream(ArgStr);
     const TemplateArgument &Arg = ArgLoc.getArgument();
 
-    Arg.print(Context->getPrintingPolicy(), Stream);
+    Arg.print(Context->getPrintingPolicy(), Stream, /*IncludeType*/ true);
     Match(Stream.str(), ArgLoc.getLocation());
     return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
       TraverseTemplateArgumentLoc(ArgLoc);