https://github.com/kadircet created 
https://github.com/llvm/llvm-project/pull/123027

Our stdlib mappings are based on names, hence they can't handle special
symbols like oprators.

Global operator new/delete show up often enough in practice to create
some user frustration, so we map these to <new>.


From 5339f8e303a99b8a75320b24a3a371e531fa6140 Mon Sep 17 00:00:00 2001
From: Kadir Cetinkaya <kadir...@google.com>
Date: Wed, 15 Jan 2025 10:11:09 +0100
Subject: [PATCH] [include-cleaner] Add special mappings for operator
 new/delete

Our stdlib mappings are based on names, hence they can't handle special
symbols like oprators.

Global operator new/delete show up often enough in practice to create
some user frustration, so we map these to <new>.
---
 .../include-cleaner/lib/FindHeaders.cpp       | 17 ++++++-
 .../unittests/FindHeadersTest.cpp             | 45 +++++++++++++++++++
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp 
b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
index 7b28d1c252d715..e6a642ae8ed48a 100644
--- a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
+++ b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/FileEntry.h"
+#include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Tooling/Inclusions/StandardLibrary.h"
@@ -157,8 +158,22 @@ headersForSpecialSymbol(const Symbol &S, const 
SourceManager &SM,
   if (!ND)
     return std::nullopt;
   auto *II = ND->getIdentifier();
-  if (!II)
+  if (!II) {
+    // Special case global operator new/delete, these show up often enough in
+    // practice and stdlib mappings can't work with them as they're symbol-name
+    // based.
+    if (ND->getDeclContext()->isTranslationUnit()) {
+      switch (ND->getDeclName().getCXXOverloadedOperator()) {
+      case OverloadedOperatorKind::OO_New:
+      case OverloadedOperatorKind::OO_Delete:
+        return hintedHeadersForStdHeaders(
+            {tooling::stdlib::Header::named("<new>").value()}, SM, PI);
+      default:
+        break;
+      }
+    }
     return std::nullopt;
+  }
 
   // Check first for symbols that are part of our stdlib mapping. As we have
   // header names for those.
diff --git a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
index 84e02e1d0d621b..d5b0a61ed1dfcb 100644
--- a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
@@ -11,11 +11,13 @@
 #include "clang-include-cleaner/Analysis.h"
 #include "clang-include-cleaner/Record.h"
 #include "clang-include-cleaner/Types.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/FileEntry.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/OperatorKinds.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Testing/TestAST.h"
 #include "clang/Tooling/Inclusions/StandardLibrary.h"
@@ -617,6 +619,49 @@ TEST_F(HeadersForSymbolTest, 
AmbiguousStdSymbolsUsingShadow) {
                   Header(*tooling::stdlib::Header::named("<cstdio>"))));
 }
 
+TEST_F(HeadersForSymbolTest, GlobalOperatorNewDelete) {
+  Inputs.Code = R"cpp(
+    void k() {
+      int *x;
+      // make sure operator new/delete are part of TU.
+      x = static_cast<int*>(::operator new(sizeof(int)));
+      ::operator delete(x);
+    }
+  )cpp";
+  buildAST();
+
+  // Find global new/delete operators.
+  struct Visitor : public DynamicRecursiveASTVisitor {
+    const NamedDecl *New = nullptr;
+    const NamedDecl *Delete = nullptr;
+    bool VisitNamedDecl(NamedDecl *ND) override {
+      if (!ND->getDeclContext()->isTranslationUnit())
+        return true;
+      switch (ND->getDeclName().getCXXOverloadedOperator()) {
+      case OO_New:
+        New = ND;
+        break;
+      case OO_Delete:
+        Delete = ND;
+        break;
+      default:
+        break;
+      }
+      return true;
+    }
+  };
+  Visitor V;
+  V.ShouldVisitImplicitCode = true;
+  V.TraverseDecl(AST->context().getTranslationUnitDecl());
+  ASSERT_TRUE(V.New) << "Couldn't find global new!";
+  ASSERT_TRUE(V.Delete) << "Couldn't find global delete!";
+  EXPECT_THAT(headersForSymbol(*V.New, AST->sourceManager(), &PI),
+              UnorderedElementsAre(
+                  Header(*tooling::stdlib::Header::named("<new>"))));
+  EXPECT_THAT(headersForSymbol(*V.Delete, AST->sourceManager(), &PI),
+              UnorderedElementsAre(
+                  Header(*tooling::stdlib::Header::named("<new>"))));
+}
 
 TEST_F(HeadersForSymbolTest, StandardHeaders) {
   Inputs.Code = R"cpp(

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to