[libcxx-commits] [libcxx] [libcxxabi] [libc++] Fix noexcept behaviour of operator new helper functions (PR #74337)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 12 13:48:19 PST 2024


https://github.com/azhan92 updated https://github.com/llvm/llvm-project/pull/74337

>From 5041d441856cda19cf796e16a13b4e0049d33342 Mon Sep 17 00:00:00 2001
From: Alison Zhang <alisonzhang at ibm.com>
Date: Mon, 4 Dec 2023 11:35:20 -0500
Subject: [PATCH 1/2] remove noexcept

---
 libcxx/src/new.cpp                        |  4 +--
 libcxxabi/src/stdlib_new_delete.cpp       |  4 +--
 libcxxabi/test/test_memory_alloc.pass.cpp | 34 +++++++++++++++++++++++
 3 files changed, 38 insertions(+), 4 deletions(-)
 create mode 100644 libcxxabi/test/test_memory_alloc.pass.cpp

diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index 033bba5c1fc95b..cb8b4aae8d5f94 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -20,7 +20,7 @@
 // in this shared library, so that they can be overridden by programs
 // that define non-weak copies of the functions.
 
-static void* operator_new_impl(std::size_t size) noexcept {
+static void* operator_new_impl(std::size_t size) {
   if (size == 0)
     size = 1;
   void* p;
@@ -87,7 +87,7 @@ _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator del
 
 #  if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
 
-static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) noexcept {
+static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
   if (size == 0)
     size = 1;
   if (static_cast<size_t>(alignment) < sizeof(void*))
diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp
index 6c9990f063dde6..f8a00ec5842566 100644
--- a/libcxxabi/src/stdlib_new_delete.cpp
+++ b/libcxxabi/src/stdlib_new_delete.cpp
@@ -30,7 +30,7 @@
 // in this shared library, so that they can be overridden by programs
 // that define non-weak copies of the functions.
 
-static void* operator_new_impl(std::size_t size) noexcept {
+static void* operator_new_impl(std::size_t size) {
   if (size == 0)
     size = 1;
   void* p;
@@ -107,7 +107,7 @@ void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
 
 #if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
 
-static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) noexcept {
+static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
   if (size == 0)
     size = 1;
   if (static_cast<size_t>(alignment) < sizeof(void*))
diff --git a/libcxxabi/test/test_memory_alloc.pass.cpp b/libcxxabi/test/test_memory_alloc.pass.cpp
new file mode 100644
index 00000000000000..219b85b9afcafa
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc.pass.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+
+#include <new>
+#include <cassert>
+#include <limits>
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw std::bad_alloc();
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new[](std::numeric_limits<std::size_t>::max());
+    (void)x;
+    assert(false);
+  } catch (std::bad_alloc const&) {
+    assert(new_handler_called == 1);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}

>From 227d0ba122403e8773318eca47a05e7fc2a5421e Mon Sep 17 00:00:00 2001
From: Alison Zhang <alisonzhang at ibm.com>
Date: Fri, 12 Jan 2024 16:35:03 -0500
Subject: [PATCH 2/2] Update test cases

---
 libcxxabi/test/test_memory_alloc1.pass.cpp    | 42 +++++++++++++++++++
 libcxxabi/test/test_memory_alloc2.pass.cpp    | 42 +++++++++++++++++++
 libcxxabi/test/test_memory_alloc3.pass.cpp    | 42 +++++++++++++++++++
 libcxxabi/test/test_memory_alloc4.pass.cpp    | 42 +++++++++++++++++++
 .../test/test_memory_alloc_nothrow1.pass.cpp  | 42 +++++++++++++++++++
 .../test/test_memory_alloc_nothrow2.pass.cpp  | 42 +++++++++++++++++++
 .../test/test_memory_alloc_nothrow3.pass.cpp  | 42 +++++++++++++++++++
 .../test/test_memory_alloc_nothrow4.pass.cpp  | 42 +++++++++++++++++++
 8 files changed, 336 insertions(+)
 create mode 100644 libcxxabi/test/test_memory_alloc1.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc2.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc3.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc4.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc_nothrow1.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc_nothrow2.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc_nothrow3.pass.cpp
 create mode 100644 libcxxabi/test/test_memory_alloc_nothrow4.pass.cpp

diff --git a/libcxxabi/test/test_memory_alloc1.pass.cpp b/libcxxabi/test/test_memory_alloc1.pass.cpp
new file mode 100644
index 00000000000000..aa202e04e8f39a
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc1.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new(std::numeric_limits<std::size_t>::max());
+    (void)x;
+    assert(false);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc2.pass.cpp b/libcxxabi/test/test_memory_alloc2.pass.cpp
new file mode 100644
index 00000000000000..1049d7d3a6387c
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc2.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new[](std::numeric_limits<std::size_t>::max());
+    (void)x;
+    assert(false);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc3.pass.cpp b/libcxxabi/test/test_memory_alloc3.pass.cpp
new file mode 100644
index 00000000000000..fee1f15bd6cda6
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc3.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new(std::numeric_limits<std::size_t>::max(), static_cast<std::align_val_t>(32));
+    (void)x;
+    assert(false);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc4.pass.cpp b/libcxxabi/test/test_memory_alloc4.pass.cpp
new file mode 100644
index 00000000000000..1a152ef6ed56bb
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc4.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new[](std::numeric_limits<std::size_t>::max(), static_cast<std::align_val_t>(32));
+    (void)x;
+    assert(false);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc_nothrow1.pass.cpp b/libcxxabi/test/test_memory_alloc_nothrow1.pass.cpp
new file mode 100644
index 00000000000000..49ceefe56a27b9
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc_nothrow1.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new(std::numeric_limits<std::size_t>::max(), std::nothrow);
+    (void)x;
+    assert(x == NULL);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc_nothrow2.pass.cpp b/libcxxabi/test/test_memory_alloc_nothrow2.pass.cpp
new file mode 100644
index 00000000000000..deff9f0a1b9f42
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc_nothrow2.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new[](std::numeric_limits<std::size_t>::max(), std::nothrow);
+    (void)x;
+    assert(x == NULL);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc_nothrow3.pass.cpp b/libcxxabi/test/test_memory_alloc_nothrow3.pass.cpp
new file mode 100644
index 00000000000000..62072254dd31a5
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc_nothrow3.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new(std::numeric_limits<std::size_t>::max(), static_cast<std::align_val_t>(32), std::nothrow);
+    (void)x;
+    assert(x == NULL);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}
diff --git a/libcxxabi/test/test_memory_alloc_nothrow4.pass.cpp b/libcxxabi/test/test_memory_alloc_nothrow4.pass.cpp
new file mode 100644
index 00000000000000..b6d183e846a4ea
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc_nothrow4.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+#include <new>
+#include <cassert>
+#include <limits>
+#include <cstdlib>
+
+struct construction_key {};
+struct my_bad_alloc : std::bad_alloc {
+  my_bad_alloc(const my_bad_alloc &) : self(this) { std::abort(); }
+  my_bad_alloc(construction_key) : self(this) {}
+  const my_bad_alloc *const self;
+};
+
+int new_handler_called = 0;
+
+void my_new_handler() {
+  ++new_handler_called;
+  throw my_bad_alloc(construction_key{});
+}
+
+int main(int, char**) {
+  std::set_new_handler(my_new_handler);
+  try {
+    void* x = operator new[](std::numeric_limits<std::size_t>::max(), static_cast<std::align_val_t>(32), std::nothrow);
+    (void)x;
+    assert(x == NULL);
+  } catch (my_bad_alloc const& e) {
+    assert(new_handler_called == 1);
+    assert(e.self == &e);
+  } catch (...) {
+    assert(false);
+  }
+  return 0;
+}



More information about the libcxx-commits mailing list