Author: hokein Date: Thu Dec 13 05:17:04 2018 New Revision: 349033 URL: http://llvm.org/viewvc/llvm-project?rev=349033&view=rev Log: [clangd] Refine the way of checking a declaration is referenced by the written code.
Summary: The previous solution (checking the AST) is not a reliable way to determine whether a declaration is explicitly referenced by the source code, we are still missing a few cases. Reviewers: ilya-biryukov Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D55191 Modified: clang-tools-extra/trunk/clangd/XRefs.cpp clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp Modified: clang-tools-extra/trunk/clangd/XRefs.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.cpp?rev=349033&r1=349032&r2=349033&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/XRefs.cpp (original) +++ clang-tools-extra/trunk/clangd/XRefs.cpp Thu Dec 13 05:17:04 2018 @@ -139,21 +139,19 @@ public: 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<ExprWithCleanups>(FirstChild) || - isa<MaterializeTemporaryExpr>(FirstChild) || - isa<CXXBindTemporaryExpr>(FirstChild) || - isa<ImplicitCastExpr>(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<CXXConstructExpr>(E)) + return CtorExpr->getNumArgs() > 0 && + CtorExpr->getParenOrBraceRange().isInvalid(); + return isa<ImplicitCastExpr>(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 Modified: clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp?rev=349033&r1=349032&r2=349033&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp Thu Dec 13 05:17:04 2018 @@ -1225,6 +1225,53 @@ TEST(FindReferences, WithinAST) { } } +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<Matcher<Location>> 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]](); }"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits