Skip to content

Commit 8dfc67d

Browse files
authored
[libc++][hardening] Rework how the assertion handler can be overridden. (#77883)
Previously there were two ways to override the verbose abort function which gets called when a hardening assertion is triggered: - compile-time: define the `_LIBCPP_VERBOSE_ABORT` macro; - link-time: provide a definition of `__libcpp_verbose_abort` function. This patch adds a new configure-time approach: the vendor can provide a path to a custom header file which will get copied into the build by CMake and included by the library. The header must provide a definition of the `_LIBCPP_ASSERTION_HANDLER` macro which is what will get called should a hardening assertion fail. As of this patch, overriding `_LIBCPP_VERBOSE_ABORT` will still work, but the previous mechanisms will be effectively removed in a follow-up patch, making the configure-time mechanism the sole way of overriding the default handler. Note that `_LIBCPP_ASSERTION_HANDLER` only gets invoked when a hardening assertion fails. It does not affect other cases where `_LIBCPP_VERBOSE_ABORT` is currently used (e.g. when an exception is thrown in the `-fno-exceptions` mode). The library provides a default version of the custom header file that will get used if it's not overridden by the vendor. That allows us to always test the override mechanism and reduces the difference in configuration between the pristine version of the library and a platform-specific version.
1 parent ba81477 commit 8dfc67d

30 files changed

+158
-115
lines changed

libcxx/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ if (NOT "${LIBCXX_HARDENING_MODE}" IN_LIST LIBCXX_SUPPORTED_HARDENING_MODES)
6969
message(FATAL_ERROR
7070
"Unsupported hardening mode: '${LIBCXX_HARDENING_MODE}'. Supported values are ${LIBCXX_SUPPORTED_HARDENING_MODES}.")
7171
endif()
72+
set(LIBCXX_ASSERTION_HANDLER_FILE
73+
"${CMAKE_CURRENT_SOURCE_DIR}/vendor/llvm/default_assertion_handler.in"
74+
CACHE STRING
75+
"Specify the path to a header that contains a custom implementation of the
76+
assertion handler that gets invoked when a hardening assertion fails. If
77+
provided, this header will be included by the library, replacing the
78+
default assertion handler.")
7279
option(LIBCXX_ENABLE_RANDOM_DEVICE
7380
"Whether to include support for std::random_device in the library. Disabling
7481
this can be useful when building the library for platforms that don't have

libcxx/docs/BuildingLibcxx.rst

+46
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,15 @@ libc++ Feature Options
409409
Use the specified GCC toolchain and standard library when building the native
410410
stdlib benchmark tests.
411411

412+
.. option:: LIBCXX_ASSERTION_HANDLER_FILE:PATH
413+
414+
**Default**:: ``"${CMAKE_CURRENT_SOURCE_DIR}/vendor/llvm/default_assertion_handler.in"``
415+
416+
Specify the path to a header that contains a custom implementation of the
417+
assertion handler that gets invoked when a hardening assertion fails. If
418+
provided, this header will be included by the library, replacing the
419+
default assertion handler.
420+
412421

413422
libc++ ABI Feature Options
414423
--------------------------
@@ -473,6 +482,43 @@ LLVM-specific options
473482
others.
474483

475484

485+
.. _assertion-handler:
486+
487+
Overriding the default assertion handler
488+
==========================================
489+
490+
When the library wants to terminate due to an unforeseen condition (such as
491+
a hardening assertion failure), the program is aborted through a special verbose
492+
termination function. The library provides a default function that prints an
493+
error message and calls ``std::abort()``. Note that this function is provided by
494+
the static or shared library, so it is only available when deploying to
495+
a platform where the compiled library is sufficiently recent. On older
496+
platforms, the program will terminate in an unspecified unsuccessful manner, but
497+
the quality of diagnostics won't be great.
498+
499+
However, vendors can also override that mechanism at CMake configuration time.
500+
When a hardening assertion fails, the library invokes the
501+
``_LIBCPP_ASSERTION_HANDLER`` macro. A vendor may provide a header that contains
502+
a custom definition of this macro and specify the path to the header via the
503+
``LIBCXX_ASSERTION_HANDLER_FILE`` CMake variable. If provided, this header will
504+
be included by the library and replace the default implementation. The header
505+
must not include any standard library headers (directly or transitively) because
506+
doing so will almost always create a circular dependency. The
507+
``_LIBCPP_ASSERTION_HANDLER(message)`` macro takes a single parameter that
508+
contains an error message explaining the hardening failure and some details
509+
about the source location that triggered it.
510+
511+
When a hardening assertion fails, it means that the program is about to invoke
512+
library undefined behavior. For this reason, the custom assertion handler is
513+
generally expected to terminate the program. If a custom assertion handler
514+
decides to avoid doing so (e.g. it chooses to log and continue instead), it does
515+
so at its own risk -- this approach should only be used in non-production builds
516+
and with an understanding of potential consequences. Furthermore, the custom
517+
assertion handler should not throw any exceptions as it may be invoked from
518+
standard library functions that are marked ``noexcept`` (so throwing will result
519+
in ``std::terminate`` being called).
520+
521+
476522
Using Alternate ABI libraries
477523
=============================
478524

libcxx/docs/ReleaseNotes/18.rst

+4
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ Deprecations and Removals
111111
macro is provided to restore the previous behavior, and it will be supported in the LLVM 18 release only.
112112
In LLVM 19 and beyond, ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`` will not be honored anymore.
113113

114+
- The only supported way to customize the assertion handler that gets invoked when a hardening assertion fails
115+
is now by setting the ``LIBCXX_ASSERTION_HANDLER_FILE`` CMake variable and providing a custom header. See
116+
the documentation on overriding the default assertion handler for details.
117+
114118
- The ``_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED`` macro is not honored anymore in LLVM 18.
115119
Please see the updated documentation about the hardening modes in libc++ and in particular the
116120
``_LIBCPP_VERBOSE_ABORT`` macro for details.

libcxx/docs/UsingLibcxx.rst

-64
Original file line numberDiff line numberDiff line change
@@ -146,70 +146,6 @@ IWYU, you should run the tool like so:
146146
If you would prefer to not use that flag, then you can replace ``/path/to/include-what-you-use/share/libcxx.imp``
147147
file with the libc++-provided ``libcxx.imp`` file.
148148

149-
.. _termination-handler:
150-
151-
Overriding the default termination handler
152-
==========================================
153-
154-
When the library wants to terminate due to an unforeseen condition (such as a hardening assertion
155-
failure), the program is aborted through a special verbose termination function. The library provides
156-
a default function that prints an error message and calls ``std::abort()``. Note that this function is
157-
provided by the static or shared library, so it is only available when deploying to a platform where
158-
the compiled library is sufficiently recent. On older platforms, the program will terminate in an
159-
unspecified unsuccessful manner, but the quality of diagnostics won't be great.
160-
161-
However, users can also override that mechanism at two different levels. First, the mechanism can be
162-
overridden at compile time by defining the ``_LIBCPP_VERBOSE_ABORT(format, args...)`` variadic macro.
163-
When that macro is defined, it will be called with a format string as the first argument, followed by
164-
a series of arguments to format using printf-style formatting. Compile-time customization may be
165-
useful to get precise control over code generation, however it is also inconvenient to use in
166-
some cases. Indeed, compile-time customization of the verbose termination function requires that all
167-
translation units be compiled with a consistent definition for ``_LIBCPP_VERBOSE_ABORT`` to avoid ODR
168-
violations, which can add complexity in the build system of users.
169-
170-
Otherwise, if compile-time customization is not necessary, link-time customization of the handler is also
171-
possible, similarly to how replacing ``operator new`` works. This mechanism trades off fine-grained control
172-
over the call site where the termination is initiated in exchange for better ergonomics. Link-time
173-
customization is done by simply defining the following function in exactly one translation unit of your
174-
program:
175-
176-
.. code-block:: cpp
177-
178-
void __libcpp_verbose_abort(char const* format, ...)
179-
180-
This mechanism is similar to how one can replace the default definition of ``operator new``
181-
and ``operator delete``. For example:
182-
183-
.. code-block:: cpp
184-
185-
// In HelloWorldHandler.cpp
186-
#include <version> // must include any libc++ header before defining the function (C compatibility headers excluded)
187-
188-
void std::__libcpp_verbose_abort(char const* format, ...) {
189-
std::va_list list;
190-
va_start(list, format);
191-
std::vfprintf(stderr, format, list);
192-
va_end(list);
193-
194-
std::abort();
195-
}
196-
197-
// In HelloWorld.cpp
198-
#include <vector>
199-
200-
int main() {
201-
std::vector<int> v;
202-
int& x = v[0]; // Your termination function will be called here if hardening is enabled.
203-
}
204-
205-
Also note that the verbose termination function should never return. Since assertions in libc++
206-
catch undefined behavior, your code will proceed with undefined behavior if your function is called
207-
and does return.
208-
209-
Furthermore, exceptions should not be thrown from the function. Indeed, many functions in the
210-
library are ``noexcept``, and any exception thrown from the termination function will result
211-
in ``std::terminate`` being called.
212-
213149
Libc++ Configuration Macros
214150
===========================
215151

libcxx/include/CMakeLists.txt

+9-1
Original file line numberDiff line numberDiff line change
@@ -1020,9 +1020,11 @@ endforeach()
10201020

10211021
configure_file("__config_site.in" "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" @ONLY)
10221022
configure_file("module.modulemap.in" "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" @ONLY)
1023+
configure_file("${LIBCXX_ASSERTION_HANDLER_FILE}" "${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler" COPYONLY)
10231024

10241025
set(_all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site"
1025-
"${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap")
1026+
"${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap"
1027+
"${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler")
10261028
foreach(f ${files})
10271029
set(src "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
10281030
set(dst "${LIBCXX_GENERATED_INCLUDE_DIR}/${f}")
@@ -1059,6 +1061,12 @@ if (LIBCXX_INSTALL_HEADERS)
10591061
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
10601062
COMPONENT cxx-headers)
10611063

1064+
# Install the generated __assertion_handler file to the generic include dir.
1065+
install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler"
1066+
DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}"
1067+
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
1068+
COMPONENT cxx-headers)
1069+
10621070
# Install the generated modulemap file to the generic include dir.
10631071
install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap"
10641072
DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}"

libcxx/include/__assert

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#ifndef _LIBCPP___ASSERT
1111
#define _LIBCPP___ASSERT
1212

13+
#include <__assertion_handler> // Note: this include is generated by CMake and is potentially vendor-provided.
1314
#include <__config>
14-
#include <__verbose_abort>
1515

1616
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1717
# pragma GCC system_header
@@ -20,8 +20,8 @@
2020
#define _LIBCPP_ASSERT(expression, message) \
2121
(__builtin_expect(static_cast<bool>(expression), 1) \
2222
? (void)0 \
23-
: _LIBCPP_VERBOSE_ABORT( \
24-
"%s:%d: assertion %s failed: %s\n", __builtin_FILE(), __builtin_LINE(), #expression, message))
23+
: _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \
24+
expression) " failed: " message "\n"))
2525

2626
// TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add
2727
// assumptions without a clear optimization intent, disable that to avoid worsening the code generation.

libcxx/test/libcxx/assertions/modes/enabling_assertions_enables_extensive_mode.pass.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
// This test ensures that enabling assertions with the legacy `_LIBCPP_ENABLE_ASSERTIONS` now enables the extensive
1111
// hardening mode.
1212

13-
// `check_assertion.h` is only available starting from C++11 and requires Unix headers.
14-
// UNSUPPORTED: c++03, !has-unix-headers
13+
// `check_assertion.h` is only available starting from C++11 and requires Unix headers and regex support.
14+
// UNSUPPORTED: c++03, !has-unix-headers, no-localization
1515
// The ability to set a custom abort message is required to compare the assertion message.
1616
// XFAIL: availability-verbose_abort-missing
1717
// Note that GCC doesn't support `-Wno-macro-redefined`.

libcxx/test/libcxx/assertions/modes/override_with_debug_mode.pass.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
// This test ensures that we can override any hardening mode with the debug mode on a per-TU basis.
1010

11-
// `check_assertion.h` is only available starting from C++11.
12-
// UNSUPPORTED: c++03
13-
// `check_assertion.h` requires Unix headers.
14-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` is only available starting from C++11 and requires Unix headers and regex support.
12+
// UNSUPPORTED: c++03, !has-unix-headers, no-localization
1513
// The ability to set a custom abort message is required to compare the assertion message.
1614
// XFAIL: availability-verbose_abort-missing
1715
// ADDITIONAL_COMPILE_FLAGS: -U_LIBCPP_HARDENING_MODE -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG

libcxx/test/libcxx/assertions/modes/override_with_extensive_mode.pass.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
// This test ensures that we can override any hardening mode with the extensive hardening mode on a per-TU basis.
1010

11-
// `check_assertion.h` is only available starting from C++11.
12-
// UNSUPPORTED: c++03
13-
// `check_assertion.h` requires Unix headers.
14-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` is only available starting from C++11 and requires Unix headers and regex support.
12+
// UNSUPPORTED: c++03, !has-unix-headers, no-localization
1513
// The ability to set a custom abort message is required to compare the assertion message.
1614
// XFAIL: availability-verbose_abort-missing
1715
// ADDITIONAL_COMPILE_FLAGS: -U_LIBCPP_HARDENING_MODE -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE

libcxx/test/libcxx/assertions/modes/override_with_fast_mode.pass.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
// This test ensures that we can override any hardening mode with the fast mode on a per-TU basis.
1010

11-
// `check_assertion.h` is only available starting from C++11.
12-
// UNSUPPORTED: c++03
13-
// `check_assertion.h` requires Unix headers.
14-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` is only available starting from C++11 and requires Unix headers and regex support.
12+
// UNSUPPORTED: c++03, !has-unix-headers, no-localization
1513
// The ability to set a custom abort message is required to compare the assertion message.
1614
// XFAIL: availability-verbose_abort-missing
1715
// ADDITIONAL_COMPILE_FLAGS: -U_LIBCPP_HARDENING_MODE -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST

libcxx/test/libcxx/assertions/modes/override_with_unchecked_mode.pass.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
// This test ensures that we can override any hardening mode with the unchecked mode on a per-TU basis.
1010

11-
// `check_assertion.h` is only available starting from C++11.
12-
// UNSUPPORTED: c++03
13-
// `check_assertion.h` requires Unix headers.
14-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` is only available starting from C++11 and requires Unix headers and regex support.
12+
// UNSUPPORTED: c++03, !has-unix-headers, no-localization
1513
// ADDITIONAL_COMPILE_FLAGS: -U_LIBCPP_HARDENING_MODE -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE
1614

1715
#include <cassert>

libcxx/test/libcxx/containers/sequences/deque/asan_caterpillar.pass.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
// Regression test to error in deque::__annotate_from_to in deque,
1212
// with origin in deque::__add_back_capacity.
1313

14-
// REQUIRES: has-unix-headers
15-
// UNSUPPORTED: c++03
14+
// `check_assertion.h` is only available starting from C++11 and requires Unix headers and regex support.
15+
// UNSUPPORTED: c++03, !has-unix-headers, no-localization
1616

1717
#include <deque>
1818
#include <cstdio>

libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.modifying.operations/alg.move/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

libcxx/test/std/algorithms/alg.sorting/alg.merge/pstl.exception_handling.pass.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
// UNSUPPORTED: c++03, c++11, c++14
1010
// UNSUPPORTED: no-exceptions
11-
// REQUIRES: has-unix-headers
11+
// `check_assertion.h` requires Unix headers and regex support.
12+
// UNSUPPORTED: !has-unix-headers, no-localization
1213

1314
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
1415

0 commit comments

Comments
 (0)