File tree Expand file tree Collapse file tree 2 files changed +21
-0
lines changed Expand file tree Collapse file tree 2 files changed +21
-0
lines changed Original file line number Diff line number Diff 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 }
Original file line number Diff line number Diff 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" },
You can’t perform that action at this time.
0 commit comments