Skip to content

Commit 1340186

Browse files
FIGMA HACK FOR XCODE 15: Revert "[libc++] Fix the behavior of throwing operator new under -fno-exceptions (llvm#69498)"
This reverts commit 3145265. This commit caused conflicts with Xcode 15's linker as described [here](https://issues.chromium.org/issues/326898585)
1 parent c3829e0 commit 1340186

13 files changed

+154
-658
lines changed

libcxx/docs/ReleaseNotes/18.rst

-23
Original file line numberDiff line numberDiff line change
@@ -239,29 +239,6 @@ LLVM 20
239239
ABI Affecting Changes
240240
---------------------
241241

242-
- When the shared/static library is built with ``-fno-exceptions``, the behavior of ``operator new`` was changed
243-
to make it standards-conforming. In LLVM 17 and before, the throwing versions of ``operator new`` would return
244-
``nullptr`` upon failure to allocate, when the shared/static library was built with exceptions disabled. This
245-
was non-conforming, since the throwing versions of ``operator new`` are never expected to return ``nullptr``, and
246-
this non-conformance could actually lead to miscompiles in subtle cases.
247-
248-
Starting in LLVM 18, the throwing versions of ``operator new`` will abort the program when they fail to allocate
249-
if the shared/static library has been built with ``-fno-exceptions``. This is consistent with the behavior of all
250-
other potentially-throwing functions in the library, which abort the program instead of throwing when ``-fno-exceptions``
251-
is used.
252-
253-
Furthermore, when the shared/static library is built with ``-fno-exceptions``, users who override the throwing
254-
version of ``operator new`` will now need to also override the ``std::nothrow_t`` version of ``operator new`` if
255-
they want to use it. Indeed, this is because there is no way to implement a conforming ``operator new(nothrow)``
256-
from a conforming potentially-throwing ``operator new`` when compiled with ``-fno-exceptions``. In that case, using
257-
``operator new(nothrow)`` without overriding it explicitly but after overriding the throwing ``operator new`` will
258-
result in an error.
259-
260-
Note that this change only impacts vendors/users that build the shared/static library themselves and pass
261-
``-DLIBCXX_ENABLE_EXCEPTIONS=OFF``, which is not the default configuration. If you are using the default
262-
configuration of the library, the libc++ shared/static library will be built with exceptions enabled, and
263-
there is no change between LLVM 17 and LLVM 18, even for users who build their own code using ``-fno-exceptions``.
264-
265242
- The symbol of a non-visible function part of ``std::system_error`` was removed.
266243
This is not a breaking change as the private function ``__init`` was never referenced internally outside of the dylib.
267244

libcxx/src/include/overridable_function.h

-130
This file was deleted.

libcxx/src/new.cpp

+26-78
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "include/overridable_function.h"
10-
#include <__assert>
119
#include <__memory/aligned_alloc.h>
12-
#include <cstddef>
1310
#include <cstdlib>
1411
#include <new>
1512

@@ -18,10 +15,6 @@
1815
// The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp
1916
// file. The version in this file is the canonical one.
2017

21-
inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); }
22-
23-
# define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str)
24-
2518
// ------------------ BEGIN COPY ------------------
2619
// Implement all new and delete operators as weak definitions
2720
// in this shared library, so that they can be overridden by programs
@@ -43,63 +36,41 @@ static void* operator_new_impl(std::size_t size) {
4336
return p;
4437
}
4538

46-
_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
39+
_LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
4740
void* p = operator_new_impl(size);
41+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
4842
if (p == nullptr)
49-
__throw_bad_alloc_shim();
43+
throw std::bad_alloc();
44+
# endif
5045
return p;
5146
}
5247

5348
_LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
54-
# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
55-
# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
56-
_LIBCPP_ASSERT_SHIM(
57-
!std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
58-
"libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
59-
"but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
60-
"`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
61-
"it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "
62-
"contract (since it should return nullptr upon failure). Please make sure you override "
63-
"`operator new(size_t, nothrow_t)` as well.");
64-
# endif
65-
66-
return operator_new_impl(size);
67-
# else
6849
void* p = nullptr;
50+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
6951
try {
52+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
7053
p = ::operator new(size);
54+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
7155
} catch (...) {
7256
}
57+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
7358
return p;
74-
# endif
7559
}
7660

77-
_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
78-
return ::operator new(size);
79-
}
61+
_LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { return ::operator new(size); }
8062

8163
_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
82-
# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
83-
# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
84-
_LIBCPP_ASSERT_SHIM(
85-
!std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
86-
"libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
87-
"but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
88-
"`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
89-
"it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
90-
"contract (since it should return nullptr upon failure). Please make sure you override "
91-
"`operator new[](size_t, nothrow_t)` as well.");
92-
# endif
93-
94-
return operator_new_impl(size);
95-
# else
9664
void* p = nullptr;
65+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
9766
try {
67+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
9868
p = ::operator new[](size);
69+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
9970
} catch (...) {
10071
}
72+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
10173
return p;
102-
# endif
10374
}
10475

10576
_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
@@ -136,66 +107,43 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm
136107
return p;
137108
}
138109

139-
_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
140-
operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
110+
_LIBCPP_WEAK void* operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
141111
void* p = operator_new_aligned_impl(size, alignment);
112+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
142113
if (p == nullptr)
143-
__throw_bad_alloc_shim();
114+
throw std::bad_alloc();
115+
# endif
144116
return p;
145117
}
146118

147119
_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
148-
# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
149-
# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
150-
_LIBCPP_ASSERT_SHIM(
151-
!std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
152-
"libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
153-
"but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
154-
"`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
155-
"terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
156-
"to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
157-
"`operator new(size_t, align_val_t, nothrow_t)` as well.");
158-
# endif
159-
160-
return operator_new_aligned_impl(size, alignment);
161-
# else
162120
void* p = nullptr;
121+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
163122
try {
123+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
164124
p = ::operator new(size, alignment);
125+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
165126
} catch (...) {
166127
}
128+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
167129
return p;
168-
# endif
169130
}
170131

171-
_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
172-
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
132+
_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
173133
return ::operator new(size, alignment);
174134
}
175135

176136
_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
177-
# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
178-
# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
179-
_LIBCPP_ASSERT_SHIM(
180-
!std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
181-
"libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
182-
"but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
183-
"`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
184-
"terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "
185-
"nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
186-
"override "
187-
"`operator new[](size_t, align_val_t, nothrow_t)` as well.");
188-
# endif
189-
190-
return operator_new_aligned_impl(size, alignment);
191-
# else
192137
void* p = nullptr;
138+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
193139
try {
140+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
194141
p = ::operator new[](size, alignment);
142+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
195143
} catch (...) {
196144
}
145+
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
197146
return p;
198-
# endif
199147
}
200148

201149
_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }

libcxx/test/libcxx/language.support/support.dynamic/assert.nothrow_new_not_overridden_fno_exceptions.pass.cpp

-58
This file was deleted.

0 commit comments

Comments
 (0)