[libcxx-commits] [libcxxabi] [libc++] Remove noexcept from _impl functions (PR #74330)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Dec 4 07:29:04 PST 2023
https://github.com/azhan92 created https://github.com/llvm/llvm-project/pull/74330
This PR removes the `noexcept` specification introduced in [`69407` ](https://github.com/llvm/llvm-project/pull/69407) since the standard allows
> throw an exception of type bad_alloc or a class derived from bad_alloc
as a behaviour of a `new_handler` function. The PR also adds a test to catch this.
>From f5d466383694fe717e26a930c39798a9710280fb Mon Sep 17 00:00:00 2001
From: Alison Zhang <alisonzhang at ibm.com>
Date: Mon, 4 Dec 2023 10:23:48 -0500
Subject: [PATCH] remove noexcepts
---
libcxxabi/src/stdlib_new_delete.cpp | 40 ++++++++++-------------
libcxxabi/test/test_memory_alloc.pass.cpp | 33 +++++++++++++++++++
2 files changed, 50 insertions(+), 23 deletions(-)
create mode 100644 libcxxabi/test/test_memory_alloc.pass.cpp
diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp
index 6c9990f063dde..71c98793cae40 100644
--- a/libcxxabi/src/stdlib_new_delete.cpp
+++ b/libcxxabi/src/stdlib_new_delete.cpp
@@ -30,7 +30,8 @@
// 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 {
+_LIBCPP_WEAK
+void* operator new(std::size_t size) _THROW_BAD_ALLOC {
if (size == 0)
size = 1;
void* p;
@@ -41,18 +42,12 @@ static void* operator_new_impl(std::size_t size) noexcept {
if (nh)
nh();
else
- break;
- }
- return p;
-}
-
-_LIBCPP_WEAK
-void* operator new(std::size_t size) _THROW_BAD_ALLOC {
- void* p = operator_new_impl(size);
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- if (p == nullptr)
- throw std::bad_alloc();
+ throw std::bad_alloc();
+#else
+ break;
#endif
+ }
return p;
}
@@ -107,7 +102,8 @@ 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 {
+_LIBCPP_WEAK
+void* operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
if (size == 0)
size = 1;
if (static_cast<size_t>(alignment) < sizeof(void*))
@@ -116,24 +112,22 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm
// Try allocating memory. If allocation fails and there is a new_handler,
// call it to try free up memory, and try again until it succeeds, or until
// the new_handler decides to terminate.
+ //
+ // If allocation fails and there is no new_handler, we throw bad_alloc
+ // (or return nullptr if exceptions are disabled).
void* p;
while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
- else
- break;
- }
- return p;
-}
-
-_LIBCPP_WEAK
-void* operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
- void* p = operator_new_aligned_impl(size, alignment);
+ else {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- if (p == nullptr)
- throw std::bad_alloc();
+ throw std::bad_alloc();
+# else
+ break;
# endif
+ }
+ }
return p;
}
diff --git a/libcxxabi/test/test_memory_alloc.pass.cpp b/libcxxabi/test/test_memory_alloc.pass.cpp
new file mode 100644
index 0000000000000..3eb618e54f1a8
--- /dev/null
+++ b/libcxxabi/test/test_memory_alloc.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+}
More information about the libcxx-commits
mailing list