Author: aokblast
Date: 2026-09-29T02:14:21Z
New Revision: 31d7b51dbd5a8a5e58631a3c77421209f562ea5c

URL: 
https://github.com/llvm/llvm-project/commit/31d7b51dbd5a8a5e58631a3c77421209f562ea5c
DIFF: 
https://github.com/llvm/llvm-project/commit/31d7b51dbd5a8a5e58631a3c77421209f562ea5c.diff

LOG: [Clang] Add missing release note entry in #226753 (#227078)

As per the feedback from #226753, we add release note for GH-212211.
Also move the test to new-delete.cpp.

Assisted-by: Claude

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/test/AST/ByteCode/new-delete.cpp

Removed: 
    clang/test/SemaCXX/new-nothrow-by-value.cpp


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b71758e4b9647..49d669db5749c 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -767,6 +767,11 @@ features cannot lower the translation-unit ABI level;
   lookup before asserting that the name is not dependent, avoiding an 
assertion 
   after an earlier diagnostic has caused the declaration to be unavailable. 
(#GH220525)
 
+- Fixed a crash in constant evaluation when a new-expression selects a
+  user-declared allocation function that takes std::nothrow_t by value. Such
+  a new-expression is now correctly rejected in a constant expression because
+  it does not select a replaceable global allocation function. (#GH212211)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made

diff  --git a/clang/test/AST/ByteCode/new-delete.cpp 
b/clang/test/AST/ByteCode/new-delete.cpp
index 24195d77962b8..e5ddd8eb2a037 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -343,6 +343,18 @@ namespace placement_new_delete {
     void operator delete(DestroyingDelete*, std::destroying_delete_t);
   };
   struct alignas(64) Overaligned {};
+  struct NothrowByValue {
+    void *operator new(std::size_t, std::nothrow_t) noexcept;
+    void *operator new[](std::size_t, std::nothrow_t) noexcept;
+  };
+
+  // Constant-folding the new-expression used to assume the (std::nothrow)
+  // placement argument was an lvalue and assert on the prvalue produced when a
+  // user-declared allocation function takes std::nothrow_t by value.
+  void nothrow_by_value_fold(NothrowByValue *p) {
+    p = (1 ? new (std::nothrow) NothrowByValue[1] : nullptr);
+    p = (1 ? new (std::nothrow) NothrowByValue : nullptr);
+  }
 
   constexpr bool ok() {
     delete new Overaligned;
@@ -376,6 +388,10 @@ namespace placement_new_delete {
       // unreasonable to expect implementations to support this.
       delete new (std::align_val_t{64}) Overaligned; // both-note {{this 
placement new expression is not supported in constant expressions}}
       break;
+
+    case 5:
+      delete new (std::nothrow) NothrowByValue; // both-note {{call to 
class-specific 'operator new'}}
+      break;
     }
 
     return true;
@@ -387,6 +403,7 @@ namespace placement_new_delete {
   static_assert(bad(3)); // both-error {{constant expression}} both-note {{in 
call}}
   static_assert(bad(4)); // both-error {{constant expression}} \
                          // both-note {{in call}}
+  static_assert(bad(5)); // both-error {{constant expression}} both-note {{in 
call}}
 }
 
 

diff  --git a/clang/test/SemaCXX/new-nothrow-by-value.cpp 
b/clang/test/SemaCXX/new-nothrow-by-value.cpp
deleted file mode 100644
index c2985ad582219..0000000000000
--- a/clang/test/SemaCXX/new-nothrow-by-value.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s 
-fexperimental-new-constant-interpreter
-
-// [expr.const] only permits a new-expression in a constant expression when it
-// selects a replaceable global allocation function. None of them take
-// std::nothrow_t by value, so a user-declared allocation function that does
-// must be rejected before examining its placement argument. The constant
-// evaluator used to assume the argument was always an lvalue and crashed on
-// the prvalue produced here.
-
-namespace std {
-inline constexpr struct nothrow_t {
-} nothrow;
-} // namespace std
-
-void *operator new[](__SIZE_TYPE__, std::nothrow_t) noexcept;
-void *operator new(__SIZE_TYPE__, std::nothrow_t) noexcept;
-
-void set(int *p) {
-  p = (1 ? new (std::nothrow) int[1] : nullptr);
-  p = (1 ? new (std::nothrow) int : nullptr);
-}
-
-constexpr bool by_value() { // expected-error {{constexpr function never 
produces a constant expression}}
-  int *p = new (std::nothrow) int; // expected-note 2{{call to placement 
'operator new'}}
-  delete p;
-  return true;
-}
-static_assert(by_value()); // expected-error {{not an integral constant 
expression}} expected-note {{in call to 'by_value()'}}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to