Summary:
clangd uses indexing api to provide references and it was not possible
to perform symbol information for template parameters. This patch enables
visiting of TemplateTypeParmTypeLocs.
Reviewers: ilya-biryukov, akyrtzi
Subscribers: javed.absar, kristof.beyls, ioeric, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58293
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354560
91177308-0d34-0410-b5e6-
96231b3b80d8
bool IndexMacrosInPreprocessor = false;
// Has no effect if IndexFunctionLocals are false.
bool IndexParametersInDeclarations = false;
+ bool IndexTemplateParameters = false;
};
/// Creates a frontend action that indexes all symbols (macros and AST decls).
shouldIndexTemplateParameterDefaultValue(Parent)) {
const TemplateParameterList *Params = D->getTemplateParameters();
for (const NamedDecl *TP : *Params) {
+ if (IndexCtx.shouldIndexTemplateParameters())
+ IndexCtx.handleDecl(TP);
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
if (TTP->hasDefaultArgument())
IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
if (isa<ParmVarDecl>(D))
return true;
- if (isa<TemplateTemplateParmDecl>(D))
- return true;
-
if (isa<ObjCTypeParamDecl>(D))
return true;
return false; \
} while (0)
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
+ SourceLocation Loc = TTPL.getNameLoc();
+ TemplateTypeParmDecl *TTPD = TTPL.getDecl();
+ return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
+ SymbolRoleSet());
+ }
+
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
SourceLocation Loc = TL.getNameLoc();
TypedefNameDecl *ND = TL.getTypedefNameDecl();
return IndexOpts.IndexParametersInDeclarations;
}
+bool IndexingContext::shouldIndexTemplateParameters() const {
+ return IndexOpts.IndexTemplateParameters;
+}
+
bool IndexingContext::handleDecl(const Decl *D,
SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations) {
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
return true;
- if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
+ if (!shouldIndexTemplateParameters() &&
+ (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ isa<TemplateTemplateParmDecl>(D))) {
return true;
+ }
return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
RefE, RefD, DC);
bool shouldIndexParametersInDeclarations() const;
+ bool shouldIndexTemplateParameters() const;
+
static bool isTemplateImplicitInstantiation(const Decl *D);
bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(),
DeclAt(Position(5, 12)))));
}
+TEST(IndexTest, IndexTypeParmDecls) {
+ std::string Code = R"cpp(
+ template <typename T, int I, template<typename> class C, typename NoRef>
+ struct Foo {
+ T t = I;
+ C<int> x;
+ };
+ )cpp";
+ auto Index = std::make_shared<Indexer>();
+ IndexingOptions Opts;
+ tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+ EXPECT_THAT(Index->Symbols, AllOf(Not(Contains(QName("Foo::T"))),
+ Not(Contains(QName("Foo::I"))),
+ Not(Contains(QName("Foo::C"))),
+ Not(Contains(QName("Foo::NoRef")))));
+
+ Opts.IndexTemplateParameters = true;
+ Index->Symbols.clear();
+ tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+ EXPECT_THAT(Index->Symbols,
+ AllOf(Contains(QName("Foo::T")), Contains(QName("Foo::I")),
+ Contains(QName("Foo::C")), Contains(QName("Foo::NoRef"))));
+}
+
} // namespace
} // namespace index
} // namespace clang