https://github.com/vbvictor created 
https://github.com/llvm/llvm-project/pull/144270

Before this patch, the following code gave misleading diagnostics about absence 
of `#include <new>`:
```cpp
struct X { int n; };
int foo() {
  const X cx = {5};
  // error: no matching 'operator new' function for non-allocating placement 
new expression; include <new>
  (void)new(&cx) X{10};
};
```
Now it gives correct diagnostics about constness of passed argument:
```cpp
struct X { int n; };
int foo() {
  const X cx = {5};
  // error: placement new expression with a const-qualified argument of type 
'const X *' is not allowed
  (void)new(&cx) X{10};
};
```

Fixes https://github.com/llvm/llvm-project/issues/143708.

>From 07392e16740d3d89700da43e22b4d90197bb4d4a Mon Sep 17 00:00:00 2001
From: Victor Baranov <bar.victor.2...@gmail.com>
Date: Sun, 15 Jun 2025 19:56:05 +0300
Subject: [PATCH] [Clang] Improve diagnostics when 'placement new' was called
 with const storage argument

---
 clang/docs/ReleaseNotes.rst                      |  2 ++
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  3 +++
 clang/lib/Sema/SemaExprCXX.cpp                   | 10 +++++++++-
 clang/test/SemaCXX/new-delete.cpp                |  7 +++++++
 4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 33ee8a53b5f37..9fdc8660a981e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -629,6 +629,8 @@ Improvements to Clang's diagnostics
   #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
   #GH36703, #GH32903, #GH23312, #GH69874.
 
+- Improve the diagnostics for placement new expression when const-qualified
+  object was passed as the storage argument.
 
 Improvements to Clang's time-trace
 ----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8fe7ad6138aa0..0bc1e7deff5ab 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8285,6 +8285,9 @@ def err_need_header_before_typeid : Error<
 def err_need_header_before_placement_new : Error<
   "no matching %0 function for non-allocating placement new expression; "
   "include <new>">;
+def err_placement_new_into_const_qualified_storage : Error<
+  "placement new expression with a const-qualified argument of type %0 "
+  "is not allowed">;
 def err_ms___leave_not_in___try : Error<
   "'__leave' statement not in __try block">;
 def err_uuidof_without_guid : Error<
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index ba52e8f8932d3..e9cd40b9061d0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2753,10 +2753,18 @@ static bool resolveAllocationOverloadInterior(
     if (Diagnose) {
       // If this is an allocation of the form 'new (p) X' for some object
       // pointer p (or an expression that will decay to such a pointer),
-      // diagnose the missing inclusion of <new>.
+      // diagnose potential error.
       if (!R.isClassLookup() && Args.size() == 2 &&
           (Args[1]->getType()->isObjectPointerType() ||
            Args[1]->getType()->isArrayType())) {
+        if (Args[1]->getType()->isPointerType()) {
+          if (Args[1]->getType()->getPointeeType().isConstQualified()) {
+            S.Diag(Args[1]->getExprLoc(),
+                   diag::err_placement_new_into_const_qualified_storage)
+                << Args[1]->getType() << Args[1]->getSourceRange();
+            return true;
+          }
+        }
         S.Diag(R.getNameLoc(), diag::err_need_header_before_placement_new)
             << R.getLookupName() << Range;
         // Listing the candidates is unlikely to be useful; skip it.
diff --git a/clang/test/SemaCXX/new-delete.cpp 
b/clang/test/SemaCXX/new-delete.cpp
index 9bbee32c58c36..fae9487cbe2c1 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -160,6 +160,13 @@ void bad_news(int *ip)
 #if __cplusplus < 201103L
   (void)new int[]{}; // expected-error {{array size must be specified in new 
expression with no initializer}}
 #endif
+  struct X { int n; };
+  const X cx = {5};
+  (void)new(&cx) X{10}; // expected-error {{placement new expression with a 
const-qualified argument of type 'const X *' is not allowed}}
+  const X* const cx2 = 0;
+  (void)new(cx2) X{10}; // expected-error {{placement new expression with a 
const-qualified argument of type 'const X *const' is not allowed}}
+  const int arr[1] = {1};
+  (void)new(&arr[0]) int(10); // expected-error {{placement new expression 
with a const-qualified argument of type 'const int *' is not allowed}}
 }
 
 void no_matching_placement_new() {

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

Reply via email to