diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -10,6 +10,7 @@ #include "Logger.h" #include "SourceCode.h" #include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -602,12 +603,15 @@ // Usually empty, but sometimes children cover tokens but shouldn't own them. SourceRange earlySourceRange(const DynTypedNode &N) { if (const Decl *D = N.get()) { + // FunctionDecl is also a DeclaratorDecl, but getLocation doesn't work for + // operator overloads, e.g. operator [[int]](); Therefore we handle them + // explicitly. // void [[foo]](); if (auto *FD = llvm::dyn_cast(D)) return FD->getNameInfo().getSourceRange(); // int (*[[s]])(); - else if (auto *VD = llvm::dyn_cast(D)) - return VD->getLocation(); + if (auto *DD = llvm::dyn_cast(D)) + return DD->getLocation(); } else if (const auto* CCI = N.get()) { // : [[b_]](42) return CCI->getMemberLocation(); diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -369,6 +369,17 @@ int test(I *f) { return 42 + [[f.^foo]]; } )cpp", "ObjCPropertyRefExpr"}, + { + R"cpp( + // We've got this nice trick, as annotation library eagerly selects + // the range and if we've got [32] below, there's no way to select + // the full range. + #define X [32] + struct foo { + [[int has^h X]]; + }; + )cpp", + "FieldDecl"}, }; for (const Case &C : Cases) { Annotations Test(C.Code);