[libcxx-commits] [libcxx] [libcxxabi] [libc++][hardening] Introduce assertion semantics (PR #148268)
Konstantin Varlamov via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jul 13 16:17:38 PDT 2025
https://github.com/var-const updated https://github.com/llvm/llvm-project/pull/148268
>From 6708ebf6020c59a4832aac95cb9524d533798100 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Fri, 11 Jul 2025 10:17:36 -0700
Subject: [PATCH 01/20] [libc++][hardening][NFC] Introduce
`_LIBCPP_VERBOSE_TRAP` macro.
Split out the calls to `__builtin_verbose_trap` into a separate header.
This is just a refactoring to make the code a bit more structured.
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__verbose_trap | 36 +++++++++++++++++++
.../vendor/llvm/default_assertion_handler.in | 14 ++------
3 files changed, 39 insertions(+), 12 deletions(-)
create mode 100644 libcxx/include/__verbose_trap
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index c8e6d28584623..f79edc9e32599 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -944,6 +944,7 @@ set(files
__vector/vector_bool.h
__vector/vector_bool_formatter.h
__verbose_abort
+ __verbose_trap
algorithm
any
array
diff --git a/libcxx/include/__verbose_trap b/libcxx/include/__verbose_trap
new file mode 100644
index 0000000000000..13ea727738c3b
--- /dev/null
+++ b/libcxx/include/__verbose_trap
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___VERBOSE_TRAP
+#define _LIBCPP___VERBOSE_TRAP
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if __has_builtin(__builtin_verbose_trap)
+// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream
+// version before upstream Clang actually got the builtin.
+// TODO: Remove once AppleClang supports the two-arguments version of the builtin.
+# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700
+# define _LIBCPP_VERBOSE_TRAP(message) __builtin_verbose_trap(message)
+# else
+# define _LIBCPP_VERBOSE_TRAP(message) __builtin_verbose_trap("libc++", message)
+# endif
+#else
+# define _LIBCPP_VERBOSE_TRAP(message) ((void)message, __builtin_trap())
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___VERBOSE_TRAP
diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in
index 1d6b21fc6bb45..90b202a2dae57 100644
--- a/libcxx/vendor/llvm/default_assertion_handler.in
+++ b/libcxx/vendor/llvm/default_assertion_handler.in
@@ -15,6 +15,7 @@
# include <__cxx03/__verbose_abort>
#else
# include <__config>
+# include <__verbose_trap>
# include <__verbose_abort>
#endif
@@ -28,18 +29,7 @@
#else
-# if __has_builtin(__builtin_verbose_trap)
-// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream
-// version before upstream Clang actually got the builtin.
-// TODO: Remove once AppleClang supports the two-arguments version of the builtin.
-# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700
-# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap(message)
-# else
-# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap("libc++", message)
-# endif
-# else
-# define _LIBCPP_ASSERTION_HANDLER(message) ((void)message, __builtin_trap())
-# endif
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
>From 1fcfec368e34964811270b9a10ad969814e3a691 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Fri, 11 Jul 2025 10:29:10 -0700
Subject: [PATCH 02/20] [libc++][hardening] Introduce a dylib function to log
hardening errors.
Unlike `verbose_abort`, this function merely logs the error but does not
terminate execution. It is intended to make it possible to implement the
`observe` semantic for Hardening.
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__configuration/availability.h | 5 ++
libcxx/include/__log_hardening_failure | 45 +++++++++++++++++
libcxx/src/CMakeLists.txt | 1 +
libcxx/src/log_hardening_failure.cpp | 49 +++++++++++++++++++
5 files changed, 101 insertions(+)
create mode 100644 libcxx/include/__log_hardening_failure
create mode 100644 libcxx/src/log_hardening_failure.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index c8e6d28584623..2f8be540e73e2 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -535,6 +535,7 @@ set(files
__locale_dir/time.h
__locale_dir/wbuffer_convert.h
__locale_dir/wstring_convert.h
+ __log_hardening_failure
__math/abs.h
__math/copysign.h
__math/error_functions.h
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index ae58e36b508b4..cb72e927caa9c 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -304,6 +304,11 @@
#define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15
#define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE
+// This controls whether the library provides a function to log hardening failures without terminating the program (for
+// the `observe` assertion semantic).
+#define _LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21
+#define _LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
+
// This controls the availability of the C++17 std::pmr library,
// which is implemented in large part in the built library.
//
diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure
new file mode 100644
index 0000000000000..73cff0ac64155
--- /dev/null
+++ b/libcxx/include/__log_hardening_failure
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOG_HARDENING_FAILURE
+#define _LIBCPP___LOG_HARDENING_FAILURE
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// This function should never be called directly from the code -- it should only be called through the
+// `_LIBCPP_LOG_HARDENING_FAILURE` macro.
+_LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_OVERRIDABLE_FUNC_VIS void
+__libcpp_log_hardening_failure(const char* message) _NOEXCEPT;
+
+// _LIBCPP_LOG_HARDENING_FAILURE(message)
+//
+// This macro is used to log a hardening failure without terminating the program (as is the case if the `observe`
+// assertion semantic is used). Where possible, it logs in a way that indicates a fatal error (which might include
+// capturing the stack trace).
+#if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
+
+# if !_LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE
+// The decltype is there to suppress -Wunused warnings in this configuration.
+void __use(const char*);
+# define _LIBCPP_LOG_HARDENING_FAILURE(message) (decltype(::std::__use(message))())
+# else
+# define _LIBCPP_LOG_HARDENING_FAILURE(message) ::std::__libcpp_log_hardening_failure(message)
+# endif
+
+#endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___LOG_HARDENING_FAILURE
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 97fe57a5f24f8..926deb3a1c732 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -30,6 +30,7 @@ set(LIBCXX_SOURCES
include/ryu/ryu.h
include/to_chars_floating_point.h
include/from_chars_floating_point.h
+ log_hardening_failure.cpp
memory.cpp
memory_resource.cpp
new_handler.cpp
diff --git a/libcxx/src/log_hardening_failure.cpp b/libcxx/src/log_hardening_failure.cpp
new file mode 100644
index 0000000000000..7e408a6f010b4
--- /dev/null
+++ b/libcxx/src/log_hardening_failure.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <__config>
+#include <__log_hardening_failure>
+#include <cstdio>
+
+#ifdef __BIONIC__
+# include <syslog.h>
+extern "C" void android_set_abort_message(const char* msg);
+#endif // __BIONIC__
+
+#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
+# include <os/reason_private.h>
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+_LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
+ // On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
+#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
+ os_fault_with_payload(
+ /*reason_namespace=*/OS_REASON_SECURITY,
+ /*reason_code=*/0,
+ /*payload=*/nullptr,
+ /*payload_size=*/0,
+ /*reason_string=*/message,
+ /*reason_flags=*/0);
+
+#elif defined(__BIONIC__)
+ // Show error in tombstone.
+ android_set_abort_message(message);
+
+ // Show error in logcat.
+ openlog("libc++", 0, 0);
+ syslog(LOG_CRIT, "%s", message);
+ closelog();
+
+#else
+ fprintf(stderr, "%s", message);
+#endif
+}
+
+_LIBCPP_END_NAMESPACE_STD
>From debdf1452cb4a3ba5258313f9b5c0fae146dd576 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Fri, 11 Jul 2025 10:58:57 -0700
Subject: [PATCH 03/20] [libc++][hardening] Introduce assertion semantics.
---
libcxx/include/__config | 30 +++++
libcxx/test/support/check_assertion.h | 120 ++++++++++++++++--
.../vendor/llvm/default_assertion_handler.in | 21 ++-
libcxxabi/src/CMakeLists.txt | 15 +--
libcxxabi/src/demangle/DemangleConfig.h | 5 +
libcxxabi/src/log_error_and_continue.cpp | 48 +++++++
libcxxabi/src/log_error_and_continue.h | 16 +++
7 files changed, 229 insertions(+), 26 deletions(-)
create mode 100644 libcxxabi/src/log_error_and_continue.cpp
create mode 100644 libcxxabi/src/log_error_and_continue.h
diff --git a/libcxx/include/__config b/libcxx/include/__config
index d940461c30234..2223d466c2a7f 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -147,6 +147,36 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \
_LIBCPP_HARDENING_MODE_DEBUG
# endif
+// Hardening assertion semantics mirror the evaluation semantics of P3100 Contracts:
+// - `ignore` does not evaluate the assertion;
+// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution;
+// - `quick-enforce` terminates the program as fast as possible (via trapping);
+// - `enforce` logs an error and then terminates the program.
+// Notes:
+// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant
+// to make adopting hardening easier but should not be used outside of this scenario;
+// - P3471 "Standard Library Hardening" wording precludes using the Contracts `ignore` semantic for hardened
+// preconditions in the Library; allowing this semantic to be used is a libc++ vendor extension.
+// clang-format off
+# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1)
+# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2)
+# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3)
+# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4)
+// clang-format on
+
+// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics.
+// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use
+// `enforce` (i.e., log and abort).
+# ifndef _LIBCPP_ASSERTION_SEMANTIC
+
+# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
+# else
+# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
+# endif
+
+# endif // _LIBCPP_ASSERTION_SEMANTIC
+
// } HARDENING
# define _LIBCPP_TOSTRING2(x) #x
diff --git a/libcxx/test/support/check_assertion.h b/libcxx/test/support/check_assertion.h
index a279400d651b4..7f8102d82970d 100644
--- a/libcxx/test/support/check_assertion.h
+++ b/libcxx/test/support/check_assertion.h
@@ -50,9 +50,17 @@ MatchResult MatchAssertionMessage(const std::string& text, std::string_view expe
std::regex assertion_format(".*###\\n(.*):(\\d+): assertion (.*) failed: (.*)\\n###");
std::smatch match_result;
- bool has_match = std::regex_match(text, match_result, assertion_format);
- assert(has_match);
- assert(match_result.size() == 5);
+ // If a non-terminating assertion semantic is used, more than one assertion might be triggered before the process
+ // dies, so we cannot expect the entire target string to match.
+ bool has_match = std::regex_search(text, match_result, assertion_format);
+ if (!has_match || match_result.size() != 5) {
+ std::stringstream matching_error;
+ matching_error //
+ << "Failed to parse the assertion message.\n" //
+ << "Expected message: '" << expected_message.data() << "'\n" //
+ << "Stderr contents: '" << text.c_str() << "'\n";
+ return MatchResult(/*success=*/false, matching_error.str());
+ }
const std::string& file = match_result[1];
int line = std::stoi(match_result[2]);
@@ -85,13 +93,16 @@ Matcher MakeAnyMatcher() {
}
enum class DeathCause {
- // Valid causes
+ // Valid causes.
VerboseAbort = 1,
StdAbort,
StdTerminate,
Trap,
- // Invalid causes
+ // Causes that might be invalid or might stem from undefined behavior (relevant for non-terminating assertion
+ // semantics).
DidNotDie,
+ Segfault,
+ // Always invalid causes.
SetupFailure,
Unknown
};
@@ -108,6 +119,16 @@ bool IsValidCause(DeathCause cause) {
}
}
+bool IsTestSetupErrorCause(DeathCause cause) {
+ switch (cause) {
+ case DeathCause::SetupFailure:
+ case DeathCause::Unknown:
+ return true;
+ default:
+ return false;
+ }
+}
+
std::string ToString(DeathCause cause) {
switch (cause) {
case DeathCause::VerboseAbort:
@@ -120,10 +141,12 @@ std::string ToString(DeathCause cause) {
return "trap";
case DeathCause::DidNotDie:
return "<invalid cause (child did not die)>";
+ case DeathCause::Segfault:
+ return "<invalid cause (segmentation fault)>";
case DeathCause::SetupFailure:
- return "<invalid cause (child failed to set up test environment)>";
+ return "<test setup error (child failed to set up test environment)>";
case DeathCause::Unknown:
- return "<invalid cause (cause unknown)>";
+ return "<test setup error (test doesn't know how to interpret the death cause)>";
}
assert(false && "Unreachable");
@@ -225,9 +248,38 @@ class DeathTest {
return DeathTestResult(Outcome::Success, cause);
}
- void PrintFailureDetails(std::string_view failure_description, std::string_view stmt, DeathCause cause) const {
- std::fprintf(
- stderr, "Failure: EXPECT_DEATH( %s ) failed!\n(reason: %s)\n\n", stmt.data(), failure_description.data());
+ // When non-terminating assertion semantics are used, the program will invoke UB which might or might not crash the
+ // process; we make sure that the execution produces the expected error message but otherwise consider the test run
+ // successful whether the child process dies or not.
+ template <class Func>
+ DeathTestResult RunWithoutGuaranteedDeath(Func&& func, const Matcher& matcher) {
+ std::signal(SIGABRT, [](int) { StopChildProcess(DeathCause::StdAbort); });
+ std::set_terminate([] { StopChildProcess(DeathCause::StdTerminate); });
+
+ DeathCause cause = Run(func);
+
+ if (IsTestSetupErrorCause(cause)) {
+ return DeathTestResult(Outcome::InvalidCause, cause, ToString(cause));
+ }
+
+ MatchResult match_result = matcher(GetChildStdErr());
+ if (!match_result.first) {
+ auto failure_description = std::string("Child produced a different error message\n") + match_result.second;
+ return DeathTestResult(Outcome::UnexpectedErrorMessage, cause, failure_description);
+ }
+
+ return DeathTestResult(Outcome::Success, cause);
+ }
+
+ void PrintFailureDetails(std::string_view invocation,
+ std::string_view failure_description,
+ std::string_view stmt,
+ DeathCause cause) const {
+ std::fprintf(stderr,
+ "Failure: %s( %s ) failed!\n(reason: %s)\n\n",
+ invocation.data(),
+ stmt.data(),
+ failure_description.data());
if (cause != DeathCause::Unknown) {
std::fprintf(stderr, "child exit code: %d\n", GetChildExitCode());
@@ -311,10 +363,13 @@ class DeathTest {
if (WIFSIGNALED(status_value)) {
exit_code_ = WTERMSIG(status_value);
- // `__builtin_trap` generqtes `SIGILL` on x86 and `SIGTRAP` on ARM.
+ // `__builtin_trap` generates `SIGILL` on x86 and `SIGTRAP` on ARM.
if (exit_code_ == SIGILL || exit_code_ == SIGTRAP) {
return DeathCause::Trap;
}
+ if (exit_code_ == SIGSEGV) {
+ return DeathCause::Segfault;
+ }
}
return DeathCause::Unknown;
@@ -334,6 +389,12 @@ class DeathTest {
};
#ifdef _LIBCPP_VERSION
+void std::__libcpp_log_hardening_failure(const char* message) noexcept {
+ std::fprintf(stderr, "%s\n", Marker);
+ std::fprintf(stderr, "%s", message);
+ std::fprintf(stderr, "%s\n", Marker);
+}
+
void std::__libcpp_verbose_abort(char const* format, ...) noexcept {
va_list args;
va_start(args, format);
@@ -357,7 +418,7 @@ bool ExpectDeath(
DeathTest test_case;
DeathTestResult test_result = test_case.Run(expected_causes, func, matcher);
if (!test_result.success()) {
- test_case.PrintFailureDetails(test_result.failure_description(), stmt, test_result.cause());
+ test_case.PrintFailureDetails("EXPECT_DEATH", test_result.failure_description(), stmt, test_result.cause());
}
return test_result.success();
@@ -378,6 +439,22 @@ bool ExpectDeath(DeathCause expected_cause, const char* stmt, Func&& func) {
return ExpectDeath(std::array<DeathCause, 1>{expected_cause}, stmt, func, MakeAnyMatcher());
}
+template <class Func>
+bool ExpectLog(const char* stmt, Func&& func, const Matcher& matcher) {
+ DeathTest test_case;
+ DeathTestResult test_result = test_case.RunWithoutGuaranteedDeath(func, matcher);
+ if (!test_result.success()) {
+ test_case.PrintFailureDetails("EXPECT_LOG", test_result.failure_description(), stmt, test_result.cause());
+ }
+
+ return test_result.success();
+}
+
+template <class Func>
+bool ExpectLog(const char* stmt, Func&& func) {
+ return ExpectLog(stmt, func, MakeAnyMatcher());
+}
+
// clang-format off
/// Assert that the specified expression aborts with the expected cause and, optionally, error message.
@@ -392,13 +469,28 @@ bool ExpectDeath(DeathCause expected_cause, const char* stmt, Func&& func) {
#define EXPECT_STD_TERMINATE(...) \
assert( ExpectDeath(DeathCause::StdTerminate, #__VA_ARGS__, __VA_ARGS__) )
-#if defined(_LIBCPP_HARDENING_MODE) && _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+#if defined(_LIBCPP_ASSERTION_SEMANTIC)
+
+#if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
assert(( ExpectDeath(DeathCause::VerboseAbort, #expr, [&]() { (void)(expr); }, MakeAssertionMessageMatcher(message)) ))
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
+#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
+ assert(( ExpectDeath(DeathCause::Trap, #expr, [&]() { (void)(expr); }) ))
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
+#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
+ assert(( ExpectLog(#expr, [&]() { (void)(expr); }, MakeAssertionMessageMatcher(message)) ))
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
+ assert(( ExpectLog(#expr, [&]() { (void)(expr); }) ))
+#else
+#error "_LIBCPP_ASSERTION_SEMANTIC is set to an invalid value"
+#endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
+
#else
#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
assert(( ExpectDeath(DeathCause::Trap, #expr, [&]() { (void)(expr); }) ))
-#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+#endif // defined(_LIBCPP_ASSERTION_SEMANTIC)
// clang-format on
diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in
index 90b202a2dae57..4ece031c03ece 100644
--- a/libcxx/vendor/llvm/default_assertion_handler.in
+++ b/libcxx/vendor/llvm/default_assertion_handler.in
@@ -15,22 +15,35 @@
# include <__cxx03/__verbose_abort>
#else
# include <__config>
-# include <__verbose_trap>
+# include <__log_hardening_failure>
# include <__verbose_abort>
+# include <__verbose_trap>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+#if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
+
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_HARDENING_FAILURE(message)
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
+
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
#else
-# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
+# error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \
+_LIBCPP_ASSERTION_SEMANTIC_IGNORE, \
+_LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \
+_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \
+_LIBCPP_ASSERTION_SEMANTIC_ENFORCE
-#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+#endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
#endif // _LIBCPP___ASSERTION_HANDLER
diff --git a/libcxxabi/src/CMakeLists.txt b/libcxxabi/src/CMakeLists.txt
index 0675577aed6a1..9a9a65ce3aaa1 100644
--- a/libcxxabi/src/CMakeLists.txt
+++ b/libcxxabi/src/CMakeLists.txt
@@ -16,6 +16,7 @@ set(LIBCXXABI_SOURCES
# Internal files
abort_message.cpp
fallback_malloc.cpp
+ log_error_and_continue.cpp
private_typeinfo.cpp
)
@@ -172,12 +173,11 @@ if (LIBCXXABI_USE_LLVM_UNWINDER)
target_link_libraries(cxxabi_shared_objects PUBLIC unwind_shared)
endif()
endif()
-target_link_libraries(cxxabi_shared_objects
- PUBLIC cxxabi-headers
- PRIVATE cxx-headers runtimes-libc-headers ${LIBCXXABI_LIBRARIES})
+target_link_libraries(cxxabi_shared_objects PRIVATE cxx-headers ${LIBCXXABI_LIBRARIES})
if (NOT CXX_SUPPORTS_NOSTDLIBXX_FLAG)
target_link_libraries(cxxabi_shared_objects PRIVATE ${LIBCXXABI_BUILTINS_LIBRARY})
endif()
+target_link_libraries(cxxabi_shared_objects PUBLIC cxxabi-headers)
set_target_properties(cxxabi_shared_objects
PROPERTIES
CXX_EXTENSIONS OFF
@@ -216,7 +216,7 @@ if (ZOS)
endif ()
target_link_libraries(cxxabi_shared
- PUBLIC cxxabi_shared_objects runtimes-libc-shared
+ PUBLIC cxxabi_shared_objects
PRIVATE ${LIBCXXABI_LIBRARIES})
if (LIBCXXABI_ENABLE_SHARED)
@@ -275,9 +275,8 @@ if (LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC
target_link_libraries(cxxabi_static_objects PUBLIC unwind_static_objects) # propagate usage requirements
target_sources(cxxabi_static_objects PUBLIC $<TARGET_OBJECTS:unwind_static_objects>)
endif()
-target_link_libraries(cxxabi_static_objects
- PUBLIC cxxabi-headers
- PRIVATE cxx-headers runtimes-libc-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
+target_link_libraries(cxxabi_static_objects PRIVATE cxx-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
+target_link_libraries(cxxabi_static_objects PUBLIC cxxabi-headers)
set_target_properties(cxxabi_static_objects
PROPERTIES
CXX_EXTENSIONS OFF
@@ -313,7 +312,7 @@ endif()
add_library(cxxabi_static STATIC)
if (LIBCXXABI_USE_LLVM_UNWINDER AND NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
- target_link_libraries(cxxabi_static PUBLIC unwind_static runtimes-libc-static)
+ target_link_libraries(cxxabi_static PUBLIC unwind_static)
endif()
set_target_properties(cxxabi_static
PROPERTIES
diff --git a/libcxxabi/src/demangle/DemangleConfig.h b/libcxxabi/src/demangle/DemangleConfig.h
index 06fd223f5553f..994d59507588f 100644
--- a/libcxxabi/src/demangle/DemangleConfig.h
+++ b/libcxxabi/src/demangle/DemangleConfig.h
@@ -19,6 +19,11 @@
#include "../abort_message.h"
#endif
+#ifndef _LIBCPP_LOG_HARDENING_FAILURE
+#define _LIBCPP_LOG_HARDENING_FAILURE(message) __log_error_and_continue(message)
+#include "../log_error_and_continue.h"
+#endif
+
#include <version>
#ifdef _MSC_VER
diff --git a/libcxxabi/src/log_error_and_continue.cpp b/libcxxabi/src/log_error_and_continue.cpp
new file mode 100644
index 0000000000000..51088cd11d914
--- /dev/null
+++ b/libcxxabi/src/log_error_and_continue.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "log_error_and_continue.h"
+
+#ifdef __BIONIC__
+# include <syslog.h>
+extern "C" void android_set_abort_message(const char* msg);
+#endif // __BIONIC__
+
+#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
+# include <os/reason_private.h>
+# define _LIBCXXABI_USE_OS_FAULT
+#endif
+
+void __log_error_and_continue(const char* message)
+{
+ // On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
+#if defined(_LIBCXXABI_USE_OS_FAULT)
+ os_fault_with_payload(
+ /*reason_namespace=*/OS_REASON_SECURITY,
+ /*reason_code=*/0,
+ /*payload=*/nullptr,
+ /*payload_size=*/0,
+ /*reason_string=*/message,
+ /*reason_flags=*/0);
+
+#elif defined(__BIONIC__)
+ // Show error in tombstone.
+ android_set_abort_message(message);
+
+ // Show error in logcat.
+ openlog("libc++", 0, 0);
+ syslog(LOG_CRIT, "%s", message);
+ closelog();
+
+#else
+ fprintf(stderr, "%s", message);
+#endif
+}
diff --git a/libcxxabi/src/log_error_and_continue.h b/libcxxabi/src/log_error_and_continue.h
new file mode 100644
index 0000000000000..e976c1de65d06
--- /dev/null
+++ b/libcxxabi/src/log_error_and_continue.h
@@ -0,0 +1,16 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LOG_ERROR_AND_CONTINUE_H_
+#define __LOG_ERROR_AND_CONTINUE_H_
+
+#include "cxxabi.h"
+
+extern "C" _LIBCXXABI_HIDDEN void __log_error_and_continue(const char* message);
+
+#endif // __LOG_ERROR_AND_CONTINUE_H_
>From 3ca83e671aa6b147cd855fc22d127d9b2fd16915 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 01:11:47 -0700
Subject: [PATCH 04/20] Address feedback
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__cxx03/__verbose_trap | 36 +++++++++++++++++++
libcxx/include/module.modulemap.in | 3 ++
.../vendor/llvm/default_assertion_handler.in | 3 +-
4 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 libcxx/include/__cxx03/__verbose_trap
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index f79edc9e32599..4f2a8dddad92c 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -1570,6 +1570,7 @@ set(files
__cxx03/__utility/unreachable.h
__cxx03/__variant/monostate.h
__cxx03/__verbose_abort
+ __cxx03/__verbose_trap
__cxx03/algorithm
__cxx03/array
__cxx03/atomic
diff --git a/libcxx/include/__cxx03/__verbose_trap b/libcxx/include/__cxx03/__verbose_trap
new file mode 100644
index 0000000000000..755124b97a5ac
--- /dev/null
+++ b/libcxx/include/__cxx03/__verbose_trap
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CXX03___VERBOSE_TRAP
+#define _LIBCPP___CXX03___VERBOSE_TRAP
+
+#include <__cxx03/__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if __has_builtin(__builtin_verbose_trap)
+// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream
+// version before upstream Clang actually got the builtin.
+// TODO: Remove once AppleClang supports the two-arguments version of the builtin.
+# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700
+# define _LIBCPP_VERBOSE_TRAP(message) __builtin_verbose_trap(message)
+# else
+# define _LIBCPP_VERBOSE_TRAP(message) __builtin_verbose_trap("libc++", message)
+# endif
+#else
+# define _LIBCPP_VERBOSE_TRAP(message) ((void)message, __builtin_trap())
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___CXX03___VERBOSE_TRAP
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 45b9c72a05b82..61ba1c381b2b3 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2356,6 +2356,9 @@ module std [system] {
module verbose_abort {
header "__verbose_abort"
}
+ module verbose_trap {
+ header "__verbose_trap"
+ }
module internal_assert {
header "__assert"
export *
diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in
index 90b202a2dae57..f115658f9f3c6 100644
--- a/libcxx/vendor/llvm/default_assertion_handler.in
+++ b/libcxx/vendor/llvm/default_assertion_handler.in
@@ -13,10 +13,11 @@
#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
# include <__cxx03/__config>
# include <__cxx03/__verbose_abort>
+# include <__cxx03/__verbose_trap>
#else
# include <__config>
-# include <__verbose_trap>
# include <__verbose_abort>
+# include <__verbose_trap>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
>From ef34aded6cfa935fe9d904bb8d4f79bfb705137a Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 01:58:15 -0700
Subject: [PATCH 05/20] Address feedback
---
libcxx/include/CMakeLists.txt | 2 +-
libcxx/include/__configuration/availability.h | 8 +--
libcxx/include/__log_error | 50 +++++++++++++++++++
libcxx/include/__log_hardening_failure | 45 -----------------
libcxx/include/module.modulemap.in | 3 ++
libcxx/src/CMakeLists.txt | 2 +-
...og_hardening_failure.cpp => log_error.cpp} | 16 +++++-
7 files changed, 73 insertions(+), 53 deletions(-)
create mode 100644 libcxx/include/__log_error
delete mode 100644 libcxx/include/__log_hardening_failure
rename libcxx/src/{log_hardening_failure.cpp => log_error.cpp} (81%)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 2f8be540e73e2..ceaf45e9e8ae6 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -535,7 +535,7 @@ set(files
__locale_dir/time.h
__locale_dir/wbuffer_convert.h
__locale_dir/wstring_convert.h
- __log_hardening_failure
+ __log_error
__math/abs.h
__math/copysign.h
__math/error_functions.h
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index cb72e927caa9c..5de0b98ba22a9 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -304,10 +304,10 @@
#define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15
#define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE
-// This controls whether the library provides a function to log hardening failures without terminating the program (for
-// the `observe` assertion semantic).
-#define _LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21
-#define _LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
+// This controls whether the library provides a function to log errors without terminating the program (used in
+// particular by the `observe` assertion semantic).
+#define _LIBCPP_AVAILABILITY_HAS_LOG_ERROR _LIBCPP_INTRODUCED_IN_LLVM_21
+#define _LIBCPP_AVAILABILITY_LOG_ERROR _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
// This controls the availability of the C++17 std::pmr library,
// which is implemented in large part in the built library.
diff --git a/libcxx/include/__log_error b/libcxx/include/__log_error
new file mode 100644
index 0000000000000..9f308898247c4
--- /dev/null
+++ b/libcxx/include/__log_error
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOG_ERROR
+#define _LIBCPP___LOG_ERROR
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+enum class _LogErrorReason {
+ // Where possible, it logs in a way that indicates a fatal error (which might include capturing the stack trace).
+ _HardeningFailure
+};
+
+// This function should never be called directly from the code -- it should only be called through the
+// `_LIBCPP_LOG_ERROR` macro.
+_LIBCPP_AVAILABILITY_LOG_ERROR _LIBCPP_EXPORTED_FROM_ABI void
+__log_error(_LogErrorReason __reason, const char* __message) _NOEXCEPT;
+
+// _LIBCPP_LOG_ERROR(message)
+//
+// This macro is used to log an error without terminating the program (as is the case for hardening failures if the
+// `observe` assertion semantic is used, for example).
+
+#if !defined(_LIBCPP_LOG_ERROR)
+
+# if !_LIBCPP_AVAILABILITY_HAS_LOG_ERROR
+// The decltype is there to suppress -Wunused warnings in this configuration.
+void __use(const char*);
+# define _LIBCPP_LOG_ERROR(__message) (decltype(::std::__use(__message))())
+# else
+# define _LIBCPP_LOG_ERROR(__reason, __message) ::std::__log_error(__reason, __message)
+# endif
+
+#endif // !defined(_LIBCPP_LOG_ERROR)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___LOG_ERROR
diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure
deleted file mode 100644
index 73cff0ac64155..0000000000000
--- a/libcxx/include/__log_hardening_failure
+++ /dev/null
@@ -1,45 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP___LOG_HARDENING_FAILURE
-#define _LIBCPP___LOG_HARDENING_FAILURE
-
-#include <__config>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-# pragma GCC system_header
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-// This function should never be called directly from the code -- it should only be called through the
-// `_LIBCPP_LOG_HARDENING_FAILURE` macro.
-_LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_OVERRIDABLE_FUNC_VIS void
-__libcpp_log_hardening_failure(const char* message) _NOEXCEPT;
-
-// _LIBCPP_LOG_HARDENING_FAILURE(message)
-//
-// This macro is used to log a hardening failure without terminating the program (as is the case if the `observe`
-// assertion semantic is used). Where possible, it logs in a way that indicates a fatal error (which might include
-// capturing the stack trace).
-#if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
-
-# if !_LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE
-// The decltype is there to suppress -Wunused warnings in this configuration.
-void __use(const char*);
-# define _LIBCPP_LOG_HARDENING_FAILURE(message) (decltype(::std::__use(message))())
-# else
-# define _LIBCPP_LOG_HARDENING_FAILURE(message) ::std::__libcpp_log_hardening_failure(message)
-# endif
-
-#endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___LOG_HARDENING_FAILURE
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 45b9c72a05b82..763d32296a03d 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2353,6 +2353,9 @@ module std [system] {
header "__std_mbstate_t.h"
export *
}
+ module log_error {
+ header "__log_error"
+ }
module verbose_abort {
header "__verbose_abort"
}
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 926deb3a1c732..0e83b2728aa5a 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -30,7 +30,7 @@ set(LIBCXX_SOURCES
include/ryu/ryu.h
include/to_chars_floating_point.h
include/from_chars_floating_point.h
- log_hardening_failure.cpp
+ log_error.cpp
memory.cpp
memory_resource.cpp
new_handler.cpp
diff --git a/libcxx/src/log_hardening_failure.cpp b/libcxx/src/log_error.cpp
similarity index 81%
rename from libcxx/src/log_hardening_failure.cpp
rename to libcxx/src/log_error.cpp
index 7e408a6f010b4..01ddaf65bf618 100644
--- a/libcxx/src/log_hardening_failure.cpp
+++ b/libcxx/src/log_error.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include <__config>
-#include <__log_hardening_failure>
+#include <__log_error>
#include <cstdio>
#ifdef __BIONIC__
@@ -21,7 +21,9 @@ extern "C" void android_set_abort_message(const char* msg);
_LIBCPP_BEGIN_NAMESPACE_STD
-_LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
+namespace {
+
+void log_fatal_error(const char* message) noexcept {
// On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
os_fault_with_payload(
@@ -46,4 +48,14 @@ _LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
#endif
}
+} // namespace
+
+void __log_error(_LogErrorReason reason, const char* message) noexcept {
+ switch (reason) {
+ case _LogErrorReason::_HardeningFailure:
+ default:
+ log_fatal_error(message);
+ }
+}
+
_LIBCPP_END_NAMESPACE_STD
>From 01eb85de6072d3b188cf357573826f663ebfa51d Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 15:01:05 -0700
Subject: [PATCH 06/20] Update the ABI list plus minor tweaks.
---
...le-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
libcxx/src/CMakeLists.txt | 2 +-
libcxx/src/log_error.cpp | 4 ++--
libcxx/utils/libcxx/test/features.py | 8 ++++++++
4 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 162757c7e37ec..bc6bdca5b8a2d 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -534,6 +534,7 @@
{'is_defined': True, 'name': '__ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNKSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNKSt3__115error_condition7messageEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'}
@@ -944,6 +945,7 @@
{'is_defined': True, 'name': '__ZNSt3__110to_wstringEx', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__110to_wstringEy', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__111__log_errorENS_15_LogErrorReasonEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'}
@@ -1125,6 +1127,7 @@
{'is_defined': True, 'name': '__ZNSt3__112system_errorD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112system_errorD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112system_errorD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'}
@@ -1305,7 +1308,6 @@
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
-{'is_defined': True, 'name': '__ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__114__num_get_base5__srcE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
@@ -1508,7 +1510,6 @@
{'is_defined': True, 'name': '__ZNSt3__117bad_function_callD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__117bad_function_callD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__117bad_function_callD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '__ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__117iostream_categoryEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'}
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 0e83b2728aa5a..fe8e57690a880 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -30,8 +30,8 @@ set(LIBCXX_SOURCES
include/ryu/ryu.h
include/to_chars_floating_point.h
include/from_chars_floating_point.h
- log_error.cpp
memory.cpp
+ log_error.cpp
memory_resource.cpp
new_handler.cpp
new_helpers.cpp
diff --git a/libcxx/src/log_error.cpp b/libcxx/src/log_error.cpp
index 01ddaf65bf618..53cf3c7aa7ac2 100644
--- a/libcxx/src/log_error.cpp
+++ b/libcxx/src/log_error.cpp
@@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace {
-void log_fatal_error(const char* message) noexcept {
+void log_security_failure(const char* message) noexcept {
// On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
os_fault_with_payload(
@@ -54,7 +54,7 @@ void __log_error(_LogErrorReason reason, const char* message) noexcept {
switch (reason) {
case _LogErrorReason::_HardeningFailure:
default:
- log_fatal_error(message);
+ log_security_failure(message);
}
}
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 0cb81546665d4..8433ea178080b 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -894,6 +894,14 @@ def check_gdb(cfg):
cfg.available_features,
),
),
+ # Tests that require __log_error support in the built library
+ Feature(
+ name="availability-log_error-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-21)",
+ cfg.available_features,
+ ),
+ ),
# Tests that require std::pmr support in the built library
Feature(
name="availability-pmr-missing",
>From 189cdc1809855f6d02ad68982a017facdd787634 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 15:58:27 -0700
Subject: [PATCH 07/20] Address feedback.
---
libcxx/include/__config | 12 +++--
.../vendor/llvm/default_assertion_handler.in | 4 +-
libcxxabi/src/CMakeLists.txt | 1 -
libcxxabi/src/demangle/DemangleConfig.h | 8 ++--
libcxxabi/src/log_error_and_continue.cpp | 48 -------------------
libcxxabi/src/log_error_and_continue.h | 16 -------
6 files changed, 15 insertions(+), 74 deletions(-)
delete mode 100644 libcxxabi/src/log_error_and_continue.cpp
delete mode 100644 libcxxabi/src/log_error_and_continue.h
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 2223d466c2a7f..ef0c8b48b658b 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -147,16 +147,20 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \
_LIBCPP_HARDENING_MODE_DEBUG
# endif
-// Hardening assertion semantics mirror the evaluation semantics of P3100 Contracts:
-// - `ignore` does not evaluate the assertion;
+// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts:
+// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts
+// `ignore` semantic which wouldn't evaluate the assertion at all);
// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution;
// - `quick-enforce` terminates the program as fast as possible (via trapping);
// - `enforce` logs an error and then terminates the program.
+//
// Notes:
// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant
// to make adopting hardening easier but should not be used outside of this scenario;
-// - P3471 "Standard Library Hardening" wording precludes using the Contracts `ignore` semantic for hardened
-// preconditions in the Library; allowing this semantic to be used is a libc++ vendor extension.
+// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts
+// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for
+// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened"
+// implementation, unlike the other semantics above.
// clang-format off
# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1)
# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2)
diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in
index 3ec9a94790712..d1ddedf1bb31b 100644
--- a/libcxx/vendor/llvm/default_assertion_handler.in
+++ b/libcxx/vendor/llvm/default_assertion_handler.in
@@ -16,7 +16,7 @@
# include <__cxx03/__verbose_trap>
#else
# include <__config>
-# include <__log_hardening_failure>
+# include <__log_error>
# include <__verbose_abort>
# include <__verbose_trap>
#endif
@@ -29,7 +29,7 @@
# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
-# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_HARDENING_FAILURE(message)
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_ERROR(_LogErrorReason::_HardeningFailure, message)
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
diff --git a/libcxxabi/src/CMakeLists.txt b/libcxxabi/src/CMakeLists.txt
index 9a9a65ce3aaa1..0a6fc892a4f69 100644
--- a/libcxxabi/src/CMakeLists.txt
+++ b/libcxxabi/src/CMakeLists.txt
@@ -16,7 +16,6 @@ set(LIBCXXABI_SOURCES
# Internal files
abort_message.cpp
fallback_malloc.cpp
- log_error_and_continue.cpp
private_typeinfo.cpp
)
diff --git a/libcxxabi/src/demangle/DemangleConfig.h b/libcxxabi/src/demangle/DemangleConfig.h
index 994d59507588f..f1f161a54afbd 100644
--- a/libcxxabi/src/demangle/DemangleConfig.h
+++ b/libcxxabi/src/demangle/DemangleConfig.h
@@ -19,9 +19,11 @@
#include "../abort_message.h"
#endif
-#ifndef _LIBCPP_LOG_HARDENING_FAILURE
-#define _LIBCPP_LOG_HARDENING_FAILURE(message) __log_error_and_continue(message)
-#include "../log_error_and_continue.h"
+#ifndef _LIBCPP_LOG_ERROR
+// Libc++abi does not have any functionality to log and continue, so we drop error messages when we build the demangler
+// with `observe` assertion semantic. Once the layering with libc++ is improved, this could use the libc++ functionality
+// to log hardening failures.
+#define _LIBCPP_LOG_ERROR(reason, message) ((void)0)
#endif
#include <version>
diff --git a/libcxxabi/src/log_error_and_continue.cpp b/libcxxabi/src/log_error_and_continue.cpp
deleted file mode 100644
index 51088cd11d914..0000000000000
--- a/libcxxabi/src/log_error_and_continue.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include "log_error_and_continue.h"
-
-#ifdef __BIONIC__
-# include <syslog.h>
-extern "C" void android_set_abort_message(const char* msg);
-#endif // __BIONIC__
-
-#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
-# include <os/reason_private.h>
-# define _LIBCXXABI_USE_OS_FAULT
-#endif
-
-void __log_error_and_continue(const char* message)
-{
- // On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
-#if defined(_LIBCXXABI_USE_OS_FAULT)
- os_fault_with_payload(
- /*reason_namespace=*/OS_REASON_SECURITY,
- /*reason_code=*/0,
- /*payload=*/nullptr,
- /*payload_size=*/0,
- /*reason_string=*/message,
- /*reason_flags=*/0);
-
-#elif defined(__BIONIC__)
- // Show error in tombstone.
- android_set_abort_message(message);
-
- // Show error in logcat.
- openlog("libc++", 0, 0);
- syslog(LOG_CRIT, "%s", message);
- closelog();
-
-#else
- fprintf(stderr, "%s", message);
-#endif
-}
diff --git a/libcxxabi/src/log_error_and_continue.h b/libcxxabi/src/log_error_and_continue.h
deleted file mode 100644
index e976c1de65d06..0000000000000
--- a/libcxxabi/src/log_error_and_continue.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __LOG_ERROR_AND_CONTINUE_H_
-#define __LOG_ERROR_AND_CONTINUE_H_
-
-#include "cxxabi.h"
-
-extern "C" _LIBCXXABI_HIDDEN void __log_error_and_continue(const char* message);
-
-#endif // __LOG_ERROR_AND_CONTINUE_H_
>From 94ef9a34532637011ec831c321447b3566764fa8 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 18:38:03 -0700
Subject: [PATCH 08/20] Test improvements
---
libcxx/src/log_error.cpp | 6 ++---
.../extents/assert.ctor_from_array.pass.cpp | 21 +++++++++++-----
.../assert.ctor_from_integral.pass.cpp | 6 ++---
.../layout_left/assert.conversion.pass.cpp | 4 +--
.../layout_left/assert.ctor.extents.pass.cpp | 5 +++-
.../assert.ctor.layout_right.pass.cpp | 4 +--
.../layout_right/assert.conversion.pass.cpp | 6 ++---
.../layout_right/assert.ctor.extents.pass.cpp | 3 ++-
.../assert.ctor.layout_left.pass.cpp | 4 +--
.../layout_stride/assert.conversion.pass.cpp | 18 +++++++------
...ert.ctor.extents_array.non_unique.pass.cpp | 4 +--
.../assert.ctor.extents_array.pass.cpp | 8 +++---
...sert.ctor.extents_span.non_unique.pass.cpp | 4 +--
.../thread/thread.latch/assert.ctor.pass.cpp | 9 ++++---
.../thread.semaphore/assert.ctor.pass.cpp | 2 +-
.../assert.ctor.pass.cpp | 2 ++
.../assert.ctor.pass.cpp | 2 ++
.../assert.to_local.pass.cpp | 1 +
.../time.zone.members/assert.to_sys.pass.cpp | 2 ++
.../assert.to_sys_choose.pass.cpp | 2 ++
libcxx/test/support/check_assertion.h | 25 +++++++++++--------
.../vendor/llvm/default_assertion_handler.in | 2 +-
22 files changed, 84 insertions(+), 56 deletions(-)
diff --git a/libcxx/src/log_error.cpp b/libcxx/src/log_error.cpp
index 53cf3c7aa7ac2..4e695ff380e8e 100644
--- a/libcxx/src/log_error.cpp
+++ b/libcxx/src/log_error.cpp
@@ -24,6 +24,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace {
void log_security_failure(const char* message) noexcept {
+ // Always log the message to `stderr` in case the platform-specific system calls fail.
+ fprintf(stderr, "%s", message);
+
// On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
os_fault_with_payload(
@@ -42,9 +45,6 @@ void log_security_failure(const char* message) noexcept {
openlog("libc++", 0, 0);
syslog(LOG_CRIT, "%s", message);
closelog();
-
-#else
- fprintf(stderr, "%s", message);
#endif
}
diff --git a/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp
index 90cb0c84a063b..6849b6a5f2e6c 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp
@@ -43,18 +43,27 @@ int main(int, char**) {
}
// mismatch of static extent
{
- TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<int, D, 5> e1(std::array{1000, 3}); }()),
- "extents construction: mismatch of provided arguments with static extents.");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ ([] {
+ [[maybe_unused]] std::extents<int, D, 5> e1(std::array{1000, 3});
+ }()),
+ "extents construction: mismatch of provided arguments with static extents.");
}
// value out of range
{
- TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(std::array{1000, 5}); }()),
- "extents ctor: arguments must be representable as index_type and nonnegative");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ ([] {
+ [[maybe_unused]] std::extents<signed char, D, 5> e1(std::array{1000, 5});
+ }()),
+ "extents ctor: arguments must be representable as index_type and nonnegative");
}
// negative value
{
- TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(std::array{-1, 5}); }()),
- "extents ctor: arguments must be representable as index_type and nonnegative");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ ([] {
+ [[maybe_unused]] std::extents<signed char, D, 5> e1(std::array{-1, 5});
+ }()),
+ "extents ctor: arguments must be representable as index_type and nonnegative");
}
return 0;
}
diff --git a/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_integral.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_integral.pass.cpp
index 37e79aabf8532..17bab03b922e6 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_integral.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_integral.pass.cpp
@@ -45,17 +45,17 @@ int main(int, char**) {
}
// mismatch of static extent
{
- TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<int, D, 5> e1(1000, 3); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([] { [[maybe_unused]] std::extents<int, D, 5> e1(1000, 3); }()),
"extents construction: mismatch of provided arguments with static extents.");
}
// value out of range
{
- TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(1000, 5); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([] { [[maybe_unused]] std::extents<signed char, D, 5> e1(1000, 5); }()),
"extents ctor: arguments must be representable as index_type and nonnegative");
}
// negative value
{
- TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(-1, 5); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([] { [[maybe_unused]] std::extents<signed char, D, 5> e1(-1, 5); }()),
"extents ctor: arguments must be representable as index_type and nonnegative");
}
return 0;
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.conversion.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.conversion.pass.cpp
index 7b6616f19d724..c67529671fcf7 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.conversion.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.conversion.pass.cpp
@@ -44,7 +44,7 @@ int main(int, char**) {
{
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_left::mapping<std::extents<signed char, D>> m(
+ [[maybe_unused]] std::layout_left::mapping<std::extents<signed char, D>> m(
std::layout_left::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
}()),
"extents ctor: arguments must be representable as index_type and nonnegative");
@@ -55,7 +55,7 @@ int main(int, char**) {
[[maybe_unused]] std::extents<signed char, D, 5> e(arg_exts);
// but the product is not, so we can't use it for layout_left
TEST_LIBCPP_ASSERT_FAILURE(
- ([=] { std::layout_left::mapping<std::extents<signed char, D, 5>> m(arg); }()),
+ ([=] { [[maybe_unused]] std::layout_left::mapping<std::extents<signed char, D, 5>> m(arg); }()),
"layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type.");
}
return 0;
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.extents.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.extents.pass.cpp
index 7c96f8ec9353f..45f07f1ed5c06 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.extents.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.extents.pass.cpp
@@ -31,7 +31,10 @@ int main(int, char**) {
{
// the extents are representable but the product is not, so we can't use it for layout_left
TEST_LIBCPP_ASSERT_FAILURE(
- ([=] { std::layout_left::mapping<std::extents<signed char, D, 5>> m(std::extents<signed char, D, 5>(100)); }()),
+ ([=] {
+ [[maybe_unused]] std::layout_left::mapping<std::extents<signed char, D, 5>> m(
+ std::extents<signed char, D, 5>(100));
+ }()),
"layout_left::mapping extents ctor: product of extents must be representable as index_type.");
}
return 0;
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.layout_right.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.layout_right.pass.cpp
index e578bac2103b0..04a6c59d265e1 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.layout_right.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.layout_right.pass.cpp
@@ -39,14 +39,14 @@ int main(int, char**) {
}
// mismatch of static extent
{
- TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<int, 3>> m(arg); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([=] { [[maybe_unused]] std::layout_left::mapping<std::extents<int, 3>> m(arg); }()),
"extents construction: mismatch of provided arguments with static extents.");
}
// non-representability of extents itself
{
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_left::mapping<std::extents<signed char, D>> m(
+ [[maybe_unused]] std::layout_left::mapping<std::extents<signed char, D>> m(
std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
}()),
"extents ctor: arguments must be representable as index_type and nonnegative");
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.conversion.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.conversion.pass.cpp
index df16edb925407..81fc8b5d65e62 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.conversion.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.conversion.pass.cpp
@@ -37,14 +37,14 @@ int main(int, char**) {
}
// mismatch of static extent
{
- TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_right::mapping<std::extents<int, D, 3>> m(arg); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([=] { [[maybe_unused]] std::layout_right::mapping<std::extents<int, D, 3>> m(arg); }()),
"extents construction: mismatch of provided arguments with static extents.");
}
// non-representability of extents itself
{
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_right::mapping<std::extents<signed char, D>> m(
+ [[maybe_unused]] std::layout_right::mapping<std::extents<signed char, D>> m(
std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
}()),
"extents ctor: arguments must be representable as index_type and nonnegative");
@@ -55,7 +55,7 @@ int main(int, char**) {
[[maybe_unused]] std::extents<signed char, D, 5> e(arg_exts);
// but the product is not, so we can't use it for layout_right
TEST_LIBCPP_ASSERT_FAILURE(
- ([=] { std::layout_right::mapping<std::extents<signed char, D, 5>> m(arg); }()),
+ ([=] { [[maybe_unused]] std::layout_right::mapping<std::extents<signed char, D, 5>> m(arg); }()),
"layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
}
return 0;
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.extents.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.extents.pass.cpp
index 52095691f6d24..33b71fdfd052d 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.extents.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.extents.pass.cpp
@@ -32,7 +32,8 @@ int main(int, char**) {
// the extents are representable but the product is not, so we can't use it for layout_right
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_right::mapping<std::extents<signed char, D, 5>> m(std::extents<signed char, D, 5>(100));
+ [[maybe_unused]] std::layout_right::mapping<std::extents<signed char, D, 5>> m(
+ std::extents<signed char, D, 5>(100));
}()),
"layout_right::mapping extents ctor: product of extents must be representable as index_type.");
}
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.layout_left.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.layout_left.pass.cpp
index 1757ddb286b9c..32972771f242d 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.layout_left.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.ctor.layout_left.pass.cpp
@@ -39,14 +39,14 @@ int main(int, char**) {
}
// mismatch of static extent
{
- TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_right::mapping<std::extents<int, 3>> m(arg); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([=] { [[maybe_unused]] std::layout_right::mapping<std::extents<int, 3>> m(arg); }()),
"extents construction: mismatch of provided arguments with static extents.");
}
// non-representability of extents itself
{
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_right::mapping<std::extents<signed char, D>> m(
+ [[maybe_unused]] std::layout_right::mapping<std::extents<signed char, D>> m(
std::layout_left::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
}()),
"extents ctor: arguments must be representable as index_type and nonnegative");
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp
index 7deb1215de0de..7b1739e0d1031 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp
@@ -58,14 +58,14 @@ int main(int, char**) {
{
std::extents<int, D, D> arg_exts{100, 5};
std::layout_stride::mapping<std::extents<int, D, D>> arg(arg_exts, std::array<int, 2>{1, 100});
- TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_stride::mapping<std::extents<int, D, 3>> m(arg); }()),
+ TEST_LIBCPP_ASSERT_FAILURE(([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<int, D, 3>> m(arg); }()),
"extents construction: mismatch of provided arguments with static extents.");
}
// non-representability of extents itself
{
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<signed char, D>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<signed char, D>> m(
std::layout_stride::mapping<std::extents<int, D>>(std::extents<int, D>(500), std::array<int, 1>{1}));
}()),
"extents ctor: arguments must be representable as index_type and nonnegative");
@@ -73,8 +73,9 @@ int main(int, char**) {
// all strides must be larger than zero
{
always_convertible_layout::mapping<std::dextents<int, 2>> offset_map(std::dextents<int, 2>{10, 10}, 100, -1);
- TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_stride::mapping<std::extents<signed char, D, D>> m(offset_map); }()),
- "layout_stride::mapping converting ctor: all strides must be greater than 0");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ ([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<signed char, D, D>> m(offset_map); }()),
+ "layout_stride::mapping converting ctor: all strides must be greater than 0");
}
// required_span_size not representable, while individual extents are
{
@@ -84,7 +85,7 @@ int main(int, char**) {
[[maybe_unused]] std::extents<signed char, D, 5> e(arg_exts);
// but the product is not, so we can't use it for layout_stride
TEST_LIBCPP_ASSERT_FAILURE(
- ([=] { std::layout_stride::mapping<std::extents<signed char, D, 5>> m(arg); }()),
+ ([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<signed char, D, 5>> m(arg); }()),
"layout_stride::mapping converting ctor: other.required_span_size() must be representable as index_type.");
}
// required_span_size not representable, while individual extents are, edge case
@@ -98,14 +99,15 @@ int main(int, char**) {
[[maybe_unused]] std::extents<signed char, D, 10> e(arg_exts);
// but the product is not, so we can't use it for layout_stride
TEST_LIBCPP_ASSERT_FAILURE(
- ([=] { std::layout_stride::mapping<std::extents<signed char, D, 10>> m(arg); }()),
+ ([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<signed char, D, 10>> m(arg); }()),
"layout_stride::mapping converting ctor: other.required_span_size() must be representable as index_type.");
}
// base offset must be 0 (i.e. mapping(0,...,0)==0) for a strided layout with positive strides
{
always_convertible_layout::mapping<std::dextents<int, 2>> offset_map(std::dextents<int, 2>{10, 10}, 3);
- TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_stride::mapping<std::extents<signed char, D, D>> m(offset_map); }()),
- "layout_stride::mapping converting ctor: base offset of mapping must be zero.");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ ([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<signed char, D, D>> m(offset_map); }()),
+ "layout_stride::mapping converting ctor: base offset of mapping must be zero.");
}
return 0;
}
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.non_unique.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.non_unique.pass.cpp
index 97a6d56e4f839..a6120f8bf9c4b 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.non_unique.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.non_unique.pass.cpp
@@ -42,7 +42,7 @@ int main(int, char**) {
{
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<unsigned, D, 5, 7>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned, D, 5, 7>> m(
std::extents<unsigned, D, 5, 7>(20), std::array<unsigned, 3>{4, 1, 200});
}()),
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
@@ -58,7 +58,7 @@ int main(int, char**) {
// will fail because neither of the equal strides is associated with an extent of 1
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<unsigned, D, 5, 2>> m3(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned, D, 5, 2>> m3(
std::extents<unsigned, D, 5, 2>(2), std::array<unsigned, 3>{5, 1, 5});
}()),
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.pass.cpp
index 860849ded2de2..9c52dd411b7c5 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_array.pass.cpp
@@ -42,7 +42,7 @@ int main(int, char**) {
// the extents are representable but the product with strides is not, so we can't use it for layout_stride
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<signed char, D, 5>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<signed char, D, 5>> m(
std::extents<signed char, D, 5>(20), std::array<int, 2>{20, 1});
}()),
"layout_stride::mapping ctor: required span size is not representable as index_type.");
@@ -51,7 +51,7 @@ int main(int, char**) {
static_assert(static_cast<unsigned char>(257u) == 1);
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<unsigned char, D, 5>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned char, D, 5>> m(
std::extents<unsigned char, D, 5>(20), std::array<unsigned, 2>{257, 1});
}()),
"layout_stride::mapping ctor: required span size is not representable as index_type.");
@@ -59,14 +59,14 @@ int main(int, char**) {
// negative strides are not allowed, check with unsigned index_type so we make sure we catch that
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<unsigned, D, 5>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned, D, 5>> m(
std::extents<unsigned, D, 5>(20), std::array<int, 2>{20, -1});
}()),
"layout_stride::mapping ctor: all strides must be greater than 0");
// zero strides are not allowed, check with unsigned index_type so we make sure we catch that
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<unsigned, D, 5>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned, D, 5>> m(
std::extents<unsigned, D, 5>(20), std::array<unsigned, 2>{20, 0});
}()),
"layout_stride::mapping ctor: all strides must be greater than 0");
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_span.non_unique.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_span.non_unique.pass.cpp
index fd0701e9ee3a7..4752d3946aece 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_span.non_unique.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.ctor.extents_span.non_unique.pass.cpp
@@ -43,7 +43,7 @@ int main(int, char**) {
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
std::array<unsigned, 3> strides{4, 1, 200};
- std::layout_stride::mapping<std::extents<unsigned, D, 5, 7>> m(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned, D, 5, 7>> m(
std::extents<unsigned, D, 5, 7>(20), std::span(strides));
}()),
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
@@ -61,7 +61,7 @@ int main(int, char**) {
// will fail because neither of the equal strides is associated with an extent of 1
TEST_LIBCPP_ASSERT_FAILURE(
([=] {
- std::layout_stride::mapping<std::extents<unsigned, D, 5, 2>> m3(
+ [[maybe_unused]] std::layout_stride::mapping<std::extents<unsigned, D, 5, 2>> m3(
std::extents<unsigned, D, 5, 2>(2), std::span(strides));
}()),
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
diff --git a/libcxx/test/libcxx/thread/thread.latch/assert.ctor.pass.cpp b/libcxx/test/libcxx/thread/thread.latch/assert.ctor.pass.cpp
index 5f1ea19d82a50..01fb907c3fbd4 100644
--- a/libcxx/test/libcxx/thread/thread.latch/assert.ctor.pass.cpp
+++ b/libcxx/test/libcxx/thread/thread.latch/assert.ctor.pass.cpp
@@ -24,11 +24,12 @@
#include "check_assertion.h"
-int main(int, char **) {
+int main(int, char**) {
{
- TEST_LIBCPP_ASSERT_FAILURE([]{ std::latch l(-1); }(),
- "latch::latch(ptrdiff_t): latch cannot be "
- "initialized with a negative value");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ [] { [[maybe_unused]] std::latch l(-1); }(),
+ "latch::latch(ptrdiff_t): latch cannot be "
+ "initialized with a negative value");
}
// We can't check the precondition for max() because there's no value
diff --git a/libcxx/test/libcxx/thread/thread.semaphore/assert.ctor.pass.cpp b/libcxx/test/libcxx/thread/thread.semaphore/assert.ctor.pass.cpp
index 1e33add779496..c490948d36abe 100644
--- a/libcxx/test/libcxx/thread/thread.semaphore/assert.ctor.pass.cpp
+++ b/libcxx/test/libcxx/thread/thread.semaphore/assert.ctor.pass.cpp
@@ -26,7 +26,7 @@
int main(int, char**) {
{
TEST_LIBCPP_ASSERT_FAILURE(
- [] { std::counting_semaphore<> s(-1); }(),
+ [] { [[maybe_unused]] std::counting_semaphore<> s(-1); }(),
"counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be "
"initialized with a negative value");
}
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp
index 73e6bf2846f0e..ee2370f5bce25 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp
index fdd9f79958f98..5d896c34e4ccd 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp
index d9ca1c80751cc..eb0ae4cf4b187 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp
index 3a2ff00088676..57b7f8d0f30a0 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp
index 65429345ae794..85ce6019fcd55 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/support/check_assertion.h b/libcxx/test/support/check_assertion.h
index 7f8102d82970d..d77c0bdb3615e 100644
--- a/libcxx/test/support/check_assertion.h
+++ b/libcxx/test/support/check_assertion.h
@@ -44,10 +44,18 @@ static constexpr const char* Marker = "###";
using MatchResult = std::pair<bool, std::string>;
using Matcher = std::function<MatchResult(const std::string& /*text*/)>;
-MatchResult MatchAssertionMessage(const std::string& text, std::string_view expected_message) {
+// Using the marker makes matching more precise, but we cannot output the marker when the `observe` semantic is used
+// (because it doesn't allow customizing the logging function). If the marker is not available, fall back to using less
+// precise matching by just the error message.
+MatchResult MatchAssertionMessage(const std::string& text, std::string_view expected_message, bool use_marker) {
// Extract information from the error message. This has to stay synchronized with how we format assertions in the
// library.
- std::regex assertion_format(".*###\\n(.*):(\\d+): assertion (.*) failed: (.*)\\n###");
+ std::string assertion_format_string = [&] {
+ if (use_marker)
+ return (".*###\\n(.*):(\\d+): assertion (.*) failed: (.*)\\n###");
+ return ("(.*):(\\d+): assertion (.*) failed: (.*)\\n");
+ }();
+ std::regex assertion_format(assertion_format_string);
std::smatch match_result;
// If a non-terminating assertion semantic is used, more than one assertion might be triggered before the process
@@ -57,6 +65,7 @@ MatchResult MatchAssertionMessage(const std::string& text, std::string_view expe
std::stringstream matching_error;
matching_error //
<< "Failed to parse the assertion message.\n" //
+ << "Using marker: " << use_marker << "\n" //
<< "Expected message: '" << expected_message.data() << "'\n" //
<< "Stderr contents: '" << text.c_str() << "'\n";
return MatchResult(/*success=*/false, matching_error.str());
@@ -80,9 +89,9 @@ MatchResult MatchAssertionMessage(const std::string& text, std::string_view expe
return MatchResult(/*success=*/true, /*maybe_error=*/"");
}
-Matcher MakeAssertionMessageMatcher(std::string_view assertion_message) {
+Matcher MakeAssertionMessageMatcher(std::string_view assertion_message, bool use_marker = true) {
return [=](const std::string& text) { //
- return MatchAssertionMessage(text, assertion_message);
+ return MatchAssertionMessage(text, assertion_message, use_marker);
};
}
@@ -389,12 +398,6 @@ class DeathTest {
};
#ifdef _LIBCPP_VERSION
-void std::__libcpp_log_hardening_failure(const char* message) noexcept {
- std::fprintf(stderr, "%s\n", Marker);
- std::fprintf(stderr, "%s", message);
- std::fprintf(stderr, "%s\n", Marker);
-}
-
void std::__libcpp_verbose_abort(char const* format, ...) noexcept {
va_list args;
va_start(args, format);
@@ -479,7 +482,7 @@ bool ExpectLog(const char* stmt, Func&& func) {
assert(( ExpectDeath(DeathCause::Trap, #expr, [&]() { (void)(expr); }) ))
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
- assert(( ExpectLog(#expr, [&]() { (void)(expr); }, MakeAssertionMessageMatcher(message)) ))
+ assert(( ExpectLog(#expr, [&]() { (void)(expr); }, MakeAssertionMessageMatcher(message, /*use_marker=*/false)) ))
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \
assert(( ExpectLog(#expr, [&]() { (void)(expr); }) ))
diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in
index d1ddedf1bb31b..e113a1b82cdd2 100644
--- a/libcxx/vendor/llvm/default_assertion_handler.in
+++ b/libcxx/vendor/llvm/default_assertion_handler.in
@@ -29,7 +29,7 @@
# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
-# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_ERROR(_LogErrorReason::_HardeningFailure, message)
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_ERROR(::std::_LogErrorReason::_HardeningFailure, message)
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
>From 0993a0822e8fe60b1822eeab4ac67e0467a70bde Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 19:18:26 -0700
Subject: [PATCH 09/20] [libc++] Add missing unsupported attributes to
hardening timezone tests.
Before this patch, these tests fail under `extensive` and `debug`
hardening modes.
---
.../time.zone.exception.ambig/assert.ctor.pass.cpp | 2 ++
.../time.zone.exception.nonexist/assert.ctor.pass.cpp | 2 ++
.../time.zone.members/assert.to_local.pass.cpp | 1 +
.../time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp | 2 ++
.../time.zone.members/assert.to_sys_choose.pass.cpp | 2 ++
5 files changed, 9 insertions(+)
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp
index 73e6bf2846f0e..ee2370f5bce25 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.ambig/assert.ctor.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp
index fdd9f79958f98..5d896c34e4ccd 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.exception/time.zone.exception.nonexist/assert.ctor.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp
index d9ca1c80751cc..eb0ae4cf4b187 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_local.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp
index 3a2ff00088676..57b7f8d0f30a0 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp
index 65429345ae794..85ce6019fcd55 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/assert.to_sys_choose.pass.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// REQUIRES: has-unix-headers
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
// <chrono>
>From cfbf82e9f04f5898510d8fe4e3f655e486b4c620 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 19:31:43 -0700
Subject: [PATCH 10/20] Regenerate the symbol list for Linux.
---
...wn-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 8c55c4385f6f6..53cda0be90ca9 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -225,6 +225,7 @@
{'is_defined': True, 'name': '_ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__115error_condition7messageEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'}
@@ -592,6 +593,7 @@
{'is_defined': True, 'name': '_ZNSt3__110to_wstringEx', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__110to_wstringEy', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__111__log_errorENS_15_LogErrorReasonEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'}
@@ -773,6 +775,7 @@
{'is_defined': True, 'name': '_ZNSt3__112system_errorD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112system_errorD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112system_errorD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'}
@@ -953,7 +956,6 @@
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
@@ -1156,7 +1158,6 @@
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117iostream_categoryEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'}
>From 1e38d401f858e898073d8c16416f6d9af1399793 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 19:40:02 -0700
Subject: [PATCH 11/20] Always log to `stderr` before making any system calls
(which might not succeed).
---
libcxx/src/log_error.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/src/log_error.cpp b/libcxx/src/log_error.cpp
index 53cf3c7aa7ac2..4e695ff380e8e 100644
--- a/libcxx/src/log_error.cpp
+++ b/libcxx/src/log_error.cpp
@@ -24,6 +24,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace {
void log_security_failure(const char* message) noexcept {
+ // Always log the message to `stderr` in case the platform-specific system calls fail.
+ fprintf(stderr, "%s", message);
+
// On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
os_fault_with_payload(
@@ -42,9 +45,6 @@ void log_security_failure(const char* message) noexcept {
openlog("libc++", 0, 0);
syslog(LOG_CRIT, "%s", message);
closelog();
-
-#else
- fprintf(stderr, "%s", message);
#endif
}
>From 78ff152aa8bf58421f10d51318175a27d9257ac2 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 19:57:21 -0700
Subject: [PATCH 12/20] More symbol list updates.
---
...ux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
...erpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
...pc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index 4b6f3548ce495..6211fa7e181ee 100644
--- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -170,6 +170,7 @@
{'is_defined': True, 'name': '_ZNKSt6__ndk115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk115error_condition7messageEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt6__ndk117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'}
@@ -580,6 +581,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk110to_wstringEx', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk110to_wstringEy', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk111__log_errorENS_15_LogErrorReasonEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'}
@@ -761,6 +763,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk112system_errorD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk112system_errorD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk112system_errorD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk113__hash_memoryEPKvj', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'}
@@ -941,7 +944,6 @@
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt6__ndk113__hash_memoryEPKvj', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
@@ -1144,7 +1146,6 @@
{'is_defined': True, 'name': '_ZNSt6__ndk117bad_function_callD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117bad_function_callD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117bad_function_callD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt6__ndk117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117iostream_categoryEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 2b85596bd87f6..b788ad3631211 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -96,6 +96,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__115__codecvt_utf16IwLb1EE6do_outERPcPKwS5_RS5_S2_S2_S3_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__115__codecvt_utf16IwLb1EE9do_lengthERPcPKcS5_m', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__115error_condition7messageEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__118__time_get_storageIcE15__do_date_orderEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__118__time_get_storageIwE15__do_date_orderEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__119__shared_weak_count13__get_deleterERKSt9type_info', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -311,6 +312,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__110to_wstringEx', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__110to_wstringEy', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111__call_onceERVmPvPFvS2_E', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111__log_errorENS_15_LogErrorReasonEPKc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111regex_errorC1ENS_15regex_constants10error_typeE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111regex_errorC2ENS_15regex_constants10error_typeE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111regex_errorD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -410,6 +412,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__112system_errorD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__112system_errorD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__112system_errorD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113random_deviceC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113random_deviceC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113random_deviceD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -418,7 +421,6 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
-{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -503,7 +505,6 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117bad_function_callD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117bad_function_callD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117bad_function_callD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
-{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117iostream_categoryEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 6ebdab96ed455..7b75b803bd30f 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -96,6 +96,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__115__codecvt_utf16IwLb1EE6do_outERPcPKwS5_RS5_S2_S2_S3_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__115__codecvt_utf16IwLb1EE9do_lengthERPcPKcS5_m', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__115error_condition7messageEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__118__time_get_storageIcE15__do_date_orderEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__118__time_get_storageIwE15__do_date_orderEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__119__shared_weak_count13__get_deleterERKSt9type_info', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -311,6 +312,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__110to_wstringEx', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__110to_wstringEy', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111__call_onceERVmPvPFvS2_E', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111__log_errorENS_15_LogErrorReasonEPKc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111regex_errorC1ENS_15regex_constants10error_typeE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111regex_errorC2ENS_15regex_constants10error_typeE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__111regex_errorD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -410,6 +412,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__112system_errorD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__112system_errorD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__112system_errorD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113random_deviceC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113random_deviceC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113random_deviceD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -418,7 +421,6 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
-{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -503,7 +505,6 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117bad_function_callD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117bad_function_callD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117bad_function_callD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
-{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117iostream_categoryEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
>From 0da96f3bbe1b3b136d246129f792cdb5967cbe27 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 19:58:46 -0700
Subject: [PATCH 13/20] More symbol list updates.
---
...ux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index 45f3d7c5904e8..bf59b2d57d854 100644
--- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -170,6 +170,7 @@
{'is_defined': True, 'name': '_ZNKSt6__ndk115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk115error_condition7messageEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt6__ndk117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt6__ndk117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'}
@@ -580,6 +581,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk110to_wstringEx', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk110to_wstringEy', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk111__log_errorENS_15_LogErrorReasonEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'}
@@ -761,6 +763,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk112system_errorD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk112system_errorD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk112system_errorD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'}
@@ -941,7 +944,6 @@
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt6__ndk113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
@@ -1144,7 +1146,6 @@
{'is_defined': True, 'name': '_ZNSt6__ndk117bad_function_callD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117bad_function_callD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117bad_function_callD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt6__ndk117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117iostream_categoryEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'}
>From f7325150084f4792e782c9c7a2c40b195a5fc40c Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 20:05:34 -0700
Subject: [PATCH 14/20] Undo accidental diff
---
libcxxabi/src/CMakeLists.txt | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/libcxxabi/src/CMakeLists.txt b/libcxxabi/src/CMakeLists.txt
index 0a6fc892a4f69..0675577aed6a1 100644
--- a/libcxxabi/src/CMakeLists.txt
+++ b/libcxxabi/src/CMakeLists.txt
@@ -172,11 +172,12 @@ if (LIBCXXABI_USE_LLVM_UNWINDER)
target_link_libraries(cxxabi_shared_objects PUBLIC unwind_shared)
endif()
endif()
-target_link_libraries(cxxabi_shared_objects PRIVATE cxx-headers ${LIBCXXABI_LIBRARIES})
+target_link_libraries(cxxabi_shared_objects
+ PUBLIC cxxabi-headers
+ PRIVATE cxx-headers runtimes-libc-headers ${LIBCXXABI_LIBRARIES})
if (NOT CXX_SUPPORTS_NOSTDLIBXX_FLAG)
target_link_libraries(cxxabi_shared_objects PRIVATE ${LIBCXXABI_BUILTINS_LIBRARY})
endif()
-target_link_libraries(cxxabi_shared_objects PUBLIC cxxabi-headers)
set_target_properties(cxxabi_shared_objects
PROPERTIES
CXX_EXTENSIONS OFF
@@ -215,7 +216,7 @@ if (ZOS)
endif ()
target_link_libraries(cxxabi_shared
- PUBLIC cxxabi_shared_objects
+ PUBLIC cxxabi_shared_objects runtimes-libc-shared
PRIVATE ${LIBCXXABI_LIBRARIES})
if (LIBCXXABI_ENABLE_SHARED)
@@ -274,8 +275,9 @@ if (LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC
target_link_libraries(cxxabi_static_objects PUBLIC unwind_static_objects) # propagate usage requirements
target_sources(cxxabi_static_objects PUBLIC $<TARGET_OBJECTS:unwind_static_objects>)
endif()
-target_link_libraries(cxxabi_static_objects PRIVATE cxx-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
-target_link_libraries(cxxabi_static_objects PUBLIC cxxabi-headers)
+target_link_libraries(cxxabi_static_objects
+ PUBLIC cxxabi-headers
+ PRIVATE cxx-headers runtimes-libc-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
set_target_properties(cxxabi_static_objects
PROPERTIES
CXX_EXTENSIONS OFF
@@ -311,7 +313,7 @@ endif()
add_library(cxxabi_static STATIC)
if (LIBCXXABI_USE_LLVM_UNWINDER AND NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
- target_link_libraries(cxxabi_static PUBLIC unwind_static)
+ target_link_libraries(cxxabi_static PUBLIC unwind_static runtimes-libc-static)
endif()
set_target_properties(cxxabi_static
PROPERTIES
>From 19b04b6e6a71ce2fa1cd4e60cff992268aca8418 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 20:14:08 -0700
Subject: [PATCH 15/20] clang-format
---
.../extents/assert.ctor_from_array.pass.cpp | 21 ++++++-------------
.../layout_stride/assert.conversion.pass.cpp | 5 +++--
libcxx/test/support/check_assertion.h | 2 +-
libcxxabi/src/demangle/DemangleConfig.h | 19 ++++++++++-------
4 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp
index 6849b6a5f2e6c..1c9829837ae62 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp
@@ -43,27 +43,18 @@ int main(int, char**) {
}
// mismatch of static extent
{
- TEST_LIBCPP_ASSERT_FAILURE(
- ([] {
- [[maybe_unused]] std::extents<int, D, 5> e1(std::array{1000, 3});
- }()),
- "extents construction: mismatch of provided arguments with static extents.");
+ TEST_LIBCPP_ASSERT_FAILURE(([] { [[maybe_unused]] std::extents<int, D, 5> e1(std::array{1000, 3}); }()),
+ "extents construction: mismatch of provided arguments with static extents.");
}
// value out of range
{
- TEST_LIBCPP_ASSERT_FAILURE(
- ([] {
- [[maybe_unused]] std::extents<signed char, D, 5> e1(std::array{1000, 5});
- }()),
- "extents ctor: arguments must be representable as index_type and nonnegative");
+ TEST_LIBCPP_ASSERT_FAILURE(([] { [[maybe_unused]] std::extents<signed char, D, 5> e1(std::array{1000, 5}); }()),
+ "extents ctor: arguments must be representable as index_type and nonnegative");
}
// negative value
{
- TEST_LIBCPP_ASSERT_FAILURE(
- ([] {
- [[maybe_unused]] std::extents<signed char, D, 5> e1(std::array{-1, 5});
- }()),
- "extents ctor: arguments must be representable as index_type and nonnegative");
+ TEST_LIBCPP_ASSERT_FAILURE(([] { [[maybe_unused]] std::extents<signed char, D, 5> e1(std::array{-1, 5}); }()),
+ "extents ctor: arguments must be representable as index_type and nonnegative");
}
return 0;
}
diff --git a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp
index 7b1739e0d1031..354db1d3cc3cc 100644
--- a/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/mdspan/layout_stride/assert.conversion.pass.cpp
@@ -58,8 +58,9 @@ int main(int, char**) {
{
std::extents<int, D, D> arg_exts{100, 5};
std::layout_stride::mapping<std::extents<int, D, D>> arg(arg_exts, std::array<int, 2>{1, 100});
- TEST_LIBCPP_ASSERT_FAILURE(([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<int, D, 3>> m(arg); }()),
- "extents construction: mismatch of provided arguments with static extents.");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ ([=] { [[maybe_unused]] std::layout_stride::mapping<std::extents<int, D, 3>> m(arg); }()),
+ "extents construction: mismatch of provided arguments with static extents.");
}
// non-representability of extents itself
{
diff --git a/libcxx/test/support/check_assertion.h b/libcxx/test/support/check_assertion.h
index d77c0bdb3615e..147c89c61901c 100644
--- a/libcxx/test/support/check_assertion.h
+++ b/libcxx/test/support/check_assertion.h
@@ -65,7 +65,7 @@ MatchResult MatchAssertionMessage(const std::string& text, std::string_view expe
std::stringstream matching_error;
matching_error //
<< "Failed to parse the assertion message.\n" //
- << "Using marker: " << use_marker << "\n" //
+ << "Using marker: " << use_marker << "\n" //
<< "Expected message: '" << expected_message.data() << "'\n" //
<< "Stderr contents: '" << text.c_str() << "'\n";
return MatchResult(/*success=*/false, matching_error.str());
diff --git a/libcxxabi/src/demangle/DemangleConfig.h b/libcxxabi/src/demangle/DemangleConfig.h
index f1f161a54afbd..fa3306cd4214b 100644
--- a/libcxxabi/src/demangle/DemangleConfig.h
+++ b/libcxxabi/src/demangle/DemangleConfig.h
@@ -20,9 +20,10 @@
#endif
#ifndef _LIBCPP_LOG_ERROR
-// Libc++abi does not have any functionality to log and continue, so we drop error messages when we build the demangler
-// with `observe` assertion semantic. Once the layering with libc++ is improved, this could use the libc++ functionality
-// to log hardening failures.
+// Libc++abi does not have any functionality to log and continue, so we drop
+// error messages when we build the demangler with `observe` assertion semantic.
+// Once the layering with libc++ is improved, this could use the libc++
+// functionality to log hardening failures.
#define _LIBCPP_LOG_ERROR(reason, message) ((void)0)
#endif
@@ -53,11 +54,11 @@
#ifndef DEMANGLE_GNUC_PREREQ
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
+#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
((maj) << 20) + ((min) << 10) + (patch))
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
-#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
+#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
#else
#define DEMANGLE_GNUC_PREREQ(maj, min, patch) 0
@@ -111,7 +112,11 @@
#define DEMANGLE_ASSERT(__expr, __msg) assert((__expr) && (__msg))
#endif
-#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {
-#define DEMANGLE_NAMESPACE_END } }
+#define DEMANGLE_NAMESPACE_BEGIN \
+ namespace { \
+ namespace itanium_demangle {
+#define DEMANGLE_NAMESPACE_END \
+ } \
+ }
#endif // LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H
>From c930bbf7a12d11e8d622a0674cb4865e7bd29b87 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 21:05:55 -0700
Subject: [PATCH 16/20] More symbol list updates.
---
...-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 51caa07a74330..c3d89695f9430 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -196,6 +196,7 @@
{'is_defined': True, 'name': '_ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__115error_condition7messageEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'}
@@ -563,6 +564,7 @@
{'is_defined': True, 'name': '_ZNSt3__110to_wstringEx', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__110to_wstringEy', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__111__log_errorENS_15_LogErrorReasonEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'}
@@ -744,6 +746,7 @@
{'is_defined': True, 'name': '_ZNSt3__112system_errorD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112system_errorD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112system_errorD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'}
@@ -923,7 +926,6 @@
{'is_defined': True, 'name': '_ZNSt3__113random_deviceclEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
@@ -1127,7 +1129,6 @@
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117iostream_categoryEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'}
>From 03da891faf2ece00c67892ac234861a6d007719f Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sun, 13 Jul 2025 02:53:33 -0700
Subject: [PATCH 17/20] Even more updates to the symbol list.
---
...nown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index de8cf6deef1df..c11a964372443 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -227,6 +227,7 @@
{'is_defined': True, 'name': '_ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__115error_condition7messageEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'}
@@ -594,6 +595,7 @@
{'is_defined': True, 'name': '_ZNSt3__110to_wstringEx', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__110to_wstringEy', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__111__log_errorENS_15_LogErrorReasonEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'}
@@ -775,6 +777,7 @@
{'is_defined': True, 'name': '_ZNSt3__112system_errorD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112system_errorD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112system_errorD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'}
@@ -955,7 +958,6 @@
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
@@ -1158,7 +1160,6 @@
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117bad_function_callD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt3__117bad_function_call4whatEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117iostream_categoryEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'}
>From f4aa0c1ae5bc4fde2cb39d865c1c04ee34fb8b47 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sun, 13 Jul 2025 14:35:11 -0700
Subject: [PATCH 18/20] Keep the old implementation of the default assertion
handler for the sake of the frozen C++03 mode.
---
.../vendor/llvm/default_assertion_handler.in | 36 +++++++++++++------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in
index e113a1b82cdd2..d0f0d7de19363 100644
--- a/libcxx/vendor/llvm/default_assertion_handler.in
+++ b/libcxx/vendor/llvm/default_assertion_handler.in
@@ -25,26 +25,40 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
-# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+// Keep the old implementation that doesn't support assertion semantics for backward compatibility with the frozen C++03
+// mode.
+# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
+# else
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
+# endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
-#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
-# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_ERROR(::std::_LogErrorReason::_HardeningFailure, message)
+#else
-#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
-# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
+# if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
-#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
-# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
+# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_ERROR(::std::_LogErrorReason::_HardeningFailure, message)
-#else
+# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
-# error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \
+# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
+# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
+
+# else
+
+# error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \
_LIBCPP_ASSERTION_SEMANTIC_IGNORE, \
_LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \
_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \
_LIBCPP_ASSERTION_SEMANTIC_ENFORCE
-#endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+# endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
#endif // _LIBCPP___ASSERTION_HANDLER
>From 4fb42b2fb730079cec89e54d6e0226561551d83c Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sun, 13 Jul 2025 15:39:35 -0700
Subject: [PATCH 19/20] Add documentation and release notes.
---
libcxx/docs/Hardening.rst | 60 +++++++++++++++++++++++++++++++++
libcxx/docs/ReleaseNotes/21.rst | 5 +++
2 files changed, 65 insertions(+)
diff --git a/libcxx/docs/Hardening.rst b/libcxx/docs/Hardening.rst
index 17808841bd9ec..41c688fd32fcc 100644
--- a/libcxx/docs/Hardening.rst
+++ b/libcxx/docs/Hardening.rst
@@ -39,6 +39,8 @@ modes are:
Enabling hardening has no impact on the ABI.
+.. _notes-for-users:
+
Notes for users
---------------
@@ -72,6 +74,10 @@ to control the level by passing **one** of the following options to the compiler
pre-built components. Most libc++ code is header-based, so a user-provided
value for ``_LIBCPP_HARDENING_MODE`` will be mostly respected.
+In some cases, users might want to override the default assertion semantic.
+This can be done similarly to setting the hardening mode; please refer to the
+:ref:`relevant section <assertion-semantics>`.
+
Notes for vendors
-----------------
@@ -260,6 +266,60 @@ output. This is less secure and increases the size of the binary (among other
things, it has to store the error message strings) but makes the failure easier
to debug. It also allows testing the error messages in our test suite.
+This default behavior can be customized by users via :ref:`assertion semantics
+<assertion-semantics>`; it can also be completely overridden by vendors by
+providing a :ref:`custom assertion failure handler
+<override-assertion-handler>`.
+
+.. _assertion-semantics:
+
+Assertion semantics
+-------------------
+
+What happens when an assertion fails depends on the assertion semantic being
+used. Four assertion semantics are available, based on C++26 Contracts
+evaluation semantics:
+
+- ``ignore`` evaluates the assertion but has no effect if it fails (note that it
+ differs from the Contracts ``ignore`` semantic which would not evaluate
+ the assertion at all);
+- ``observe`` logs an error (indicating, if possible on the platform, that the
+ error is fatal) but continues execution;
+- ``quick-enforce`` terminates the program as fast as possible via a trap
+ instruction. It is the default semantic for the production modes (``fast`` and
+ ``extensive``);
+- ``enforce`` logs an error and then terminates the program. It is the default
+ semantic for the ``debug`` mode.
+
+Notes:
+
+- Continuing execution after a hardening check fails results in undefined
+ behavior; the ``observe`` semantic is meant to make adopting hardening easier
+ but should not be used outside of the adoption period;
+- C++26 wording for Library Hardening precludes a conforming Hardened
+ implementation from using the Contracts ``ignore`` semantic when evaluating
+ hardened preconditions in the Library. Libc++ allows using this semantic for
+ hardened preconditions, but please be aware that using ``ignore`` does not
+ produce a conforming "Hardened" implementation, unlike the other semantics
+ above.
+
+The default assertion semantics are as follows:
+
+- ``fast``: ``quick-enforce``;
+- ``extensive``: ``quick-enforce``;
+- ``debug``: ``enforce``.
+
+The default assertion semantics can be overridden by passing **one** of the
+following options to the compiler:
+
+- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_IGNORE``
+- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_OBSERVE``
+- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE``
+- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE``
+
+All the :ref:`same notes <notes-for-users>` apply to setting this macro as for
+setting ``_LIBCPP_HARDENING_MODE``.
+
.. _override-assertion-handler:
Overriding the assertion failure handler
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 3d70fa38d971e..c26ada9b9ed94 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -87,6 +87,11 @@ Improvements and New Features
- ``ctype::tolower`` and ``ctype::toupper`` have been optimized, resulting in a 2x performane improvement.
+- Hardening now supports assertion semantics that allow customizing how a hardening assertion failure is handled. The
+ four available semantics, modeled on C++26 Contracts, are ``ignore``, ``observe``, ``quick-enforce`` and ``enforce``.
+ The ``observe`` semantic is intended to make it easier to adopt Hardening in production but should not be used outside
+ of this scenario. Please refer to the :ref:`Hardening documentation <hardening>` for details.
+
Deprecations and Removals
-------------------------
>From ba3053d8934d4cd66a3370f38c51115a12b609a9 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sun, 13 Jul 2025 16:17:05 -0700
Subject: [PATCH 20/20] Fix test
---
libcxx/test/support/test.support/test_check_assertion.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/support/test.support/test_check_assertion.pass.cpp b/libcxx/test/support/test.support/test_check_assertion.pass.cpp
index 4dfc5319aaf97..540cb01e3594a 100644
--- a/libcxx/test/support/test.support/test_check_assertion.pass.cpp
+++ b/libcxx/test/support/test.support/test_check_assertion.pass.cpp
@@ -53,7 +53,7 @@ bool TestDeathTest(
}
if (!maybe_failure_description.empty()) {
- test_case.PrintFailureDetails(maybe_failure_description, stmt, test_result.cause());
+ test_case.PrintFailureDetails("EXPECT_DEATH", maybe_failure_description, stmt, test_result.cause());
return false;
}
More information about the libcxx-commits
mailing list