https://github.com/Aethezz updated 
https://github.com/llvm/llvm-project/pull/150161

>From a018c87c6356326cb04bd0a98ff5842e07403f9c Mon Sep 17 00:00:00 2001
From: Aethezz <64500703+aeth...@users.noreply.github.com>
Date: Tue, 22 Jul 2025 23:19:11 -0400
Subject: [PATCH 1/3] fix false positive, warning is now only triggered when
 the place size is strictly less than target size. Add test cases for when
 place size == or > or < than target size.

---
 .../Checkers/CheckPlacementNew.cpp            | 28 ++++---------------
 clang/test/SemaCXX/placement-new-bounds.cpp   | 25 +++++++++++++++++
 2 files changed, 30 insertions(+), 23 deletions(-)
 create mode 100644 clang/test/SemaCXX/placement-new-bounds.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp 
b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
index 839c8bcd90210..4c4ca15efa4c9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
@@ -111,32 +111,14 @@ bool PlacementNewChecker::checkPlaceCapacityIsSufficient(
   if (!SizeOfPlaceCI)
     return true;
 
-  if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue()) ||
-      (IsArrayTypeAllocated &&
-       SizeOfPlaceCI->getValue() >= SizeOfTargetCI->getValue())) {
+  if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue())) {
     if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
       std::string Msg;
       // TODO: use clang constant
-      if (IsArrayTypeAllocated &&
-          SizeOfPlaceCI->getValue() > SizeOfTargetCI->getValue())
-        Msg = std::string(llvm::formatv(
-            "{0} bytes is possibly not enough for array allocation which "
-            "requires {1} bytes. Current overhead requires the size of {2} "
-            "bytes",
-            SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue(),
-            *SizeOfPlaceCI->getValue() - SizeOfTargetCI->getValue()));
-      else if (IsArrayTypeAllocated &&
-               SizeOfPlaceCI->getValue() == SizeOfTargetCI->getValue())
-        Msg = std::string(llvm::formatv(
-            "Storage provided to placement new is only {0} bytes, "
-            "whereas the allocated array type requires more space for "
-            "internal needs",
-            SizeOfPlaceCI->getValue()));
-      else
-        Msg = std::string(llvm::formatv(
-            "Storage provided to placement new is only {0} bytes, "
-            "whereas the allocated type requires {1} bytes",
-            SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue()));
+      Msg = std::string(llvm::formatv(
+          "Storage provided to placement new is only {0} bytes, "
+          "whereas the allocated type requires {1} bytes",
+          SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue()));
 
       auto R = std::make_unique<PathSensitiveBugReport>(SBT, Msg, N);
       bugreporter::trackExpressionValue(N, NE->getPlacementArg(0), *R);
diff --git a/clang/test/SemaCXX/placement-new-bounds.cpp 
b/clang/test/SemaCXX/placement-new-bounds.cpp
new file mode 100644
index 0000000000000..49a7352922140
--- /dev/null
+++ b/clang/test/SemaCXX/placement-new-bounds.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang -fsyntax-only -Xclang -analyze -Xclang 
-analyzer-checker=cplusplus.PlacementNew -Xclang -verify -std=c++17 %s
+
+#include <new>
+
+void test_exact_size() {
+    void *buf = ::operator new(sizeof(int)*2);
+    int *placement_int = new (buf) int[2]; // no-warning
+    placement_int[0] = 42;
+    ::operator delete(buf);
+}
+
+void test_undersize() {
+    void *buf = ::operator new(sizeof(int)*1);
+    // Remember the exact text including the checker name, or use regex for 
robustness.
+    int *placement_int = new (buf) int[2]; // expected-warning {{Storage 
provided to placement new is only 4 bytes, whereas the allocated type requires 
8 bytes [cplusplus.PlacementNew]}}
+    placement_int[0] = 42;
+    ::operator delete(buf);
+}
+
+void test_oversize() {
+    void *buf = ::operator new(sizeof(int)*4);
+    int *placement_int = new (buf) int[2]; // no-warning
+    placement_int[0] = 42;
+    ::operator delete(buf);
+}
\ No newline at end of file

>From d3e79946cf09a8c87e152b836b0b4f324c6cdd42 Mon Sep 17 00:00:00 2001
From: Aethezz <ellisonlao...@gmail.com>
Date: Wed, 23 Jul 2025 12:27:27 -0400
Subject: [PATCH 2/3] Fixed formatting issues and removed expected warnings
 from other test cases

---
 clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp | 8 ++++----
 clang/test/Analysis/placement-new.cpp                   | 8 ++++----
 clang/test/SemaCXX/placement-new-bounds.cpp             | 1 -
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp 
b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
index 4c4ca15efa4c9..2a57fa2e8ff4a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
@@ -115,10 +115,10 @@ bool PlacementNewChecker::checkPlaceCapacityIsSufficient(
     if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
       std::string Msg;
       // TODO: use clang constant
-      Msg = std::string(llvm::formatv(
-          "Storage provided to placement new is only {0} bytes, "
-          "whereas the allocated type requires {1} bytes",
-          SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue()));
+      Msg = std::string(
+          llvm::formatv("Storage provided to placement new is only {0} bytes, "
+                        "whereas the allocated type requires {1} bytes",
+                        SizeOfPlaceCI->getValue(), 
SizeOfTargetCI->getValue()));
 
       auto R = std::make_unique<PathSensitiveBugReport>(SBT, Msg, N);
       bugreporter::trackExpressionValue(N, NE->getPlacementArg(0), *R);
diff --git a/clang/test/Analysis/placement-new.cpp 
b/clang/test/Analysis/placement-new.cpp
index 766b11cf84c5f..82d1d87c59792 100644
--- a/clang/test/Analysis/placement-new.cpp
+++ b/clang/test/Analysis/placement-new.cpp
@@ -168,8 +168,8 @@ void f1() {
 
   // bad (not enough space).
   const unsigned N = 32;
-  alignas(S) unsigned char buffer1[sizeof(S) * N]; // expected-note 
{{'buffer1' initialized here}}
-  ::new (buffer1) S[N];                            // 
expected-warning{{Storage provided to placement new is only 64 bytes, whereas 
the allocated array type requires more space for internal needs}} expected-note 
1 {{}}
+  alignas(S) unsigned char buffer1[sizeof(S) * N]; 
+  ::new (buffer1) S[N];                           
 }
 
 void f2() {
@@ -179,8 +179,8 @@ void f2() {
 
   // maybe ok but we need to warn.
   const unsigned N = 32;
-  alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; // 
expected-note {{'buffer2' initialized here}}
-  ::new (buffer2) S[N];                                          // 
expected-warning{{68 bytes is possibly not enough for array allocation which 
requires 64 bytes. Current overhead requires the size of 4 bytes}} 
expected-note 1 {{}}
+  alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; 
+  ::new (buffer2) S[N];                                         
 }
 } // namespace testArrayTypesAllocation
 
diff --git a/clang/test/SemaCXX/placement-new-bounds.cpp 
b/clang/test/SemaCXX/placement-new-bounds.cpp
index 49a7352922140..89bfb1292fc3e 100644
--- a/clang/test/SemaCXX/placement-new-bounds.cpp
+++ b/clang/test/SemaCXX/placement-new-bounds.cpp
@@ -11,7 +11,6 @@ void test_exact_size() {
 
 void test_undersize() {
     void *buf = ::operator new(sizeof(int)*1);
-    // Remember the exact text including the checker name, or use regex for 
robustness.
     int *placement_int = new (buf) int[2]; // expected-warning {{Storage 
provided to placement new is only 4 bytes, whereas the allocated type requires 
8 bytes [cplusplus.PlacementNew]}}
     placement_int[0] = 42;
     ::operator delete(buf);

>From b93bd2cfdf3b8299c952e60a64e0c378e6f81b47 Mon Sep 17 00:00:00 2001
From: Aethezz <ellisonlao...@gmail.com>
Date: Fri, 25 Jul 2025 14:32:48 -0400
Subject: [PATCH 3/3] removed the redundant test file, update comments in
 placement-new.cpp test file to explain the removal of checker warning the
 rare case of allocating extra memory, and removed std::string explicit
 conversion operator

---
 .../Checkers/CheckPlacementNew.cpp            |  7 +++---
 clang/test/Analysis/placement-new.cpp         |  6 +++--
 clang/test/SemaCXX/placement-new-bounds.cpp   | 24 -------------------
 3 files changed, 7 insertions(+), 30 deletions(-)
 delete mode 100644 clang/test/SemaCXX/placement-new-bounds.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp 
b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
index 2a57fa2e8ff4a..a4ea359758f14 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
@@ -113,12 +113,11 @@ bool PlacementNewChecker::checkPlaceCapacityIsSufficient(
 
   if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue())) {
     if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
-      std::string Msg;
-      // TODO: use clang constant
-      Msg = std::string(
+      std::string Msg =
           llvm::formatv("Storage provided to placement new is only {0} bytes, "
                         "whereas the allocated type requires {1} bytes",
-                        SizeOfPlaceCI->getValue(), 
SizeOfTargetCI->getValue()));
+                        SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue());
+      // TODO: use clang constants
 
       auto R = std::make_unique<PathSensitiveBugReport>(SBT, Msg, N);
       bugreporter::trackExpressionValue(N, NE->getPlacementArg(0), *R);
diff --git a/clang/test/Analysis/placement-new.cpp 
b/clang/test/Analysis/placement-new.cpp
index 82d1d87c59792..db3717286bf8f 100644
--- a/clang/test/Analysis/placement-new.cpp
+++ b/clang/test/Analysis/placement-new.cpp
@@ -166,7 +166,8 @@ void f1() {
     short a;
   };
 
-  // bad (not enough space).
+  // on some systems, placement array new may allocate more memory than the 
nominal size of the array
+  // in such cases, test code could be problematic, but the checker doesn't 
warn here because this behavior is expected to be rare
   const unsigned N = 32;
   alignas(S) unsigned char buffer1[sizeof(S) * N]; 
   ::new (buffer1) S[N];                           
@@ -177,7 +178,8 @@ void f2() {
     short a;
   };
 
-  // maybe ok but we need to warn.
+  // on some systems, placement array new may allocate more memory than the 
nominal size of the array
+  // in such cases, test code could be problematic, but the checker doesn't 
warn here because this behavior is expected to be rare
   const unsigned N = 32;
   alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; 
   ::new (buffer2) S[N];                                         
diff --git a/clang/test/SemaCXX/placement-new-bounds.cpp 
b/clang/test/SemaCXX/placement-new-bounds.cpp
deleted file mode 100644
index 89bfb1292fc3e..0000000000000
--- a/clang/test/SemaCXX/placement-new-bounds.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %clang -fsyntax-only -Xclang -analyze -Xclang 
-analyzer-checker=cplusplus.PlacementNew -Xclang -verify -std=c++17 %s
-
-#include <new>
-
-void test_exact_size() {
-    void *buf = ::operator new(sizeof(int)*2);
-    int *placement_int = new (buf) int[2]; // no-warning
-    placement_int[0] = 42;
-    ::operator delete(buf);
-}
-
-void test_undersize() {
-    void *buf = ::operator new(sizeof(int)*1);
-    int *placement_int = new (buf) int[2]; // expected-warning {{Storage 
provided to placement new is only 4 bytes, whereas the allocated type requires 
8 bytes [cplusplus.PlacementNew]}}
-    placement_int[0] = 42;
-    ::operator delete(buf);
-}
-
-void test_oversize() {
-    void *buf = ::operator new(sizeof(int)*4);
-    int *placement_int = new (buf) int[2]; // no-warning
-    placement_int[0] = 42;
-    ::operator delete(buf);
-}
\ No newline at end of file

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

Reply via email to