[clang-tools-extra] [include-cleaner] Respect the UsingShadowDecl when find headers for ambiguous std symbols. (PR #66485)

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 15 03:05:36 PDT 2023


https://github.com/hokein created https://github.com/llvm/llvm-project/pull/66485

In libcpp, the `std::remove(const char*)` is a using decl in std namespace `using ::remove`, which was not handled correctly in `headerForAmbiguousStdSymbol`

>From ffd109a7b4273d6a1dc5810b64039a110a4147c9 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Fri, 15 Sep 2023 11:59:06 +0200
Subject: [PATCH] [include-cleaner] Respect the UsingShadowDecl when find
 headers for ambiguous std symbols.

In libcpp, the `std::remove(const char*)` is a using decl in std
namespace `using ::remove`, which was not handled correctly in
`headerForAmbiguousStdSymbol`
---
 .../include-cleaner/lib/FindHeaders.cpp       |  3 ++
 .../unittests/FindHeadersTest.cpp             | 31 +++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
index 06e5e1812ba7218..fd2de6a17ad4a53 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<tooling::stdlib::Header>
 headerForAmbiguousStdSymbol(const NamedDecl *ND) {
   if (!ND->isInStdNamespace())
     return {};
+  if (auto* USD = llvm::dyn_cast<UsingShadowDecl>(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 4cdcde1184a0a9e..5a2a41b2d99bdd7 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<Visitor> {
+    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("<cstdio>"))));
+}
+
+
 TEST_F(HeadersForSymbolTest, StandardHeaders) {
   Inputs.Code = "void assert();";
   buildAST();



More information about the cfe-commits mailing list