Skip to content

Commit 4239775

Browse files
committed
Improve attribute range handling for attributed function types in selection
This fix clangd/clangd#2488
1 parent 89eef94 commit 4239775

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

clang-tools-extra/clangd/Selection.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,18 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
958958
claimRange(SourceRange(FTL.getLParenLoc(), FTL.getEndLoc()), Result);
959959
return;
960960
}
961+
if (auto ATL = TL->getAs<AttributedTypeLoc>()) {
962+
// For attributed function types like `int foo() [[attr]]`, the
963+
// AttributedTypeLoc's range includes the function name. We want to
964+
// allow the function name to be associated with the FunctionDecl
965+
// rather than the AttributedTypeLoc, so we only claim the attribute
966+
// range itself.
967+
if (ATL.getModifiedLoc().getAs<FunctionTypeLoc>()) {
968+
// Only claim the attribute's source range, not the whole type.
969+
claimRange(ATL.getLocalSourceRange(), Result);
970+
return;
971+
}
972+
}
961973
}
962974
claimRange(getSourceRange(N), Result);
963975
}

clang-tools-extra/clangd/unittests/SelectionTests.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,15 @@ TEST(SelectionTest, CommonAncestor) {
311311
{"[[void foo^()]];", "FunctionProtoTypeLoc"},
312312
{"[[^void foo^()]];", "FunctionDecl"},
313313
{"[[void ^foo()]];", "FunctionDecl"},
314+
// Tricky case: with function attributes, the AttributedTypeLoc's range
315+
// includes the function name, but we want the name to be associated with
316+
// the FunctionDecl.
317+
{"struct X { [[void ^foo() [[clang::lifetimebound]]]]; };",
318+
"FunctionDecl"},
319+
{"struct X { [[void ^foo() const [[clang::lifetimebound]]]]; };",
320+
"FunctionDecl"},
321+
{"struct X { [[const int* ^Get() const [[clang::lifetimebound]]]]; };",
322+
"FunctionDecl"},
314323
// Tricky case: two VarDecls share a specifier.
315324
{"[[int ^a]], b;", "VarDecl"},
316325
{"[[int a, ^b]];", "VarDecl"},

0 commit comments

Comments
 (0)