@@ -135,13 +135,25 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \
135135_LIBCPP_HARDENING_MODE_DEBUG
136136#endif
137137
138- // Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts:
138+ // The library provides the macro `_LIBCPP_ASSERTION_SEMANTIC` for configuring the assertion semantic used by hardening;
139+ // it can be set to one of the following values:
140+ //
141+ // - `_LIBCPP_ASSERTION_SEMANTIC_IGNORE`;
142+ // - `_LIBCPP_ASSERTION_SEMANTIC_OBSERVE`;
143+ // - `_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE`;
144+ // - `_LIBCPP_ASSERTION_SEMANTIC_ENFORCE`.
145+ //
146+ // libc++ assertion semantics generally mirror the evaluation semantics of C++26 Contracts:
139147// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts
140148// `ignore` semantic which wouldn't evaluate the assertion at all);
141149// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution;
142150// - `quick-enforce` terminates the program as fast as possible (via trapping);
143151// - `enforce` logs an error and then terminates the program.
144152//
153+ // Additionally, a special `hardening-dependent` value selects the assertion semantic based on the hardening mode in
154+ // effect: the production-capable modes (`fast` and `extensive`) map to `quick_enforce` and the `debug` mode maps to
155+ // `enforce`.
156+ //
145157// Notes:
146158// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant
147159// to make adopting hardening easier but should not be used outside of this scenario;
@@ -150,42 +162,42 @@ _LIBCPP_HARDENING_MODE_DEBUG
150162// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened"
151163// implementation, unlike the other semantics above.
152164// clang-format off
153- # define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1 )
154- # define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2 )
155- # define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3 )
156- # define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4 )
165+ # define _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT (1 << 1 )
166+ # define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 2 )
167+ # define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 3 )
168+ # define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 4 )
169+ # define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 5 )
157170// clang-format on
158171
159- // If the user or the vendor attempt to configure the assertion semantic, check that it is allowed in the current
160- // environment.
161- #if defined(_LIBCPP_ASSERTION_SEMANTIC) || defined(_LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
172+ // If the user attempts to configure the assertion semantic, check that it is allowed in the current environment.
173+ #if defined(_LIBCPP_ASSERTION_SEMANTIC)
162174# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY
163175# error "Assertion semantics are an experimental feature."
164176# endif
165177# if defined(_LIBCPP_CXX03_LANG)
166178# error "Assertion semantics are not available in the C++03 mode."
167179# endif
168- #endif // defined(_LIBCPP_ASSERTION_SEMANTIC) || defined(_LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
180+ #endif // defined(_LIBCPP_ASSERTION_SEMANTIC)
169181
170- // There are 2 ways to configure the assertion semantic, listed in order of precedence:
171- // 1. The ` _LIBCPP_ASSERTION_SEMANTIC` macro, defined directly by the user.
172- // 2. The `LIBCXX_ASSERTION_SEMANTIC` CMake variable, set by the vendor.
173- // If neither `_LIBCPP_ASSERTION_SEMANTIC` nor `LIBCXX_ASSERTION_SEMANTIC` are defined, the default mapping is used
174- // which determines the semantic based on the hardening mode in effect: production-capable modes map to `quick-enforce`
175- // (i.e., trap) and the `debug` mode maps to `enforce` (i.e., log and abort) .
176- #ifndef _LIBCPP_ASSERTION_SEMANTIC // User-provided semantic takes top priority -- don't override if set.
182+ // User-provided semantic takes top priority -- don't override if set.
183+ # ifndef _LIBCPP_ASSERTION_SEMANTIC
184+
185+ # ifndef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT
186+ # error _LIBCPP_ASSERTION_SEMANTIC_DEFAULT is not defined. This definition should be set at configuration time in \
187+ the `__config_site` header, please make sure your installation of libc++ is not broken .
188+ # endif
177189
178- # ifdef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT // Vendor-provided semantic takes second priority.
190+ # if _LIBCPP_ASSERTION_SEMANTIC_DEFAULT != _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT
179191# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_DEFAULT
180- # else // Fallback: use the default mapping.
192+ # else
181193# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
182194# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
183195# else
184196# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
185197# endif
186- # endif // ifdef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT
198+ # endif // _LIBCPP_ASSERTION_SEMANTIC_DEFAULT != _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT
187199
188- #endif // _LIBCPP_ASSERTION_SEMANTIC
200+ #endif // #ifndef _LIBCPP_ASSERTION_SEMANTIC
189201
190202// Finally, validate the selected semantic (in case the user tries setting it to an incorrect value):
191203#if _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_IGNORE && \
0 commit comments