Author: Maria Fernanda GuimarĂ£es Date: 2026-08-14T22:58:24+08:00 New Revision: b79317f9877d805a5091b26dd1f2eb795b5aca05
URL: https://github.com/llvm/llvm-project/commit/b79317f9877d805a5091b26dd1f2eb795b5aca05 DIFF: https://github.com/llvm/llvm-project/commit/b79317f9877d805a5091b26dd1f2eb795b5aca05.diff LOG: [clangd] Add hover support for statement attributes (#214318) Hovering over `[unroll]`, `[loop]`, `[branch]`, or `[flatten]` should display the attribute name and documentation about its effect on GPU shader execution. This patch extends clangd's `SelectionTree` to traverse attributes attached to `AttributedStmt` nodes before visiting the underlying statement. Fixes #214067 Added: Modified: clang-tools-extra/clangd/Selection.cpp clang-tools-extra/clangd/unittests/HoverTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index b79ffc7d5a6e9..41d028cfcf4b5 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -666,6 +666,14 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> { bool TraverseAttr(Attr *X) { return traverseNode(X, [&] { return Base::TraverseAttr(X); }); } + bool TraverseAttributedStmt(AttributedStmt *S) { + return traverseNode(S, [&] { + for (const Attr *A : S->getAttrs()) + if (!TraverseAttr(const_cast<Attr *>(A))) + return false; + return TraverseStmt(S->getSubStmt()); + }); + } bool TraverseConceptReference(ConceptReference *X) { return traverseNode(X, [&] { return Base::TraverseConceptReference(X); }); } diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 02ce48c6dca95..d355118f30761 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -5412,6 +5412,87 @@ TEST(Hover, HLSLInvalidVectorSwizzleNoCrash) { EXPECT_FALSE(H); } +TEST(Hover, AttributedStmt) { + struct { + const char *const Code; + const char *const ExpectedName; + bool IsHLSL; + bool ExpectDocumentation; + } Cases[] = { + {R"hlsl( + [numthreads(1, 1, 1)] + void main() { + [^unroll] + for (int i = 0; i < 4; i++) {} + } + )hlsl", + "unroll", /*IsHLSL=*/true, /*ExpectDocumentation=*/true}, + {R"hlsl( + [numthreads(1, 1, 1)] + void main() { + [l^oop] + for (int i = 0; i < 4; i++) {} + } + )hlsl", + "loop", /*IsHLSL=*/true, /*ExpectDocumentation=*/true}, + {R"hlsl( + [numthreads(1, 1, 1)] + void main() { + [b^ranch] + if (true) {} + } + )hlsl", + "branch", /*IsHLSL=*/true, /*ExpectDocumentation=*/false}, + {R"hlsl( + [numthreads(1, 1, 1)] + void main() { + [f^latten] + if (true) {} + } + )hlsl", + "flatten", /*IsHLSL=*/true, /*ExpectDocumentation=*/false}, + {R"cpp( + void foo() { + [[^likely]] if (true) {} + } + )cpp", + "likely", /*IsHLSL=*/false, /*ExpectDocumentation=*/false}, + {R"cpp( + void foo() { + [[^unlikely]] if (true) {} + } + )cpp", + "unlikely", /*IsHLSL=*/false, /*ExpectDocumentation=*/false}, + {R"cpp( + void foo() { + switch (1) { + case 1: + [[^fallthrough]]; + case 2: + break; + } + } + )cpp", + "fallthrough", /*IsHLSL=*/false, /*ExpectDocumentation=*/false}, + }; + for (const auto &Case : Cases) { + SCOPED_TRACE(Case.Code); + Annotations T(Case.Code, + Annotations::Markers().setRangeBegin("{{").setRangeEnd("}}")); + TestTU TU = TestTU::withCode(T.code()); + if (Case.IsHLSL) + configureHLSL(TU); + else + TU.ExtraArgs.push_back("-std=c++20"); + auto AST = TU.build(); + auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + EXPECT_EQ(H->Name, Case.ExpectedName); + if (Case.ExpectDocumentation) { + EXPECT_FALSE(H->Documentation.empty()); + } + } +} TEST(Hover, HLSLRegisterAttributeRange) { Annotations T(R"hlsl( Texture2D tex : [[^register]]([[^t1]]); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
