From 99d63ccff04b672694f8a2b3eed024b873dc163d Mon Sep 17 00:00:00 2001 From: Pratyush Das Date: Wed, 12 May 2021 17:28:41 +0000 Subject: [PATCH] Add type information to integral template argument if required. 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 --- clang-tools-extra/clangd/Hover.cpp | 3 +- clang/include/clang/AST/DeclTemplate.h | 3 + clang/include/clang/AST/Expr.h | 2 + clang/include/clang/AST/StmtDataCollectors.td | 2 +- clang/include/clang/AST/TemplateBase.h | 3 +- clang/lib/AST/ASTTypeTraits.cpp | 4 +- clang/lib/AST/DeclPrinter.cpp | 43 +++++++-- clang/lib/AST/DeclTemplate.cpp | 15 +++- clang/lib/AST/Expr.cpp | 77 +++++++++++++++- clang/lib/AST/NestedNameSpecifier.cpp | 5 +- clang/lib/AST/StmtPrinter.cpp | 89 +++++-------------- clang/lib/AST/TemplateBase.cpp | 89 +++++++++++++++---- clang/lib/AST/TypePrinter.cpp | 31 ++++--- clang/lib/Analysis/PathDiagnostic.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp | 20 +++-- clang/lib/Sema/SemaTemplate.cpp | 8 +- clang/lib/Sema/SemaTemplateDeduction.cpp | 7 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 3 +- clang/test/Analysis/eval-predefined-exprs.cpp | 6 +- .../test/CXX/lex/lex.literal/lex.ext/p12.cpp | 5 +- .../test/CXX/lex/lex.literal/lex.ext/p13.cpp | 14 +++ .../test/CXX/lex/lex.literal/lex.ext/p14.cpp | 11 +++ .../debug-info-codeview-template-literal.cpp | 9 ++ .../debug-info-codeview-template-type.cpp | 12 +++ clang/test/SemaCXX/builtin-align-cxx.cpp | 4 +- clang/test/SemaCXX/cxx11-ast-print.cpp | 2 +- clang/test/SemaCXX/cxx1z-ast-print.cpp | 11 +++ clang/test/SemaCXX/matrix-type-builtins.cpp | 22 ++--- clang/test/SemaCXX/matrix-type-operators.cpp | 18 ++-- .../SemaTemplate/address_space-dependent.cpp | 2 +- .../default-arguments-ast-print.cpp | 12 +++ .../SemaTemplate/delegating-constructors.cpp | 2 +- clang/test/SemaTemplate/matrix-type.cpp | 4 +- .../SemaTemplate/temp_arg_enum_printing.cpp | 2 +- clang/test/SemaTemplate/temp_arg_nontype.cpp | 17 ++++ .../SemaTemplate/temp_arg_nontype_cxx1z.cpp | 30 +++++++ clang/tools/libclang/CIndex.cpp | 5 +- .../TemplateArgumentLocTraverser.cpp | 2 +- 38 files changed, 434 insertions(+), 162 deletions(-) create mode 100644 clang/test/CXX/lex/lex.literal/lex.ext/p13.cpp create mode 100644 clang/test/CXX/lex/lex.literal/lex.ext/p14.cpp create mode 100644 clang/test/CodeGenCXX/debug-info-codeview-template-literal.cpp create mode 100644 clang/test/CodeGenCXX/debug-info-codeview-template-type.cpp create mode 100644 clang/test/SemaCXX/cxx1z-ast-print.cpp create mode 100644 clang/test/SemaTemplate/default-arguments-ast-print.cpp diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index c58dab22f8a3..3651a3446fed 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -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)); diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 7fbf6294970e..0cd8f00c623b 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -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 diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index a44d06967431..589199dbcdca 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -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()); diff --git a/clang/include/clang/AST/StmtDataCollectors.td b/clang/include/clang/AST/StmtDataCollectors.td index 7cb9f16fbce2..922dd2a20d59 100644 --- a/clang/include/clang/AST/StmtDataCollectors.td +++ b/clang/include/clang/AST/StmtDataCollectors.td @@ -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()' != 'foo()'. OS << '\n'; } diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index 19f2cadc1f2b..fa27a12cfbb9 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -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; diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp index 8f9ceea656a3..4a033bf50bd4 100644 --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -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()) - TA->print(PP, OS); + TA->print(PP, OS, /*IncludeType*/ true); else if (const TemplateArgumentLoc *TAL = get()) - TAL->getArgument().print(PP, OS); + TAL->getArgument().print(PP, OS, /*IncludeType*/ true); else if (const TemplateName *TN = get()) TN->print(OS, PP); else if (const NestedNameSpecifier *NNS = get()) diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 7ba31c4a7057..90391cab08d6 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -110,8 +110,12 @@ namespace { void printTemplateParameters(const TemplateParameterList *Params, bool OmitTemplateKW = false); - void printTemplateArguments(llvm::ArrayRef Args); - void printTemplateArguments(llvm::ArrayRef Args); + void printTemplateArguments(llvm::ArrayRef Args, + const TemplateParameterList *Params, + bool TemplOverloaded); + void printTemplateArguments(llvm::ArrayRef 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(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 Args) { +void DeclPrinter::printTemplateArguments(ArrayRef 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 Args) { +void DeclPrinter::printTemplateArguments(ArrayRef 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 << ">"; } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 25235c56ec46..4b3a4062d642 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -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(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 << ">"; } } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index a4a70befbdb3..fe2cdc91fb27 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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 #include @@ -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) { diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index 08e8819a4d69..3f8fb7aa8553 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -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(); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 9a7e40fd88e0..58afc020f457 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -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 #include @@ -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(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(Node->getMemberDecl())) { + if (!Node->hadMultipleCandidates()) + if (auto *FTD = FD->getPrimaryTemplate()) + TPL = FTD->getTemplateParameters(); + } else if (auto *VTSD = + dyn_cast(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(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) { diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index b1816ff8aeb1..7be72cb2c0cb 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -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()) { + 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(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(); } } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 9000976fb48e..59549dbfba2b 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -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 +template static void printTo(raw_ostream &OS, ArrayRef 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 OrigArgs; @@ -2022,12 +2024,15 @@ static void printTo(raw_ostream &OS, ArrayRef 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 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 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 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 { diff --git a/clang/lib/Analysis/PathDiagnostic.cpp b/clang/lib/Analysis/PathDiagnostic.cpp index b42f47fb68c5..ee8185c2147c 100644 --- a/clang/lib/Analysis/PathDiagnostic.cpp +++ b/clang/lib/Analysis/PathDiagnostic.cpp @@ -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); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e1665997729d..1a8ef40aa86b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a2082814a4e8..dfd4297bbc8b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3570,7 +3570,9 @@ public: OS << VD->getName(); if (const auto *IV = dyn_cast(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 << ']'; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 3c66c8eeda8b..08e798304b0c 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 578a77aceeda..a4cbb2e8e9d5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -805,9 +805,10 @@ void Sema::PrintInstantiationStack() { SmallString<128> TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); cast(Active->Entity)->printName(OS); - if (!isa(Active->Entity)) + if (!isa(Active->Entity)) { printTemplateArgumentList(OS, Active->template_arguments(), getPrintingPolicy()); + } Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str() << Active->InstantiationRange; break; diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp index 57e4c5ad2ace..1eec4476a065 100644 --- a/clang/test/Analysis/eval-predefined-exprs.cpp +++ b/clang/test/Analysis/eval-predefined-exprs.cpp @@ -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 } diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p12.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p12.cpp index 34a2f5c67820..75d92a7dfd78 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p12.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p12.cpp @@ -8,7 +8,8 @@ struct check{}; template<> struct check{}; template int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}} - check chars; // expected-error {{implicit instantiation of undefined template 'check'}} expected-error {{implicit instantiation of undefined template 'check'}} + check chars; // expected-error {{implicit instantiation of undefined template 'check'}} \ + // expected-error {{implicit instantiation of undefined template 'check'}} 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' requested here}} int e = uR"("ั‚ะตัั‚ ๐€€)"_x; int f = UR"("ั‚ะตัั‚ ๐€€)"_x; -int g = UR"("ั‚ะตัั‚_๐€€)"_x; // expected-note {{in instantiation of function template specialization 'operator""_x' requested here}} +int g = UR"("ั‚ะตัั‚_๐€€)"_x; // expected-note {{in instantiation of function template specialization 'operator""_x' 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 index 000000000000..1cfe86f79c35 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p13.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +template struct check; // expected-note {{template is declared here}} +template <> +struct check {}; +template int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}} + check chars; // expected-error {{implicit instantiation of undefined template 'check'}} + return 1; +} +int a = u8"\"ั‚ะตัั‚ ๐€€"_x; +int b = u8"\"ั‚ะตัั‚_๐€€"_x; // expected-note {{in instantiation of function template specialization 'operator""_x' requested here}} + +template struct C{}; +C::D d; // expected-error {{no type named 'D' in 'C'}} 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 index 000000000000..4f0277f483eb --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p14.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-unknown-linux %s + +template struct check; // expected-note {{template is declared here}} +template <> +struct check {}; +template int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}} + check chars; // expected-error {{implicit instantiation of undefined template 'check'}} + return 1; +} +void *operator""_x(const char *); // #2 +int h = LR"("ั‚ะตัั‚_๐€€)"_x; // expected-note {{in instantiation of function template specialization 'operator""_x' 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 index 000000000000..49827f70c063 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-codeview-template-literal.cpp @@ -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 struct check; +template int operator""_x() { + return 1; +} + +int b = u8"\"ั‚ะตัั‚_๐€€"_x; +// CHECK: _x 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 index 000000000000..be371904ac57 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-codeview-template-type.cpp @@ -0,0 +1,12 @@ +// RUN: %clang -std=c++11 -g -target x86_64-windows-msvc -S -emit-llvm -o - %s | FileCheck %s + +template +void foo() { +} + +void instantiate_foo() { + foo<10>(); + // CHECK: foo<10> + foo(); + // CHECK: foo<1> +} diff --git a/clang/test/SemaCXX/builtin-align-cxx.cpp b/clang/test/SemaCXX/builtin-align-cxx.cpp index 848ed86525bb..1c05e2f10160 100644 --- a/clang/test/SemaCXX/builtin-align-cxx.cpp +++ b/clang/test/SemaCXX/builtin-align-cxx.cpp @@ -31,10 +31,10 @@ void test_templated_arguments() { void test() { test_templated_arguments(); // fine test_templated_arguments(); - // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments'}} + // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments'}} // expected-note@-2{{forward declaration of 'fwddecl'}} test_templated_arguments(); // invalid alignment value - // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments'}} + // expected-note@-1{{in instantiation of function template specialization 'test_templated_arguments'}} } template diff --git a/clang/test/SemaCXX/cxx11-ast-print.cpp b/clang/test/SemaCXX/cxx11-ast-print.cpp index 17dcbcb3f7b0..593c98f8d15f 100644 --- a/clang/test/SemaCXX/cxx11-ast-print.cpp +++ b/clang/test/SemaCXX/cxx11-ast-print.cpp @@ -40,7 +40,7 @@ const char *p9 = 0x42e3F_fritz; const char *p10 = 3.300e+15_fritz; template const char *operator"" _suffix(); -// CHECK: const char *PR23120 = operator""_suffix(); +// CHECK: const char *PR23120 = operator""_suffix(); 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 index 000000000000..42b3cd35713d --- /dev/null +++ b/clang/test/SemaCXX/cxx1z-ast-print.cpp @@ -0,0 +1,11 @@ +//RUN: %clang_cc1 -std=c++1z -verify -ast-print %s | FileCheck %s + +struct TypeSuffix { + template static int x; // expected-note {{forward declaration of template entity is here}} + template 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}} diff --git a/clang/test/SemaCXX/matrix-type-builtins.cpp b/clang/test/SemaCXX/matrix-type-builtins.cpp index fce4d6fb2162..97aa046241c5 100644 --- a/clang/test/SemaCXX/matrix-type-builtins.cpp +++ b/clang/test/SemaCXX/matrix-type-builtins.cpp @@ -30,14 +30,14 @@ void test_transpose_template(unsigned *Ptr1, float *Ptr2) { MyMatrix Mat2; Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1); Mat1.value = transpose(Mat1); - // expected-note@-1 {{in instantiation of function template specialization 'transpose' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'transpose' requested here}} Mat1.value = transpose(Mat2); - // expected-note@-1 {{in instantiation of function template specialization 'transpose' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'transpose' requested here}} MyMatrix Mat3; Mat3.value = transpose(Mat2); - // expected-note@-1 {{in instantiation of function template specialization 'transpose' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'transpose' requested here}} } template @@ -55,13 +55,13 @@ typename MyMatrix::matrix_t column_major_load(MyMatrix Mat1; Mat1.value = column_major_load(Mat1, Ptr1); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_load' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_load' requested here}} column_major_load(Mat1, Ptr1); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_load' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_load' requested here}} MyMatrix Mat2; Mat1.value = column_major_load(Mat2, Ptr2); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_load' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_load' 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 &M1, unsigned *Ptr1, MyMatrix &M2, float *Ptr2) { column_major_store(M1, Ptr2, 10); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_store' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_store' requested here}} column_major_store(M2, Ptr2); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_store &, float *, 1>' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_store &, float *, 1U>' requested here}} } template @@ -139,13 +139,13 @@ void column_major_store(MyMatrix &A, EltTy1 *Ptr) { void test_column_major_store_template(unsigned *Ptr1, float *Ptr2) { MyMatrix Mat1; column_major_store(Mat1, Ptr1); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_store'}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_store'}} column_major_store(Mat1, Ptr2); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_store'}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_store'}} MyMatrix Mat2; column_major_store(Mat2, Ptr1); - // expected-note@-1 {{in instantiation of function template specialization 'column_major_store'}} + // expected-note@-1 {{in instantiation of function template specialization 'column_major_store'}} } void test_column_major_store_constexpr(unsigned *Ptr, MyMatrix &M) { diff --git a/clang/test/SemaCXX/matrix-type-operators.cpp b/clang/test/SemaCXX/matrix-type-operators.cpp index 808e47451461..52aa0bad3459 100644 --- a/clang/test/SemaCXX/matrix-type-operators.cpp +++ b/clang/test/SemaCXX/matrix-type-operators.cpp @@ -28,13 +28,13 @@ void test_add_template(unsigned *Ptr1, float *Ptr2) { Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1); unsigned v1 = add(Mat1, Mat1); // expected-error@-1 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}} - // expected-note@-2 {{in instantiation of function template specialization 'add' requested here}} + // expected-note@-2 {{in instantiation of function template specialization 'add' requested here}} Mat1.value = add(Mat1, Mat2); - // expected-note@-1 {{in instantiation of function template specialization 'add' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'add' requested here}} Mat1.value = add(Mat2, Mat3); - // expected-note@-1 {{in instantiation of function template specialization 'add' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'add' requested here}} } template @@ -56,13 +56,13 @@ void test_subtract_template(unsigned *Ptr1, float *Ptr2) { Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1); unsigned v1 = subtract(Mat1, Mat1); // expected-error@-1 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}} - // expected-note@-2 {{in instantiation of function template specialization 'subtract' requested here}} + // expected-note@-2 {{in instantiation of function template specialization 'subtract' requested here}} Mat1.value = subtract(Mat1, Mat2); - // expected-note@-1 {{in instantiation of function template specialization 'subtract' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'subtract' requested here}} Mat1.value = subtract(Mat2, Mat3); - // expected-note@-1 {{in instantiation of function template specialization 'subtract' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'subtract' requested here}} } template @@ -89,15 +89,15 @@ void test_multiply_template(unsigned *Ptr1, float *Ptr2) { MyMatrix Mat3; Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1); unsigned v1 = multiply(Mat1, Mat1); - // expected-note@-1 {{in instantiation of function template specialization 'multiply' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'multiply' requested here}} // expected-error@-2 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}} MyMatrix Mat4; Mat1.value = multiply(Mat4, Mat2); - // expected-note@-1 {{in instantiation of function template specialization 'multiply' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'multiply' requested here}} Mat1.value = multiply(Mat3, Mat1); - // expected-note@-1 {{in instantiation of function template specialization 'multiply' requested here}} + // expected-note@-1 {{in instantiation of function template specialization 'multiply' requested here}} Mat4.value = Mat4.value * Mat1; // expected-error@-1 {{no viable conversion from 'MyMatrix' to 'unsigned int'}} diff --git a/clang/test/SemaTemplate/address_space-dependent.cpp b/clang/test/SemaTemplate/address_space-dependent.cpp index a42e4daa7bc4..821703bf7825 100644 --- a/clang/test/SemaTemplate/address_space-dependent.cpp +++ b/clang/test/SemaTemplate/address_space-dependent.cpp @@ -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 index 000000000000..9ed17a79de0d --- /dev/null +++ b/clang/test/SemaTemplate/default-arguments-ast-print.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-print %s | FileCheck %s + +template class Foo; + +template <> class Foo { int method1(); }; + +using int_type = int; + +int Foo::method1() { + // CHECK: int Foo::method1() + return 10; +} diff --git a/clang/test/SemaTemplate/delegating-constructors.cpp b/clang/test/SemaTemplate/delegating-constructors.cpp index 852b89d809fa..db3939d9b0e0 100644 --- a/clang/test/SemaTemplate/delegating-constructors.cpp +++ b/clang/test/SemaTemplate/delegating-constructors.cpp @@ -9,7 +9,7 @@ namespace PR10457 { public: template 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() { diff --git a/clang/test/SemaTemplate/matrix-type.cpp b/clang/test/SemaTemplate/matrix-type.cpp index 0ced57c71aa8..1843c0a1a6ed 100644 --- a/clang/test/SemaTemplate/matrix-type.cpp +++ b/clang/test/SemaTemplate/matrix-type.cpp @@ -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 @@ -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 diff --git a/clang/test/SemaTemplate/temp_arg_enum_printing.cpp b/clang/test/SemaTemplate/temp_arg_enum_printing.cpp index dbb4db81f67a..c5570af82bc8 100644 --- a/clang/test/SemaTemplate/temp_arg_enum_printing.cpp +++ b/clang/test/SemaTemplate/temp_arg_enum_printing.cpp @@ -17,7 +17,7 @@ void test() { NamedEnumNS::foo(); // CHECK: template<> void foo() NamedEnumNS::foo<(NamedEnum)1>(); - // CHECK: template<> void foo<2>() + // CHECK: template<> void foo<(NamedEnumNS::NamedEnum)2>() NamedEnumNS::foo<(NamedEnum)2>(); } diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp index 2be815de221c..a735e92a6c98 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -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 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 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 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 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 { diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index 245504f6a85f..cfb5bba7a67b 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -528,3 +528,33 @@ namespace decay { x1.f(x2); } } + +namespace TypeSuffix { + template 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 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 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 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 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 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 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>'}} +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index a6a9cfc39827..5ce74e5f474f 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -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()); } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp index ae427a02bc26..5eee19f0730e 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp @@ -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:: TraverseTemplateArgumentLoc(ArgLoc);