diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -129,6 +129,23 @@ return Merged.CanonicalDeclaration; } +// Returns true if the given expression is an implicit AST node. +bool IsImplicitExpr(const Expr *E) { + if (!E) + return false; + // We assume that a constructor expression is implict (was inserted by + // clang) if it has an invalid paren/brace location, since such + // experssion is impossible to write down. + if (const auto *CtorExpr = dyn_cast(E)) + return CtorExpr->getParenOrBraceRange().isInvalid(); + // Ignore implicit conversion-operator AST node. + if (const auto *ME = dyn_cast(E)) { + if (isa(ME->getMemberDecl())) + return ME->getMemberLoc().isInvalid(); + } + return isa(E); +} + /// Finds declarations locations that a given source location refers to. class DeclarationAndMacrosFinder : public index::IndexDataConsumer { std::vector MacroInfos; @@ -179,22 +196,6 @@ return true; if (Loc == SearchedLocation) { - auto IsImplicitExpr = [](const Expr *E) { - if (!E) - return false; - // We assume that a constructor expression is implict (was inserted by - // clang) if it has an invalid paren/brace location, since such - // experssion is impossible to write down. - if (const auto *CtorExpr = dyn_cast(E)) - return CtorExpr->getParenOrBraceRange().isInvalid(); - // Ignore implicit conversion-operator AST node. - if (const auto *ME = dyn_cast(E)) { - if (isa(ME->getMemberDecl())) - return ME->getMemberLoc().isInvalid(); - } - return isa(E); - }; - if (IsImplicitExpr(ASTNode.OrigE)) return true; // Find and add definition declarations (for GoToDefinition). @@ -408,7 +409,8 @@ assert(D->isCanonicalDecl() && "expect D to be a canonical declaration"); const SourceManager &SM = AST.getSourceManager(); Loc = SM.getFileLoc(Loc); - if (isInsideMainFile(Loc, SM) && CanonicalTargets.count(D)) + if (isInsideMainFile(Loc, SM) && CanonicalTargets.count(D) && + !IsImplicitExpr(ASTNode.OrigE)) References.push_back({Loc, Roles}); return true; } diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -2080,7 +2080,18 @@ [[a]].operator bool(); if ([[a^]]) {} // ignore implicit conversion-operator AST node } - )cpp", + )cpp", + R"cpp( + struct X { + [[operator]] bool(); + }; + + int test() { + X a; + a.[[oper^ator]] bool(); + if (a) {} + } + )cpp", }; for (const char *Test : Tests) { Annotations T(Test);