Skip to content

Commit b0f8174

Browse files
committed
Make hardening_dependent a special value for choosing the assertion
semantic (rather than relying on it being not set).
1 parent 5208926 commit b0f8174

File tree

2 files changed

+45
-31
lines changed

2 files changed

+45
-31
lines changed

libcxx/CMakeLists.txt

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,16 @@ if (NOT "${LIBCXX_HARDENING_MODE}" IN_LIST LIBCXX_SUPPORTED_HARDENING_MODES)
6666
message(FATAL_ERROR
6767
"Unsupported hardening mode: '${LIBCXX_HARDENING_MODE}'. Supported values are ${LIBCXX_SUPPORTED_HARDENING_MODES}.")
6868
endif()
69-
set(LIBCXX_SUPPORTED_ASSERTION_SEMANTICS ignore observe quick_enforce enforce)
70-
set(LIBCXX_ASSERTION_SEMANTIC "" CACHE STRING
69+
set(LIBCXX_SUPPORTED_ASSERTION_SEMANTICS hardening_dependent ignore observe quick_enforce enforce)
70+
set(LIBCXX_ASSERTION_SEMANTIC "hardening_dependent" CACHE STRING
7171
"Specify the default assertion semantic to use. This semantic will be used
7272
inside the compiled library and will be the default when compiling user code.
73-
If not defined, the library will select the assertion semantic based on the hardening
74-
mode in effect. Note that users can override this setting in their own code.
75-
This does not affect the ABI. Supported values are
76-
${LIBCXX_SUPPORTED_ASSERTION_SEMANTICS}.")
73+
Note that users can override this setting in their own code. This does not
74+
affect the ABI. Supported values are ${LIBCXX_SUPPORTED_ASSERTION_SEMANTICS}.
75+
`hardening_dependent` is a special value that instructs the library to select
76+
the assertion semantic based on the hardening mode in effect.")
7777

78-
if (NOT "${LIBCXX_ASSERTION_SEMANTIC}" STREQUAL "" AND NOT "${LIBCXX_ASSERTION_SEMANTIC}" IN_LIST LIBCXX_SUPPORTED_ASSERTION_SEMANTICS)
78+
if (NOT "${LIBCXX_ASSERTION_SEMANTIC}" IN_LIST LIBCXX_SUPPORTED_ASSERTION_SEMANTICS)
7979
message(FATAL_ERROR
8080
"Unsupported assertion semantic: '${LIBCXX_ASSERTION_SEMANTIC}'. Supported values are ${LIBCXX_SUPPORTED_ASSERTION_SEMANTICS}.")
8181
endif()
@@ -776,14 +776,16 @@ elseif (LIBCXX_HARDENING_MODE STREQUAL "extensive")
776776
elseif (LIBCXX_HARDENING_MODE STREQUAL "debug")
777777
config_define(8 _LIBCPP_HARDENING_MODE_DEFAULT)
778778
endif()
779-
if (LIBCXX_ASSERTION_SEMANTIC STREQUAL "ignore")
779+
if (LIBCXX_ASSERTION_SEMANTIC STREQUAL "hardening_dependent")
780780
config_define(2 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
781-
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "observe")
781+
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "ignore")
782782
config_define(4 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
783-
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "quick_enforce")
783+
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "observe")
784784
config_define(8 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
785-
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "enforce")
785+
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "quick_enforce")
786786
config_define(16 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
787+
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "enforce")
788+
config_define(32 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
787789
endif()
788790

789791
if (LIBCXX_PSTL_BACKEND STREQUAL "serial")

libcxx/include/__configuration/hardening.h

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)