diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -471,6 +471,12 @@ void VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { Outer.add(OIT->getDecl(), Flags); } + void VisitAutoType(const AutoType *T) { + if (T->isConstrained()) { + Outer.add(T->getTypeConstraintConcept(), Flags); + } + TypeVisitor::VisitAutoType(T); + } }; Visitor(*this, Flags).Visit(T.getTypePtr()); } diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -572,6 +572,23 @@ )cpp"; EXPECT_DECLS("ConceptSpecializationExpr", {"template concept Fooable = true"}); + + // Constrained auto + Code = R"cpp( + template + concept Fooable = true; + + [[Fooable]] auto i = 42; + )cpp"; + EXPECT_DECLS("AutoTypeLoc", {"template concept Fooable = true"}); + + Code = R"cpp( + template + concept Fooable = true; + + template<[[Fooable]] auto x> void Foo() {} + )cpp"; + EXPECT_DECLS("AutoTypeLoc", {"template concept Fooable = true"}); } TEST_F(TargetDeclTest, Coroutine) { diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -487,6 +487,46 @@ HI.Kind = index::SymbolKind::TypeAlias; HI.Definition = "int"; }}, + // constraint of constrained auto + {R"cpp( + template concept Fooable = true; + [[Foo^able]] auto x = 1; + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "Fooable"; + HI.Kind = index::SymbolKind::Concept; + HI.Definition = "template \n" + "concept Fooable = true"; + }}, + {R"cpp( + template concept Fooable = true; + template<[[Fooa^ble]] auto x> void Foo() {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "Fooable"; + HI.Kind = index::SymbolKind::Concept; + HI.Definition = "template \n" + "concept Fooable = true"; + }}, + // concept + {R"cpp( + template + concept Fooable = requires (T t) { t.foo(); }; + + template requires [[Fo^oable]] + void bar(T t) { + t.foo(); + } + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "Fooable"; + HI.Kind = index::SymbolKind::Concept; + HI.Definition = "template \n" + "concept Fooable = requires(T t) { t.foo(); }"; + }}, // auto on lambda {R"cpp( void foo() {