forked from OSchip/llvm-project
[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 llvm-svn: 349033
This commit is contained in:
parent
e58e0903e2
commit
bf28533726
|
@ -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
|
||||
|
|
|
@ -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]](); }");
|
||||
|
|
Loading…
Reference in New Issue