Index: clangd/XRefs.cpp =================================================================== --- clangd/XRefs.cpp +++ clangd/XRefs.cpp @@ -139,21 +139,19 @@ SourceLocation Loc, index::IndexDataConsumer::ASTNodeInfo ASTNode) override { if (Loc == SearchedLocation) { - // Check whether the E has an implicit AST node (e.g. ImplicitCastExpr). - auto hasImplicitExpr = [](const Expr *E) { - if (!E || E->child_begin() == E->child_end()) + auto isImplicitExpr = [](const Expr *E) { + if (!E) return false; - // Use the first child is good enough for most cases -- normally the - // expression returned by handleDeclOccurence contains exactly one - // child expression. - const auto *FirstChild = *E->child_begin(); - return isa(FirstChild) || - isa(FirstChild) || - isa(FirstChild) || - isa(FirstChild); + // 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->getNumArgs() > 0 && + CtorExpr->getParenOrBraceRange().isInvalid(); + return isa(E); }; - bool IsExplicit = !hasImplicitExpr(ASTNode.OrigE); + bool IsExplicit = !isImplicitExpr(ASTNode.OrigE); // Find and add definition declarations (for GoToDefinition). // We don't use parameter `D`, as Parameter `D` is the canonical // declaration, which is the first declaration of a redeclarable Index: unittests/clangd/XRefsTests.cpp =================================================================== --- unittests/clangd/XRefsTests.cpp +++ unittests/clangd/XRefsTests.cpp @@ -1225,6 +1225,53 @@ } } +TEST(FindReferences, ExplicitSymbols) { + const char *Tests[] = { + R"cpp( + struct Foo { Foo* [self]() const; }; + void f() { + if (Foo* T = foo.[^self]()) {} // Foo member call expr. + } + )cpp", + + R"cpp( + struct Foo { Foo(int); }; + Foo f() { + int [b]; + return [^b]; // Foo constructor expr. + } + )cpp", + + R"cpp( + struct Foo {}; + void g(Foo); + Foo [f](); + void call() { + g([^f]()); // Foo constructor expr. + } + )cpp", + + R"cpp( + void [foo](int); + void [foo](double); + + namespace ns { + using ::[fo^o]; + } + )cpp", + }; + for (const char *Test : Tests) { + Annotations T(Test); + auto AST = TestTU::withCode(T.code()).build(); + std::vector> ExpectedLocations; + for (const auto &R : T.ranges()) + ExpectedLocations.push_back(RangeIs(R)); + EXPECT_THAT(findReferences(AST, T.point()), + ElementsAreArray(ExpectedLocations)) + << Test; + } +} + TEST(FindReferences, NeedsIndex) { const char *Header = "int foo();"; Annotations Main("int main() { [[f^oo]](); }");