massberg created this revision. massberg added a reviewer: sammccall. Herald added subscribers: kadircet, arphaman, kristof.beyls. Herald added a project: All. massberg requested review of this revision. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added projects: clang, clang-tools-extra.
Consider type constraints of TemplateTypeParmDecls in FindTarget. To this end TemplateTypeParmTypeLoc:getLocalSourceRange() now also includes the whole constraint if there is any. In clangd this enables that Hover now works for type constraints of auto function parameters and template parameters. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D155460 Files: clang-tools-extra/clangd/FindTarget.cpp clang-tools-extra/clangd/unittests/FindTargetTests.cpp clang-tools-extra/clangd/unittests/HoverTests.cpp clang/include/clang/AST/TypeLoc.h clang/lib/AST/TypeLoc.cpp clang/unittests/AST/SourceLocationTest.cpp
Index: clang/unittests/AST/SourceLocationTest.cpp =================================================================== --- clang/unittests/AST/SourceLocationTest.cpp +++ clang/unittests/AST/SourceLocationTest.cpp @@ -19,6 +19,7 @@ #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Testing/CommandLineArgs.h" #include "clang/Tooling/Tooling.h" #include "llvm/Testing/Annotations/Annotations.h" #include "gtest/gtest.h" @@ -263,6 +264,19 @@ EXPECT_TRUE(Verifier.match(Code, typeLoc(loc(autoType())), Lang_CXX20)); } +TEST(TypeLoc, TemplateTypeParmTypeLocRange) { + RangeVerifier<TypeLoc> Verifier; + Verifier.expectRange(2, 10, 2, 18); + EXPECT_TRUE(Verifier.match("template <typename T> concept Fooable = true;\n" + "void Bar(Fooable auto x) {}", + typeLoc(loc(templateTypeParmType())), Lang_CXX20)); + + Verifier.expectRange(2, 11, 2, 31); + EXPECT_TRUE(Verifier.match("template <typename T> concept Fooable = true;\n" + "template <Fooable T> void bar(T t) {}", + typeLoc(loc(templateTypeParmType())), Lang_CXX20)); +} + TEST(TypeLoc, LongDoubleRange) { RangeVerifier<TypeLoc> Verifier; Verifier.expectRange(1, 1, 1, 6); @@ -370,10 +384,10 @@ TEST(CompoundLiteralExpr, ParensCompoundVectorLiteralRange) { RangeVerifier<CompoundLiteralExpr> Verifier; Verifier.expectRange(2, 20, 2, 31); - EXPECT_TRUE(Verifier.match( - "typedef int int2 __attribute__((ext_vector_type(2)));\n" - "constant int2 i2 = (int2)(1, 2);", - compoundLiteralExpr(), Lang_OpenCL)); + EXPECT_TRUE( + Verifier.match("typedef int int2 __attribute__((ext_vector_type(2)));\n" + "constant int2 i2 = (int2)(1, 2);", + compoundLiteralExpr(), Lang_OpenCL)); } TEST(InitListExpr, VectorLiteralListBraceRange) { Index: clang/lib/AST/TypeLoc.cpp =================================================================== --- clang/lib/AST/TypeLoc.cpp +++ clang/lib/AST/TypeLoc.cpp @@ -11,9 +11,10 @@ //===----------------------------------------------------------------------===// #include "clang/AST/TypeLoc.h" -#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" @@ -718,3 +719,21 @@ return AutoTypeLoc(); return Res.getAs<AutoTypeLoc>(); } + +SourceRange TemplateTypeParmTypeLoc::getLocalSourceRange() const { + SourceRange SR = + InheritingConcreteTypeLoc<TypeSpecTypeLoc, TemplateTypeParmTypeLoc, + TemplateTypeParmType>::getLocalSourceRange(); + SourceLocation StartLoc = SR.getBegin(); + + if (auto *D = getDecl()) { + if (auto *TC = D->getTypeConstraint()) { + if (TC->getNestedNameSpecifierLoc()) { + StartLoc = TC->getNestedNameSpecifierLoc().getBeginLoc(); + } else { + StartLoc = TC->getConceptNameLoc(); + } + } + } + return SourceRange(StartLoc, getNameLoc()); +} Index: clang/include/clang/AST/TypeLoc.h =================================================================== --- clang/include/clang/AST/TypeLoc.h +++ clang/include/clang/AST/TypeLoc.h @@ -751,6 +751,8 @@ TemplateTypeParmType> { public: TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } + + SourceRange getLocalSourceRange() const; }; struct ObjCTypeParamTypeLocInfo { Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -487,6 +487,29 @@ HI.Kind = index::SymbolKind::TypeAlias; HI.Definition = "int"; }}, + // constrained function parameter + {R"cpp( + template <class T> concept Fooable = true; + void Foo([[Fooa^ble]] auto x) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "Fooable"; + HI.Kind = index::SymbolKind::Concept; + HI.Definition = "template <class T>\nconcept Fooable = true"; + }}, + // constrained template parameter + {R"cpp( + template <class T> concept Fooable = true; + template <[[Foo^able]] T> + void bar(T t) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "Fooable"; + HI.Kind = index::SymbolKind::Concept; + HI.Definition = "template <class T>\nconcept Fooable = true"; + }}, // auto on lambda {R"cpp( void foo() { @@ -3024,58 +3047,59 @@ struct { const char *Code; const std::function<void(HoverInfo &)> ExpectedBuilder; - } Cases[] = {{R"cpp( - struct Foo {}; + } Cases[] = { + {R"cpp( + struct Foo {}; Foo F = Fo^o{}; )cpp", - [](HoverInfo &HI) { HI.Provider = ""; }}, - {R"cpp( - #include "foo.h" + [](HoverInfo &HI) { HI.Provider = ""; }}, + {R"cpp( + #include "foo.h" Foo F = Fo^o{}; )cpp", - [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, - {R"cpp( - #include "all.h" + [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, + {R"cpp( + #include "all.h" Foo F = Fo^o{}; )cpp", - [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, - {R"cpp( + [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, + {R"cpp( #define FOO 5 int F = ^FOO; )cpp", - [](HoverInfo &HI) { HI.Provider = ""; }}, - {R"cpp( + [](HoverInfo &HI) { HI.Provider = ""; }}, + {R"cpp( #include "foo.h" int F = ^FOO; )cpp", - [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, - {R"cpp( + [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, + {R"cpp( #include "all.h" int F = ^FOO; )cpp", - [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, - {R"cpp( - #include "foo.h" + [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, + {R"cpp( + #include "foo.h" Foo A; Foo B; Foo C = A ^+ B; )cpp", - [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, - // Hover selects the underlying decl of the using decl - {R"cpp( + [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, + // Hover selects the underlying decl of the using decl + {R"cpp( #include "foo.h" namespace ns { using ::Foo; } ns::F^oo d; )cpp", - [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, - {R"cpp( + [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, + {R"cpp( namespace foo {}; using namespace fo^o; )cpp", - [](HoverInfo &HI) { HI.Provider = ""; }}, - }; + [](HoverInfo &HI) { HI.Provider = ""; }}, + }; for (const auto &Case : Cases) { Annotations Code{Case.Code}; Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -559,7 +559,7 @@ template <[[Fooable]] T> void bar(T t); )cpp"; - EXPECT_DECLS("ConceptSpecializationExpr", + EXPECT_DECLS("TemplateTypeParmTypeLoc", {"template <typename T> concept Fooable = true"}); // partial-concept-id @@ -570,7 +570,17 @@ template <[[Fooable]]<int> T> void bar(T t); )cpp"; - EXPECT_DECLS("ConceptSpecializationExpr", + EXPECT_DECLS("TemplateTypeParmTypeLoc", + {"template <typename T, typename U> concept Fooable = true"}); + + // Constrained function parameter + Code = R"cpp( + template <typename T, typename U> + concept Fooable = true; + + void Foo([[Fooable]]<int> auto t); + )cpp"; + EXPECT_DECLS("TemplateTypeParmTypeLoc", {"template <typename T, typename U> concept Fooable = true"}); } Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -230,6 +230,11 @@ dyn_cast<ObjCCategoryImplDecl>(D)) { // Treat ObjC{Category,CategoryImpl}Decl as if they were a decl/def pair. D = CID->getCategoryDecl(); + } else if (const TemplateTypeParmDecl *TTPD = + dyn_cast<TemplateTypeParmDecl>(D)) { + if (auto *TC = TTPD->getTypeConstraint()) { + D = TC->getNamedConcept(); + } } if (!D) return;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits