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 @@ -405,6 +405,11 @@ } TEST_F(TargetDeclTest, Concept) { + Flags.push_back("-std=c++20"); + + // FIXME: Should we truncate the pretty-printed form of a concept decl + // somewhere? + Code = R"cpp( template concept Fooable = requires (T t) { t.foo(); }; @@ -414,12 +419,31 @@ t.foo(); } )cpp"; - Flags.push_back("-std=c++20"); EXPECT_DECLS( "ConceptSpecializationExpr", - // FIXME: Should we truncate the pretty-printed form of a concept decl - // somewhere? {"template concept Fooable = requires (T t) { t.foo(); };"}); + + // constrained-parameter + Code = R"cpp( + template + concept Fooable = true; + + template <[[Fooable]] T> + void bar(T t); + )cpp"; + EXPECT_DECLS("ConceptSpecializationExpr", + {"template concept Fooable = true;"}); + + // partial-concept-id + Code = R"cpp( + template + concept Fooable = true; + + template <[[Fooable]] T> + void bar(T t); + )cpp"; + EXPECT_DECLS("ConceptSpecializationExpr", + {"template concept Fooable = true;"}); } TEST_F(TargetDeclTest, FunctionTemplate) { diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1777,8 +1777,10 @@ // D is the "T" in something like "template class vector;" if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - if (const auto *TC = D->getTypeConstraint()) + if (const auto *TC = D->getTypeConstraint()) { + TRY_TO(TraverseStmt(TC->getImmediatelyDeclaredConstraint())); TRY_TO(TraverseConceptReference(*TC)); + } if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); })