diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -50,6 +50,17 @@ return SM.getSpellingLoc(D->getLocation()); } +static llvm::Optional> +getTemplateSpecializationArgLocs(const NamedDecl &ND) { + if (auto *Func = llvm::dyn_cast(&ND)) + return Func->getTemplateSpecializationArgsAsWritten()->arguments(); + if (auto *Cls = llvm::dyn_cast(&ND)) + return Cls->getTemplateArgsAsWritten()->arguments(); + if (auto *Var = llvm::dyn_cast(&ND)) + return Var->getTemplateArgsInfo().arguments(); + return llvm::None; +} + std::string printQualifiedName(const NamedDecl &ND) { std::string QName; llvm::raw_string_ostream OS(QName); @@ -60,6 +71,10 @@ // namespaces to query: the preamble doesn't have a dedicated list. Policy.SuppressUnwrittenScope = true; ND.printQualifiedName(OS, Policy); + if (auto Args = getTemplateSpecializationArgLocs(ND)) + printTemplateArgumentList(OS, *Args, Policy); + else if (auto *Cls = llvm::dyn_cast(&ND)) + printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); OS.flush(); assert(!StringRef(QName).startswith("::")); return QName; diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1632,6 +1632,18 @@ return A.getArgument(); } +static void printArgument(const TemplateArgument &A, + const PrintingPolicy &PP, + llvm::raw_ostream &OS) { + A.print(PP, OS); +} + +static void printArgument(const TemplateArgumentLoc &A, + const PrintingPolicy &PP, + llvm::raw_ostream &OS) { + A.getTypeSourceInfo()->getType().print(OS, PP); +} + template static void printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, bool SkipBrackets) { @@ -1653,7 +1665,7 @@ } else { if (!FirstArg) OS << Comma; - Argument.print(Policy, ArgOS); + printArgument(Arg, Policy, ArgOS); } StringRef ArgString = ArgOS.str();