https://github.com/snarang181 updated 
https://github.com/llvm/llvm-project/pull/155737

>From 0b13b0e77e184666d46450b264e1237e6c41a1de Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Wed, 27 Aug 2025 22:45:25 -0400
Subject: [PATCH 1/6] Enable nullptr handle with negative elemsize in a dynamic
 allocation

---
 clang/lib/AST/ByteCode/Interp.h     |  7 ++++++-
 clang/test/SemaCXX/new-neg-size.cpp | 15 +++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaCXX/new-neg-size.cpp

diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 92e60b6b88e6a..e505712b60dd3 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3490,7 +3490,12 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, 
PrimType T, const Expr *Source,
     S.Stk.push<Pointer>(0, nullptr);
     return true;
   }
-  assert(NumElements.isPositive());
+  if (!NumElements.isPositive()) {
+    if (!IsNoThrow)
+      return false;
+    S.Stk.push<Pointer>(0, nullptr);
+    return true;
+  }
 
   if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
     return false;
diff --git a/clang/test/SemaCXX/new-neg-size.cpp 
b/clang/test/SemaCXX/new-neg-size.cpp
new file mode 100644
index 0000000000000..4b5a0d4bfe228
--- /dev/null
+++ b/clang/test/SemaCXX/new-neg-size.cpp
@@ -0,0 +1,15 @@
+// RUN: not %clang_cc1 -std=c++20 -fsyntax-only %s 2>&1 \
+// RUN:   | FileCheck %s --implicit-check-not='Assertion 
`NumElements.isPositive()` failed'
+
+// In C++20, constexpr dynamic allocation is permitted *only* if valid.
+// A negative element count must be diagnosed (and must not crash).
+
+constexpr void f_bad_neg() {
+  int a = -1;
+  (void) new int[a]; // triggers negative-size path in the interpreter
+}
+
+// Force evaluation so we definitely run the constexpr interpreter.
+constexpr bool force_eval = (f_bad_neg(), true);
+
+// CHECK: error: constexpr function never produces a constant expression

>From 6d28107ebb963803b3bf6c4ae09734ec1ec6b526 Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Wed, 27 Aug 2025 23:10:05 -0400
Subject: [PATCH 2/6] Add test case

---
 clang/test/SemaCXX/new-neg-size.cpp | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/clang/test/SemaCXX/new-neg-size.cpp 
b/clang/test/SemaCXX/new-neg-size.cpp
index 4b5a0d4bfe228..e03f34c183809 100644
--- a/clang/test/SemaCXX/new-neg-size.cpp
+++ b/clang/test/SemaCXX/new-neg-size.cpp
@@ -1,7 +1,7 @@
 // RUN: not %clang_cc1 -std=c++20 -fsyntax-only %s 2>&1 \
 // RUN:   | FileCheck %s --implicit-check-not='Assertion 
`NumElements.isPositive()` failed'
 
-// In C++20, constexpr dynamic allocation is permitted *only* if valid.
+// In C++20, constexpr dynamic allocation is permitted only if valid.
 // A negative element count must be diagnosed (and must not crash).
 
 constexpr void f_bad_neg() {
@@ -9,7 +9,17 @@ constexpr void f_bad_neg() {
   (void) new int[a]; // triggers negative-size path in the interpreter
 }
 
-// Force evaluation so we definitely run the constexpr interpreter.
-constexpr bool force_eval = (f_bad_neg(), true);
+struct __nothrow_t { };
+extern const __nothrow_t __nothrow_dummy;
+void* operator new[](unsigned long, const __nothrow_t&) noexcept;
 
-// CHECK: error: constexpr function never produces a constant expression
+// Ensure we take the nothrow overload.
+constexpr void f_bad_neg_nothrow() {
+  (void) new (__nothrow_dummy) int[-7]; // should evaluate to nullptr (no 
crash)
+}
+
+// Force evaluation so the constexpr interpreter actually runs both cases.
+constexpr bool force_eval1 = (f_bad_neg(), true);
+constexpr bool force_eval2 = (f_bad_neg_nothrow(), true);
+
+// CHECK: error: constexpr function {{(never produces|is not a)}} constant 
expression
\ No newline at end of file

>From 204c5995105abf8aa8c7949754ddecda2dd3e95e Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Wed, 27 Aug 2025 23:42:39 -0400
Subject: [PATCH 3/6] Revert "Add test case"

This reverts commit 6d28107ebb963803b3bf6c4ae09734ec1ec6b526.
---
 clang/test/SemaCXX/new-neg-size.cpp | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/clang/test/SemaCXX/new-neg-size.cpp 
b/clang/test/SemaCXX/new-neg-size.cpp
index e03f34c183809..4b5a0d4bfe228 100644
--- a/clang/test/SemaCXX/new-neg-size.cpp
+++ b/clang/test/SemaCXX/new-neg-size.cpp
@@ -1,7 +1,7 @@
 // RUN: not %clang_cc1 -std=c++20 -fsyntax-only %s 2>&1 \
 // RUN:   | FileCheck %s --implicit-check-not='Assertion 
`NumElements.isPositive()` failed'
 
-// In C++20, constexpr dynamic allocation is permitted only if valid.
+// In C++20, constexpr dynamic allocation is permitted *only* if valid.
 // A negative element count must be diagnosed (and must not crash).
 
 constexpr void f_bad_neg() {
@@ -9,17 +9,7 @@ constexpr void f_bad_neg() {
   (void) new int[a]; // triggers negative-size path in the interpreter
 }
 
-struct __nothrow_t { };
-extern const __nothrow_t __nothrow_dummy;
-void* operator new[](unsigned long, const __nothrow_t&) noexcept;
+// Force evaluation so we definitely run the constexpr interpreter.
+constexpr bool force_eval = (f_bad_neg(), true);
 
-// Ensure we take the nothrow overload.
-constexpr void f_bad_neg_nothrow() {
-  (void) new (__nothrow_dummy) int[-7]; // should evaluate to nullptr (no 
crash)
-}
-
-// Force evaluation so the constexpr interpreter actually runs both cases.
-constexpr bool force_eval1 = (f_bad_neg(), true);
-constexpr bool force_eval2 = (f_bad_neg_nothrow(), true);
-
-// CHECK: error: constexpr function {{(never produces|is not a)}} constant 
expression
\ No newline at end of file
+// CHECK: error: constexpr function never produces a constant expression

>From 21e1f9646cbfad9eece1fefa03a24519b5ffba3a Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Thu, 28 Aug 2025 09:18:05 -0400
Subject: [PATCH 4/6] Add nothrow test for negative size allocation in constant
 expressions Move test directory to AST/ Add Diagnostic Note for negative size
 allocation in constant expressions

---
 .../include/clang/Basic/DiagnosticASTKinds.td  |  2 ++
 clang/lib/AST/ByteCode/Interp.h                |  4 +++-
 .../test/AST/ByteCode/new-neg-size-nothrow.cpp | 18 ++++++++++++++++++
 clang/test/AST/ByteCode/new-neg-size.cpp       |  7 +++++++
 clang/test/SemaCXX/new-neg-size.cpp            | 15 ---------------
 5 files changed, 30 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/AST/ByteCode/new-neg-size-nothrow.cpp
 create mode 100644 clang/test/AST/ByteCode/new-neg-size.cpp
 delete mode 100644 clang/test/SemaCXX/new-neg-size.cpp

diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index a63bd80b89657..0ce6a4f7d0113 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -37,6 +37,8 @@ def note_constexpr_invalid_inhctor : Note<
   "constant expression; derived class cannot be implicitly initialized">;
 def note_constexpr_no_return : Note<
   "control reached end of constexpr function">;
+def note_constexpr_negative_allocation_size : Note<
+"cannot allocate array with negative size in a constant expression">;
 def note_constexpr_virtual_call : Note<
   "cannot evaluate call to virtual function in a constant expression "
   "in C++ standards before C++20">;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index e505712b60dd3..0f937e6beb137 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3491,8 +3491,10 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, 
PrimType T, const Expr *Source,
     return true;
   }
   if (!NumElements.isPositive()) {
-    if (!IsNoThrow)
+    if (!IsNoThrow) {
+      S.FFDiag(Source, diag::note_constexpr_negative_allocation_size);
       return false;
+    }
     S.Stk.push<Pointer>(0, nullptr);
     return true;
   }
diff --git a/clang/test/AST/ByteCode/new-neg-size-nothrow.cpp 
b/clang/test/AST/ByteCode/new-neg-size-nothrow.cpp
new file mode 100644
index 0000000000000..79cee693131fc
--- /dev/null
+++ b/clang/test/AST/ByteCode/new-neg-size-nothrow.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-fexperimental-new-constant-interpreter -verify %s
+// expected-no-diagnostics
+
+struct __nothrow_t { };
+extern const __nothrow_t __nothrow_dummy;
+void* operator new[](unsigned long, const __nothrow_t&) noexcept;
+
+// This test ensures that new (nothrow) int[-1] does not crash in constexpr 
interpreter.
+// It should evaluate to a nullptr, not assert.
+constexpr int get_neg_size() {
+  return -1;
+}
+
+void test_nothrow_negative_size() {
+  int x = get_neg_size();
+  int *p = new (__nothrow_dummy) int[x]; 
+  (void)p;
+}
diff --git a/clang/test/AST/ByteCode/new-neg-size.cpp 
b/clang/test/AST/ByteCode/new-neg-size.cpp
new file mode 100644
index 0000000000000..d3755e67f04d8
--- /dev/null
+++ b/clang/test/AST/ByteCode/new-neg-size.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-fexperimental-new-constant-interpreter -verify %s
+
+constexpr void f() {
+  int a = -1;
+  int *b = new int[a]; // expected-note {{cannot allocate array with negative 
size in a constant expression}}
+}
+// expected-error@-4 {{constexpr function never produces a constant 
expression}}
diff --git a/clang/test/SemaCXX/new-neg-size.cpp 
b/clang/test/SemaCXX/new-neg-size.cpp
deleted file mode 100644
index 4b5a0d4bfe228..0000000000000
--- a/clang/test/SemaCXX/new-neg-size.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: not %clang_cc1 -std=c++20 -fsyntax-only %s 2>&1 \
-// RUN:   | FileCheck %s --implicit-check-not='Assertion 
`NumElements.isPositive()` failed'
-
-// In C++20, constexpr dynamic allocation is permitted *only* if valid.
-// A negative element count must be diagnosed (and must not crash).
-
-constexpr void f_bad_neg() {
-  int a = -1;
-  (void) new int[a]; // triggers negative-size path in the interpreter
-}
-
-// Force evaluation so we definitely run the constexpr interpreter.
-constexpr bool force_eval = (f_bad_neg(), true);
-
-// CHECK: error: constexpr function never produces a constant expression

>From 5394a043db1005eb82305a31099396ae99fafdc9 Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Thu, 28 Aug 2025 10:39:20 -0400
Subject: [PATCH 5/6] Move test cases into new-delete

---
 clang/test/AST/ByteCode/new-delete.cpp        | 26 +++++++++++++++++++
 .../AST/ByteCode/new-neg-size-nothrow.cpp     | 18 -------------
 clang/test/AST/ByteCode/new-neg-size.cpp      |  7 -----
 3 files changed, 26 insertions(+), 25 deletions(-)
 delete mode 100644 clang/test/AST/ByteCode/new-neg-size-nothrow.cpp
 delete mode 100644 clang/test/AST/ByteCode/new-neg-size.cpp

diff --git a/clang/test/AST/ByteCode/new-delete.cpp 
b/clang/test/AST/ByteCode/new-delete.cpp
index 3f0e928c7664e..6db58859d5bbc 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -1069,6 +1069,32 @@ namespace BaseCompare {
   static_assert(foo());
 }
 
+
+namespace NegativeArraySize {
+
+constexpr void f() {
+  int x = -1;
+  int *p = new int[x]; // expected-note {{cannot allocate array with negative 
size in a constant expression}}
+}
+// both-error@-4 {{constexpr function never produces a constant expression}}
+// ref-note@-3 {{cannot allocate array; evaluated array bound -1 is negative}}
+
+} // namespace NegativeArraySize
+
+namespace NewNegSizeNothrow {
+  constexpr int get_neg_size() {
+    return -1;
+  }
+
+  constexpr bool test_nothrow_neg_size() {
+    int x = get_neg_size();
+    int* p = new (std::nothrow) int[x]; 
+    return p == nullptr;
+  }
+
+  static_assert(test_nothrow_neg_size(), "expected nullptr");
+} // namespace NewNegSizeNothrow
+
 #else
 /// Make sure we reject this prior to C++20
 constexpr int a() { // both-error {{never produces a constant expression}}
diff --git a/clang/test/AST/ByteCode/new-neg-size-nothrow.cpp 
b/clang/test/AST/ByteCode/new-neg-size-nothrow.cpp
deleted file mode 100644
index 79cee693131fc..0000000000000
--- a/clang/test/AST/ByteCode/new-neg-size-nothrow.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-fexperimental-new-constant-interpreter -verify %s
-// expected-no-diagnostics
-
-struct __nothrow_t { };
-extern const __nothrow_t __nothrow_dummy;
-void* operator new[](unsigned long, const __nothrow_t&) noexcept;
-
-// This test ensures that new (nothrow) int[-1] does not crash in constexpr 
interpreter.
-// It should evaluate to a nullptr, not assert.
-constexpr int get_neg_size() {
-  return -1;
-}
-
-void test_nothrow_negative_size() {
-  int x = get_neg_size();
-  int *p = new (__nothrow_dummy) int[x]; 
-  (void)p;
-}
diff --git a/clang/test/AST/ByteCode/new-neg-size.cpp 
b/clang/test/AST/ByteCode/new-neg-size.cpp
deleted file mode 100644
index d3755e67f04d8..0000000000000
--- a/clang/test/AST/ByteCode/new-neg-size.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-fexperimental-new-constant-interpreter -verify %s
-
-constexpr void f() {
-  int a = -1;
-  int *b = new int[a]; // expected-note {{cannot allocate array with negative 
size in a constant expression}}
-}
-// expected-error@-4 {{constexpr function never produces a constant 
expression}}

>From 46325899b68dac06f27551037b434668c5acdb42 Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Thu, 28 Aug 2025 11:25:06 -0400
Subject: [PATCH 6/6] Shift expected output to line it is emitted on

---
 clang/test/AST/ByteCode/new-delete.cpp | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/test/AST/ByteCode/new-delete.cpp 
b/clang/test/AST/ByteCode/new-delete.cpp
index 6db58859d5bbc..665cb4cc2e48e 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -1070,14 +1070,13 @@ namespace BaseCompare {
 }
 
 
-namespace NegativeArraySize {
+namespace NegativeArraySize { 
 
-constexpr void f() {
+constexpr void f() { // both-error {{constexpr function never produces a 
constant expression}}
   int x = -1;
-  int *p = new int[x]; // expected-note {{cannot allocate array with negative 
size in a constant expression}}
+  int *p = new int[x]; // expected-note {{cannot allocate array with negative 
size in a constant expression}} \
+                       // ref-note {{cannot allocate array; evaluated array 
bound -1 is negative}}
 }
-// both-error@-4 {{constexpr function never produces a constant expression}}
-// ref-note@-3 {{cannot allocate array; evaluated array bound -1 is negative}}
 
 } // namespace NegativeArraySize
 

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

Reply via email to