diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -288,8 +288,7 @@ )cpp"; EXPECT_DECLS("TemplateSpecializationTypeLoc", {"template<> class Foo", Rel::TemplateInstantiation}, - {"template class Foo", - Rel::TemplatePattern}); + {"template class Foo", Rel::TemplatePattern}); } TEST_F(TargetDeclTest, FunctionTemplate) { diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -897,6 +897,17 @@ HI.Definition = "int test"; HI.Type = "int"; }}, + // Partially-specialized class decl. (formerly type-parameter-0-0) + {R"cpp( + template class X; + template class [[^X]] {}; + )cpp", + [](HoverInfo &HI) { + HI.Name = "X"; + HI.NamespaceScope = ""; + HI.Kind = SymbolKind::Class; + HI.Definition = "template class X {}"; + }}, // auto on lambda {R"cpp( diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -108,8 +108,8 @@ void printTemplateParameters(const TemplateParameterList *Params, bool OmitTemplateKW = false); - void printTemplateArguments(const TemplateArgumentList &Args, - const TemplateParameterList *Params = nullptr); + void printTemplateArguments(llvm::ArrayRef Args); + void printTemplateArguments(llvm::ArrayRef Args); void prettyPrintAttributes(Decl *D); void prettyPrintPragmas(Decl *D); void printDeclType(QualType T, StringRef DeclName, bool Pack = false); @@ -636,10 +636,15 @@ if (GuideDecl) Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); - if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { + if (D->isFunctionTemplateSpecialization()) { llvm::raw_string_ostream POut(Proto); DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); - TArgPrinter.printTemplateArguments(*TArgs); + const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten(); + if (TArgAsWritten && !Policy.PrintCanonicalTypes) + TArgPrinter.printTemplateArguments(TArgAsWritten->arguments()); + else if (const TemplateArgumentList *TArgs = + D->getTemplateSpecializationArgs()) + TArgPrinter.printTemplateArguments(TArgs->asArray()); } QualType Ty = D->getType(); @@ -957,10 +962,15 @@ if (D->getIdentifier()) { Out << ' ' << *D; - if (auto S = dyn_cast(D)) - printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters()); - else if (auto S = dyn_cast(D)) - printTemplateArguments(S->getTemplateArgs()); + if (auto S = dyn_cast(D)) { + ArrayRef Args = S->getTemplateArgs().asArray(); + if (!Policy.PrintCanonicalTypes) + if (const auto* TSI = S->getTypeAsWritten()) + if (const auto *TST = + dyn_cast(TSI->getType())) + Args = TST->template_arguments(); + printTemplateArguments(Args); + } } if (D->isCompleteDefinition()) { @@ -1083,40 +1093,22 @@ Out << ' '; } -void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args, - const TemplateParameterList *Params) { +void DeclPrinter::printTemplateArguments(ArrayRef Args) { Out << "<"; for (size_t I = 0, E = Args.size(); I < E; ++I) { - const TemplateArgument &A = Args[I]; if (I) Out << ", "; - if (Params) { - if (A.getKind() == TemplateArgument::Type) - if (auto T = A.getAsType()->getAs()) { - auto P = cast(Params->getParam(T->getIndex())); - Out << *P; - continue; - } - if (A.getKind() == TemplateArgument::Template) { - if (auto T = A.getAsTemplate().getAsTemplateDecl()) - if (auto TD = dyn_cast(T)) { - auto P = cast( - Params->getParam(TD->getIndex())); - Out << *P; - continue; - } - } - if (A.getKind() == TemplateArgument::Expression) { - if (auto E = dyn_cast(A.getAsExpr())) - if (auto N = dyn_cast(E->getDecl())) { - auto P = cast( - Params->getParam(N->getIndex())); - Out << *P; - continue; - } - } - } - A.print(Policy, Out); + Args[I].print(Policy, Out); + } + Out << ">"; +} + +void DeclPrinter::printTemplateArguments(ArrayRef Args) { + Out << "<"; + for (size_t I = 0, E = Args.size(); I < E; ++I) { + if (I) + Out << ", "; + Args[I].getArgument().print(Policy, Out); } Out << ">"; } diff --git a/clang/test/Index/print-display-names.cpp b/clang/test/Index/print-display-names.cpp --- a/clang/test/Index/print-display-names.cpp +++ b/clang/test/Index/print-display-names.cpp @@ -22,7 +22,7 @@ // RUN: env CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT=1 c-index-test -test-load-source all-pretty %s | FileCheck %s --check-prefix=PRETTY // PRETTY: print-display-names.cpp:2:7: ClassTemplate=template class ClassTmpl {}:2:7 (Definition) Extent=[1:1 - 2:20] // PRETTY: print-display-names.cpp:4:13: TypedefDecl=typedef int Integer:4:13 (Definition) Extent=[4:1 - 4:20] -// PRETTY: print-display-names.cpp:6:16: ClassDecl=template<> class ClassTmpl {}:6:16 (Definition) [Specialization of ClassTmpl:2:7] Extent=[6:1 - 6:43] +// PRETTY: print-display-names.cpp:6:16: ClassDecl=template<> class ClassTmpl {}:6:16 (Definition) [Specialization of ClassTmpl:2:7] Extent=[6:1 - 6:43] // PRETTY: print-display-names.cpp:8:6: FunctionDecl=void f(ClassTmpl p):8:6 Extent=[8:1 - 8:36] // PRETTY: print-display-names.cpp:8:34: ParmDecl=ClassTmpl p:8:34 (Definition) Extent=[8:8 - 8:35] // PRETTY: print-display-names.cpp:11:6: FunctionTemplate=template void g(ClassTmpl):11:6 Extent=[10:1 - 11:24] diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -1067,8 +1067,7 @@ "template" "struct A { T a; };", classTemplateSpecializationDecl().bind("id"), - "template struct A {}")); - // WRONG; Should be: "template struct A { ... }" + "template struct A {}")); } TEST(DeclPrinter, TestClassTemplateSpecializationDecl1) {