nridge created this revision. Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman, jkorous. Herald added a project: clang. nridge requested review of this revision. Herald added subscribers: MaskRay, ilya-biryukov.
As part of this change, DynTypedNode is enhanced to allow storing a TemplateArgumentLoc. Fixes https://github.com/clangd/clangd/issues/473 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D85503 Files: clang-tools-extra/clangd/FindTarget.cpp clang-tools-extra/clangd/Selection.cpp clang-tools-extra/clangd/unittests/FindTargetTests.cpp clang/include/clang/AST/ASTTypeTraits.h clang/lib/AST/ASTTypeTraits.cpp
Index: clang/lib/AST/ASTTypeTraits.cpp =================================================================== --- clang/lib/AST/ASTTypeTraits.cpp +++ clang/lib/AST/ASTTypeTraits.cpp @@ -23,6 +23,7 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { { NKI_None, "<None>" }, { NKI_None, "TemplateArgument" }, + { NKI_None, "TemplateArgumentLoc" }, { NKI_None, "TemplateName" }, { NKI_None, "NestedNameSpecifierLoc" }, { NKI_None, "QualType" }, @@ -129,6 +130,8 @@ const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get<TemplateArgument>()) TA->print(PP, OS); + else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) + TAL->getArgument().print(PP, OS); else if (const TemplateName *TN = get<TemplateName>()) TN->print(OS, PP); else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) @@ -175,6 +178,8 @@ return D->getSourceRange(); if (const Stmt *S = get<Stmt>()) return S->getSourceRange(); + if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) + return TAL->getSourceRange(); if (const auto *C = get<OMPClause>()) return SourceRange(C->getBeginLoc(), C->getEndLoc()); return SourceRange(); Index: clang/include/clang/AST/ASTTypeTraits.h =================================================================== --- clang/include/clang/AST/ASTTypeTraits.h +++ clang/include/clang/AST/ASTTypeTraits.h @@ -132,6 +132,7 @@ enum NodeKindId { NKI_None, NKI_TemplateArgument, + NKI_TemplateArgumentLoc, NKI_TemplateName, NKI_NestedNameSpecifierLoc, NKI_QualType, @@ -191,6 +192,7 @@ }; KIND_TO_KIND_ID(CXXCtorInitializer) KIND_TO_KIND_ID(TemplateArgument) +KIND_TO_KIND_ID(TemplateArgumentLoc) KIND_TO_KIND_ID(TemplateName) KIND_TO_KIND_ID(NestedNameSpecifier) KIND_TO_KIND_ID(NestedNameSpecifierLoc) @@ -456,12 +458,13 @@ /// Note that we can store \c Decls, \c Stmts, \c Types, /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are /// guaranteed to be unique pointers pointing to dedicated storage in the AST. - /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and - /// \c TemplateArguments on the other hand do not have storage or unique - /// pointers and thus need to be stored by value. + /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs, + /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not + /// have storage or unique pointers and thus need to be stored by value. llvm::AlignedCharArrayUnion<const void *, TemplateArgument, - NestedNameSpecifierLoc, QualType, - TypeLoc> Storage; + TemplateArgumentLoc, NestedNameSpecifierLoc, + QualType, TypeLoc> + Storage; }; template <typename T> @@ -496,6 +499,10 @@ struct DynTypedNode::BaseConverter< TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; +template <> +struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void> + : public ValueConverter<TemplateArgumentLoc> {}; + template <> struct DynTypedNode::BaseConverter< TemplateName, void> : public ValueConverter<TemplateName> {}; Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -376,6 +376,14 @@ {"template<> class Foo<int *>", Rel::TemplateInstantiation}, {"template <typename T> class Foo<T *>", Rel::TemplatePattern}); + Code = R"cpp( + // Default argument of template template parameter. + template<typename T> struct Vector {}; + template <template <typename> class Container = [[Vector]]> + struct A {}; + )cpp"; + EXPECT_DECLS("TemplateArgumentLoc", {"template <typename T> struct Vector"}); + Flags.push_back("-std=c++17"); // for CTAD tests Code = R"cpp( Index: clang-tools-extra/clangd/Selection.cpp =================================================================== --- clang-tools-extra/clangd/Selection.cpp +++ clang-tools-extra/clangd/Selection.cpp @@ -479,6 +479,10 @@ bool TraverseTypeLoc(TypeLoc X) { return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); }); } + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &X) { + return traverseNode(&X, + [&] { return Base::TraverseTemplateArgumentLoc(X); }); + } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc X) { return traverseNode( &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); }); Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -590,6 +590,19 @@ add(CCI->getAnyMember(), Flags); // Constructor calls contain a TypeLoc node, so we don't handle them here. } + + void add(const TemplateArgument &Arg, RelSet Flags) { + // Only used for template template arguments. + // For type and non-type template arguments, SelectionTree + // will hit a more specific node (e.g. a TypeLoc or a + // DeclRefExpr). + if (Arg.getKind() == TemplateArgument::Template || + Arg.getKind() == TemplateArgument::TemplateExpansion) { + if (TemplateDecl *TD = Arg.getAsTemplate().getAsTemplateDecl()) { + report(TD, Flags); + } + } + } }; } // namespace @@ -613,6 +626,8 @@ Finder.add(*QT, Flags); else if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) Finder.add(CCI, Flags); + else if (const TemplateArgumentLoc *TAL = N.get<TemplateArgumentLoc>()) + Finder.add(TAL->getArgument(), Flags); return Finder.takeDecls(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits