diff --git a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp index 06e5e1812ba72..fd2de6a17ad4a 100644 --- a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp +++ b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/FileEntry.h" #include "clang/Basic/SourceLocation.h" @@ -116,6 +117,8 @@ std::optional headerForAmbiguousStdSymbol(const NamedDecl *ND) { if (!ND->isInStdNamespace()) return {}; + if (auto* USD = llvm::dyn_cast(ND)) + ND = USD->getTargetDecl(); const auto *FD = ND->getAsFunction(); if (!FD) return std::nullopt; diff --git a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp index 4cdcde1184a0a..5a2a41b2d99bd 100644 --- a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp @@ -11,6 +11,7 @@ #include "clang-include-cleaner/Analysis.h" #include "clang-include-cleaner/Record.h" #include "clang-include-cleaner/Types.h" +#include "clang/AST/Expr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/FileEntry.h" #include "clang/Basic/FileManager.h" @@ -587,6 +588,36 @@ TEST_F(HeadersForSymbolTest, AmbiguousStdSymbols) { } } +TEST_F(HeadersForSymbolTest, AmbiguousStdSymbolsUsingShadow) { + Inputs.Code = R"cpp( + void remove(char*); + namespace std { using ::remove; } + + void k() { + std::remove("abc"); + } + )cpp"; + buildAST(); + + // Find the DeclRefExpr in the std::remove("abc") function call. + struct Visitor : public RecursiveASTVisitor { + const DeclRefExpr *Out = nullptr; + bool VisitDeclRefExpr(const DeclRefExpr *DRE) { + EXPECT_TRUE(Out == nullptr) << "Found multiple DeclRefExpr!"; + Out = DRE; + return true; + } + }; + Visitor V; + V.TraverseDecl(AST->context().getTranslationUnitDecl()); + ASSERT_TRUE(V.Out) << "Couldn't find a DeclRefExpr!"; + EXPECT_THAT(headersForSymbol(*(V.Out->getFoundDecl()), + AST->sourceManager(), &PI), + UnorderedElementsAre( + Header(*tooling::stdlib::Header::named("")))); +} + + TEST_F(HeadersForSymbolTest, StandardHeaders) { Inputs.Code = "void assert();"; buildAST();