Skip to content

Commit 7b3db80

Browse files
authored
[include-cleaner] Respect the UsingShadowDecl when find headers for ambiguous std symbols. (#66485)
In libcpp, the `std::remove(const char*)` is a using decl in std namespace `using ::remove`, which was not handled correctly in `headerForAmbiguousStdSymbol`
1 parent 8b4ca0a commit 7b3db80

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/AST/ASTContext.h"
1414
#include "clang/AST/Decl.h"
1515
#include "clang/AST/DeclBase.h"
16+
#include "clang/AST/DeclCXX.h"
1617
#include "clang/Basic/Builtins.h"
1718
#include "clang/Basic/FileEntry.h"
1819
#include "clang/Basic/SourceLocation.h"
@@ -116,6 +117,8 @@ std::optional<tooling::stdlib::Header>
116117
headerForAmbiguousStdSymbol(const NamedDecl *ND) {
117118
if (!ND->isInStdNamespace())
118119
return {};
120+
if (auto* USD = llvm::dyn_cast<UsingShadowDecl>(ND))
121+
ND = USD->getTargetDecl();
119122
const auto *FD = ND->getAsFunction();
120123
if (!FD)
121124
return std::nullopt;

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "clang-include-cleaner/Analysis.h"
1212
#include "clang-include-cleaner/Record.h"
1313
#include "clang-include-cleaner/Types.h"
14+
#include "clang/AST/Expr.h"
1415
#include "clang/AST/RecursiveASTVisitor.h"
1516
#include "clang/Basic/FileEntry.h"
1617
#include "clang/Basic/FileManager.h"
@@ -587,6 +588,36 @@ TEST_F(HeadersForSymbolTest, AmbiguousStdSymbols) {
587588
}
588589
}
589590

591+
TEST_F(HeadersForSymbolTest, AmbiguousStdSymbolsUsingShadow) {
592+
Inputs.Code = R"cpp(
593+
void remove(char*);
594+
namespace std { using ::remove; }
595+
596+
void k() {
597+
std::remove("abc");
598+
}
599+
)cpp";
600+
buildAST();
601+
602+
// Find the DeclRefExpr in the std::remove("abc") function call.
603+
struct Visitor : public RecursiveASTVisitor<Visitor> {
604+
const DeclRefExpr *Out = nullptr;
605+
bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
606+
EXPECT_TRUE(Out == nullptr) << "Found multiple DeclRefExpr!";
607+
Out = DRE;
608+
return true;
609+
}
610+
};
611+
Visitor V;
612+
V.TraverseDecl(AST->context().getTranslationUnitDecl());
613+
ASSERT_TRUE(V.Out) << "Couldn't find a DeclRefExpr!";
614+
EXPECT_THAT(headersForSymbol(*(V.Out->getFoundDecl()),
615+
AST->sourceManager(), &PI),
616+
UnorderedElementsAre(
617+
Header(*tooling::stdlib::Header::named("<cstdio>"))));
618+
}
619+
620+
590621
TEST_F(HeadersForSymbolTest, StandardHeaders) {
591622
Inputs.Code = "void assert();";
592623
buildAST();

0 commit comments

Comments
 (0)