- Notifications
You must be signed in to change notification settings - Fork14.5k
[libc++][hardening] Introduce assertion semantics#148268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
[libc++][hardening] Introduce assertion semantics#148268
Uh oh!
There was an error while loading.Please reload this page.
Conversation
github-actionsbot commentedJul 11, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
✅ With the latest revision this PR passed the C/C++ code formatter. |
llvmbot commentedJul 13, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@llvm/pr-subscribers-github-workflow @llvm/pr-subscribers-libcxx Author: Konstantin Varlamov (var-const) Changes
Patch is 78.09 KiB, truncated to 20.00 KiB below, full version:https://github.com/llvm/llvm-project/pull/148268.diff 38 Files Affected:
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txtindex c8e6d28584623..7052716bbb6f0 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_error __math/abs.h __math/copysign.h __math/error_functions.h@@ -944,6 +945,7 @@ set(files __vector/vector_bool.h __vector/vector_bool_formatter.h __verbose_abort+ __verbose_trap algorithm any array@@ -1569,6 +1571,7 @@ set(files __cxx03/__utility/unreachable.h __cxx03/__variant/monostate.h __cxx03/__verbose_abort+ __cxx03/__verbose_trap __cxx03/algorithm __cxx03/array __cxx03/atomicdiff --git a/libcxx/include/__config b/libcxx/include/__configindex d940461c30234..ef0c8b48b658b 100644--- a/libcxx/include/__config+++ b/libcxx/include/__config@@ -147,6 +147,40 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \ _LIBCPP_HARDENING_MODE_DEBUG # endif+// 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;+// - 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)+# 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) #xdiff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.hindex ae58e36b508b4..5de0b98ba22a9 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 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/__cxx03/__verbose_trap b/libcxx/include/__cxx03/__verbose_trapnew file mode 100644index 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_TRAPdiff --git a/libcxx/include/__log_error b/libcxx/include/__log_errornew file mode 100644index 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_ERRORdiff --git a/libcxx/include/__verbose_trap b/libcxx/include/__verbose_trapnew file mode 100644index 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_TRAPdiff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.inindex 45b9c72a05b82..8d29bded96169 100644--- a/libcxx/include/module.modulemap.in+++ b/libcxx/include/module.modulemap.in@@ -2353,9 +2353,15 @@ module std [system] { header "__std_mbstate_t.h" export * }+ module log_error {+ header "__log_error"+ } module verbose_abort { header "__verbose_abort" }+ module verbose_trap {+ header "__verbose_trap"+ } module internal_assert { header "__assert" export *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.abilistindex 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/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilistindex 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.abilistindex 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_cla...[truncated] |
#endif | ||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
# pragma GCC system_header | ||
#endif | ||
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This isn't very pretty, but I can't think of a better way, assuming we don't want to add new functionality to the frozen headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This looks reasonable to me.
ba3053d
to2ad957b
CompareUh oh!
There was an error while loading.Please reload this page.
.. _assertion-semantics: | ||
Assertion semantics |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
General comment: we need to mention (or at least plan for) what happens when C++26 Contracts are implemented. In particular, there will be a time when Clang and libc++ will implement Contracts and the Contracts runtime (class std::contract_violation
, etc). Furthermore, we'll want libc++ to be a valid C++26Hardened Implementation, which requires that hardening failures be treated as contract violations.
When that's the case, what should happen with_LIBCPP_ASSERTION_SEMANTIC
?
var-constJul 14, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think our design is constrained by the fact that we want to support hardening in older language modes where Contracts would not be available even when using a new compiler (after all, a major motivation for hardening is makingexisting code bases more secure). Support for theobserve
semantic is important for adopting hardening in production, so I think it would be a significant limitation if this semantic were only available for projects that can use very recent compiler versions. It makes having some form of assertion semantics unavoidable.
I also think it makes sense to have assertion semantics mimic the actual Contracts semantics -- it's simple(r) conceptually and might make migrating to Contracts easier. We could have e.g. a boolean flag ("observe"/"not observe") instead but I think it would be creating unnecessary differences without buying us much.
If this is the case, then we cannot escape the situation where libc++ assertion semantics and actual Contracts evaluation semantics "clash" and need to choose the best (in the sense of "lesser of several evils") alternative. Summarizing our offline discussion, I think when a user sets the assertion semantic in an environment where Contract semantics are available, we can:
- A. Make this an error.
- B. Allow the Contracts semantic to silently take precedence (effectively override) the assertion semantic.
- C. Do either A or B based on whether the assertion semantic matches the Contract semantic (if they match, setting the assertion semantic is a no-op, if they don't match, produce an error). While it's not impossible for a project to use different semantics based on the language mode, it seems very unlikely in practice.
(C) seems like the better option -- (A) would make it painful for projects to support more than one language mode, and (B) might allow silently downgrading the semantic to a non-terminating one, for example. IIUC, the evaluation semantic can be chosen at runtime, making it hard or impossible to catch mismatch, but these cases should be relatively rare, and I think (C) should generally cover this.
This also means that we would want to support assertion semantics long term, having support for Contracts doesn't automatically deprecate them.
libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cppShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
#endif | ||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
# pragma GCC system_header | ||
#endif | ||
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This looks reasonable to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This LGTM after rebasing ontomain
.
Assertion semantics closely mimic C++26 Contracts evaluation semantics.This brings our implementation closer in line with C++26 LibraryHardening (one particular benefit is that using the observe semanticmakes adopting hardening easier for projects).
17b5a0d
tof187236
Compare7345508
intollvm:mainUh oh!
There was an error while loading.Please reload this page.
… (#148822)Revertsllvm/llvm-project#148268It looks like this was based on #148266, which I reverted in #148787.
Uh oh!
There was an error while loading.Please reload this page.
Assertion semantics closely mimic C++26 Contracts evaluation semantics. This brings our implementation closer in line with C++26 Library Hardening (one particular benefit is that using the
observe
semantic makes adopting hardening easier for projects).