diff --git a/clang-tools-extra/clangd/index/Serialization.cpp b/clang-tools-extra/clangd/index/Serialization.cpp --- a/clang-tools-extra/clangd/index/Serialization.cpp +++ b/clang-tools-extra/clangd/index/Serialization.cpp @@ -282,6 +282,7 @@ OS.write(static_cast(Sym.SymInfo.Lang)); writeVar(Strings.index(Sym.Name), OS); writeVar(Strings.index(Sym.Scope), OS); + writeVar(Strings.index(Sym.TemplateArgumentList), OS); writeLocation(Sym.Definition, Strings, OS); writeLocation(Sym.CanonicalDeclaration, Strings, OS); writeVar(Sym.References, OS); @@ -309,6 +310,7 @@ Sym.SymInfo.Lang = static_cast(Data.consume8()); Sym.Name = Data.consumeString(Strings); Sym.Scope = Data.consumeString(Strings); + Sym.TemplateArgumentList = Data.consumeString(Strings); Sym.Definition = readLocation(Data, Strings); Sym.CanonicalDeclaration = readLocation(Data, Strings); Sym.References = Data.consumeVar(); diff --git a/clang-tools-extra/clangd/index/Symbol.h b/clang-tools-extra/clangd/index/Symbol.h --- a/clang-tools-extra/clangd/index/Symbol.h +++ b/clang-tools-extra/clangd/index/Symbol.h @@ -42,6 +42,10 @@ llvm::StringRef Name; /// The containing namespace. e.g. "" (global), "ns::" (top-level namespace). llvm::StringRef Scope; + /// Argument list in human-readable format, will be displayed to help + /// disambiguate between different specializations of a template. Empty for + /// non-specializations. Example: "" + llvm::StringRef TemplateArgumentList; /// The location of the symbol's definition, if one was found. /// This just covers the symbol name (e.g. without class/function body). SymbolLocation Definition; @@ -143,6 +147,7 @@ template void visitStrings(Symbol &S, const Callback &CB) { CB(S.Name); CB(S.Scope); + CB(S.TemplateArgumentList); CB(S.Signature); CB(S.CompletionSnippetSuffix); CB(S.Documentation); diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -523,6 +523,8 @@ Symbol S; S.ID = std::move(ID); + std::string TemplateArgumentList = printTemplateArgsAsWritten(ND); + S.TemplateArgumentList = TemplateArgumentList; std::string QName = printQualifiedName(ND); std::tie(S.Scope, S.Name) = splitQualifiedName(QName); // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo: diff --git a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp --- a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp +++ b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp @@ -51,6 +51,9 @@ return (arg.Name + arg.CompletionSnippetSuffix).str() == S; } MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; } +MATCHER_P(TemplateArgs, TemplArgs, "") { + return arg.TemplateArgumentList == TemplArgs; +} MATCHER_P(DeclURI, P, "") { return StringRef(arg.CanonicalDeclaration.FileURI) == P; } @@ -394,23 +397,80 @@ Annotations Header(R"( // Primary template and explicit specialization are indexed, instantiation // is not. - template struct [[Tmpl]] {T $xdecl[[x]] = 0;}; - template <> struct $specdecl[[Tmpl]] {}; - template struct $partspecdecl[[Tmpl]] {}; - extern template struct Tmpl; - template struct Tmpl; + template class $barclasstemp[[Bar]] {}; + template class Z, int Q> + struct [[Tmpl]] { T $xdecl[[x]] = 0; }; + + // template-template, non-type and type full spec + template <> struct $specdecl[[Tmpl]] {}; + + // template-template, non-type and type partial spec + template struct $partspecdecl[[Tmpl]] {}; + // instantiation + extern template struct Tmpl; + // instantiation + template struct Tmpl; + + template class $fooclasstemp[[Foo]] {}; + // parameter-packs full spec + template<> class $parampack[[Foo]], int, double> {}; + // parameter-packs partial spec + template class $parampackpartial[[Foo]] {}; + + template class $bazclasstemp[[Baz]] {}; + // non-type parameter-packs full spec + template<> class $parampacknontype[[Baz]]<3, 5, 8> {}; + // non-type parameter-packs partial spec + template class $parampacknontypepartial[[Baz]] {}; + + template