Skip to content

Commit 9dfb843

Browse files
authored
[include-cleaner] Use FoundDecl only for using-shadow-decls (#82615)
1 parent de04b7d commit 9dfb843

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

clang-tools-extra/include-cleaner/lib/WalkAST.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
128128

129129
bool VisitDeclRefExpr(DeclRefExpr *DRE) {
130130
auto *FD = DRE->getFoundDecl();
131+
// Prefer the underlying decl if FoundDecl isn't a shadow decl, e.g:
132+
// - For templates, found-decl is always primary template, but we want the
133+
// specializaiton itself.
134+
if (!llvm::isa<UsingShadowDecl>(FD))
135+
FD = DRE->getDecl();
131136
// For refs to non-meber-like decls, use the found decl.
132137
// For member-like decls, we should have a reference from the qualifier to
133138
// the container decl instead, which is preferred as it'll handle

clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -200,24 +200,26 @@ TEST(WalkAST, VarTemplates) {
200200
EXPECT_THAT(testWalk(R"cpp(
201201
template <typename T> T $explicit^Foo = 0;)cpp",
202202
"int z = ^Foo<int>;"),
203-
ElementsAre(Decl::VarTemplate));
203+
ElementsAre(Decl::VarTemplateSpecialization));
204204
EXPECT_THAT(testWalk(R"cpp(
205-
template<typename T> T $explicit^Foo = 0;
206-
template<> int Foo<int> = 1;)cpp",
205+
template<typename T> T Foo = 0;
206+
template<> int $explicit^Foo<int> = 1;)cpp",
207207
"int x = ^Foo<int>;"),
208-
ElementsAre(Decl::VarTemplate));
208+
ElementsAre(Decl::VarTemplateSpecialization));
209209
// FIXME: This points at implicit specialization, instead we should point to
210210
// explicit partial specializaiton pattern.
211211
EXPECT_THAT(testWalk(R"cpp(
212-
template<typename T> T $explicit^Foo = 0;
213-
template<typename T> T* Foo<T*> = nullptr;)cpp",
212+
template<typename T> T Foo = 0;
213+
template<typename T> T* $explicit^Foo<T*> = nullptr;)cpp",
214214
"int *x = ^Foo<int *>;"),
215-
ElementsAre(Decl::VarTemplate));
215+
ElementsAre(Decl::VarTemplateSpecialization));
216+
// Implicit specializations through explicit instantiations has source
217+
// locations pointing at the primary template.
216218
EXPECT_THAT(testWalk(R"cpp(
217219
template<typename T> T $explicit^Foo = 0;
218220
template int Foo<int>;)cpp",
219221
"int x = ^Foo<int>;"),
220-
ElementsAre(Decl::VarTemplate));
222+
ElementsAre(Decl::VarTemplateSpecialization));
221223
}
222224
TEST(WalkAST, FunctionTemplates) {
223225
// Explicit instantiation and (partial) specialization references primary
@@ -239,18 +241,19 @@ TEST(WalkAST, FunctionTemplates) {
239241
EXPECT_THAT(testWalk(R"cpp(
240242
template <typename T> void $explicit^foo() {})cpp",
241243
"auto x = []{ ^foo<int>(); };"),
242-
ElementsAre(Decl::FunctionTemplate));
243-
// FIXME: DeclRefExpr points at primary template, not the specialization.
244+
ElementsAre(Decl::Function));
244245
EXPECT_THAT(testWalk(R"cpp(
245-
template<typename T> void $explicit^foo() {}
246-
template<> void foo<int>(){})cpp",
246+
template<typename T> void foo() {}
247+
template<> void $explicit^foo<int>(){})cpp",
247248
"auto x = []{ ^foo<int>(); };"),
248-
ElementsAre(Decl::FunctionTemplate));
249+
ElementsAre(Decl::Function));
250+
// The decl is actually the specialization, but explicit instantations point
251+
// at the primary template.
249252
EXPECT_THAT(testWalk(R"cpp(
250253
template<typename T> void $explicit^foo() {};
251254
template void foo<int>();)cpp",
252255
"auto x = [] { ^foo<int>(); };"),
253-
ElementsAre(Decl::FunctionTemplate));
256+
ElementsAre(Decl::Function));
254257
}
255258
TEST(WalkAST, TemplateSpecializationsFromUsingDecl) {
256259
// Class templates
@@ -548,7 +551,8 @@ TEST(WalkAST, Concepts) {
548551
testWalk(Concept, "template<typename T> void func() requires ^Foo<T> {}");
549552
testWalk(Concept, "void func(^Foo auto x) {}");
550553
// FIXME: Foo should be explicitly referenced.
551-
testWalk("template<typename T> concept Foo = true;", "void func() { ^Foo auto x = 1; }");
554+
testWalk("template<typename T> concept Foo = true;",
555+
"void func() { ^Foo auto x = 1; }");
552556
}
553557

554558
TEST(WalkAST, FriendDecl) {

0 commit comments

Comments
 (0)