[clang] 31d7b51 - [Clang] Add missing release note entry in #226753 (#227078)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 28 19:14:32 PDT 2026
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()'}}
More information about the cfe-commits
mailing list