forked from OSchip/llvm-project
[clangd] Don't set the Underlying bit on targets of UsingDecls.
With this patch, we don't treat `using ns::X` as a first-class declaration like `using Z = ns::Y`, reference to X that goes through this using-decl is considered a direct reference (without the Underlying bit). Fix the workaround in https://reviews.llvm.org/D87225 and https://reviews.llvm.org/D74054. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D88472
This commit is contained in:
parent
31dc908017
commit
f24649b77d
|
@ -342,8 +342,9 @@ public:
|
|||
add(TND->getUnderlyingType(), Flags | Rel::Underlying);
|
||||
Flags |= Rel::Alias; // continue with the alias.
|
||||
} else if (const UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
|
||||
// no Underlying as this is a non-renaming alias.
|
||||
for (const UsingShadowDecl *S : UD->shadows())
|
||||
add(S->getUnderlyingDecl(), Flags | Rel::Underlying);
|
||||
add(S->getUnderlyingDecl(), Flags);
|
||||
Flags |= Rel::Alias; // continue with the alias.
|
||||
} else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) {
|
||||
add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying);
|
||||
|
@ -354,7 +355,7 @@ public:
|
|||
UUVD->getQualifier()->getAsType(),
|
||||
[UUVD](ASTContext &) { return UUVD->getNameInfo().getName(); },
|
||||
ValueFilter)) {
|
||||
add(Target, Flags | Rel::Underlying);
|
||||
add(Target, Flags); // no Underlying as this is a non-renaming alias
|
||||
}
|
||||
Flags |= Rel::Alias; // continue with the alias
|
||||
} else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
|
||||
|
@ -364,7 +365,6 @@ public:
|
|||
// Shadow decls are synthetic and not themselves interesting.
|
||||
// Record the underlying decl instead, if allowed.
|
||||
D = USD->getTargetDecl();
|
||||
Flags |= Rel::Underlying; // continue with the underlying decl.
|
||||
} else if (const auto *DG = dyn_cast<CXXDeductionGuideDecl>(D)) {
|
||||
D = DG->getDeducedTemplate();
|
||||
} else if (const ObjCImplementationDecl *IID =
|
||||
|
|
|
@ -102,13 +102,20 @@ enum class DeclRelation : unsigned {
|
|||
TemplatePattern,
|
||||
|
||||
// Alias options apply when the declaration is an alias.
|
||||
// e.g. namespace clang { [[StringRef]] S; }
|
||||
// e.g. namespace client { [[X]] x; }
|
||||
|
||||
/// This declaration is an alias that was referred to.
|
||||
/// e.g. using llvm::StringRef (the UsingDecl directly referenced).
|
||||
/// e.g. using ns::X (the UsingDecl directly referenced),
|
||||
/// using Z = ns::Y (the TypeAliasDecl directly referenced)
|
||||
Alias,
|
||||
/// This is the underlying declaration for an alias, decltype etc.
|
||||
/// e.g. class llvm::StringRef (the underlying declaration referenced).
|
||||
/// This is the underlying declaration for a renaming-alias, decltype etc.
|
||||
/// e.g. class ns::Y (the underlying declaration referenced).
|
||||
///
|
||||
/// Note that we don't treat `using ns::X` as a first-class declaration like
|
||||
/// `using Z = ns::Y`. Therefore reference to X that goes through this
|
||||
/// using-decl is considered a direct reference (without the Underlying bit).
|
||||
/// Nevertheless, we report `using ns::X` as an Alias, so that some features
|
||||
/// like go-to-definition can still target it.
|
||||
Underlying,
|
||||
};
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelation);
|
||||
|
|
|
@ -343,18 +343,6 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
|
|||
}
|
||||
}
|
||||
|
||||
// Give the underlying decl if navigation is triggered on a non-renaming
|
||||
// alias.
|
||||
if (llvm::isa<UsingDecl>(D) || llvm::isa<UnresolvedUsingValueDecl>(D)) {
|
||||
// FIXME: address more complicated cases. TargetDecl(... Underlying) gives
|
||||
// all overload candidates, we only want the targeted one if the cursor is
|
||||
// on an using-alias usage, workround it with getDeclAtPosition.
|
||||
llvm::for_each(
|
||||
getDeclAtPosition(AST, CurLoc, DeclRelation::Underlying, NodeKind),
|
||||
[&](const NamedDecl *UD) { AddResultDecl(UD); });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: if the class name is selected, also map Objective-C
|
||||
// categories and category implementations back to their class interface.
|
||||
//
|
||||
|
@ -1159,17 +1147,6 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
|
|||
DeclRelation::TemplatePattern | DeclRelation::Alias;
|
||||
std::vector<const NamedDecl *> Decls =
|
||||
getDeclAtPosition(AST, *CurLoc, Relations);
|
||||
std::vector<const NamedDecl *> NonrenamingAliasUnderlyingDecls;
|
||||
// If the results include a *non-renaming* alias, get its
|
||||
// underlying decls as well. (See similar logic in locateASTReferent()).
|
||||
for (const NamedDecl *D : Decls) {
|
||||
if (llvm::isa<UsingDecl>(D) || llvm::isa<UnresolvedUsingValueDecl>(D)) {
|
||||
for (const NamedDecl *AD :
|
||||
getDeclAtPosition(AST, *CurLoc, DeclRelation::Underlying))
|
||||
NonrenamingAliasUnderlyingDecls.push_back(AD);
|
||||
}
|
||||
}
|
||||
llvm::copy(NonrenamingAliasUnderlyingDecls, std::back_inserter(Decls));
|
||||
|
||||
// We traverse the AST to find references in the main file.
|
||||
auto MainFileRefs = findRefs(Decls, AST);
|
||||
|
|
|
@ -181,8 +181,7 @@ TEST_F(TargetDeclTest, UsingDecl) {
|
|||
int x = [[f]](42);
|
||||
)cpp";
|
||||
// f(char) is not referenced!
|
||||
EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
|
||||
{"int f(int)", Rel::Underlying});
|
||||
EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, {"int f(int)"});
|
||||
|
||||
Code = R"cpp(
|
||||
namespace foo {
|
||||
|
@ -192,9 +191,8 @@ TEST_F(TargetDeclTest, UsingDecl) {
|
|||
[[using foo::f]];
|
||||
)cpp";
|
||||
// All overloads are referenced.
|
||||
EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
|
||||
{"int f(int)", Rel::Underlying},
|
||||
{"int f(char)", Rel::Underlying});
|
||||
EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, {"int f(int)"},
|
||||
{"int f(char)"});
|
||||
|
||||
Code = R"cpp(
|
||||
struct X {
|
||||
|
@ -205,8 +203,7 @@ TEST_F(TargetDeclTest, UsingDecl) {
|
|||
};
|
||||
int x = Y().[[foo]]();
|
||||
)cpp";
|
||||
EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
|
||||
{"int foo()", Rel::Underlying});
|
||||
EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, {"int foo()"});
|
||||
|
||||
Code = R"cpp(
|
||||
template <typename T>
|
||||
|
@ -219,7 +216,7 @@ TEST_F(TargetDeclTest, UsingDecl) {
|
|||
};
|
||||
)cpp";
|
||||
EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::waldo", Rel::Alias},
|
||||
{"void waldo()", Rel::Underlying});
|
||||
{"void waldo()"});
|
||||
}
|
||||
|
||||
TEST_F(TargetDeclTest, ConstructorInitList) {
|
||||
|
|
|
@ -1118,17 +1118,18 @@ TEST(LocateSymbol, Alias) {
|
|||
// decls.
|
||||
R"cpp(
|
||||
namespace ns { class [[Foo]] {}; }
|
||||
using ns::F^oo;
|
||||
// FIXME: don't return the using decl if it touches the cursor position.
|
||||
using ns::[[F^oo]];
|
||||
)cpp",
|
||||
|
||||
R"cpp(
|
||||
namespace ns { int [[x]](char); int [[x]](double); }
|
||||
using ns::^x;
|
||||
using ns::[[^x]];
|
||||
)cpp",
|
||||
|
||||
R"cpp(
|
||||
namespace ns { int [[x]](char); int x(double); }
|
||||
using ns::x;
|
||||
using ns::[[x]];
|
||||
int y = ^x('a');
|
||||
)cpp",
|
||||
|
||||
|
@ -1156,7 +1157,7 @@ TEST(LocateSymbol, Alias) {
|
|||
};
|
||||
template <typename T>
|
||||
struct Derived : Base<T> {
|
||||
using Base<T>::w^aldo;
|
||||
using Base<T>::[[w^aldo]];
|
||||
};
|
||||
)cpp",
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue