[clangd] Do not skip Attr nodes in SelectionTree traversal (#174199)

SelectionTree attempts to skip nodes that don't intersect with the
selection for performance. However, Attr nodes (like AlignedAttr) often
have inaccurate source ranges (e.g. pointing to a single location).

Previously, canSafelySkipNode handled nodes that *have* attributes
attached, but failed to account for the case where the node being
visited *is* the attribute itself. This caused `alignas(WALDO)` to be
skipped, breaking features like go-to-definition on WALDO.

This commit adds a check to ensure explicit Attr nodes are visited,
fixing the issue.

Fixes https://github.com/clangd/clangd/issues/2502
This commit is contained in:
Quan Zhuo 2026-01-20 22:41:55 +08:00 committed by GitHub
parent c8e5259c09
commit 08391d2b4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 0 deletions

View File

@ -817,6 +817,11 @@ private:
if (llvm::any_of(getAttributes(N),
[](const Attr *A) { return !A->isImplicit(); }))
return false;
// Attributes themselves also often have bad source ranges.
if (const auto *A = N.get<Attr>()) {
if (!A->isImplicit())
return false;
}
if (!SelChecker.mayHit(S)) {
dlog("{2}skip: {0} {1}", printNodeToString(N, PrintPolicy),
S.printToString(SM), indent());

View File

@ -608,6 +608,11 @@ TEST(SelectionTest, CommonAncestor) {
template <typename T> void g(D<[[^T]]> auto abc) {}
)cpp",
"TemplateTypeParmTypeLoc"},
{R"cpp(
const unsigned WALDO = 64;
struct alignas([[WA^LDO]]) foo {};
)cpp",
"DeclRefExpr"},
};
for (const Case &C : Cases) {