Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions libcxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ if (NOT "${LIBCXX_HARDENING_MODE}" IN_LIST LIBCXX_SUPPORTED_HARDENING_MODES)
message(FATAL_ERROR
"Unsupported hardening mode: '${LIBCXX_HARDENING_MODE}'. Supported values are ${LIBCXX_SUPPORTED_HARDENING_MODES}.")
endif()
set(LIBCXX_SUPPORTED_ASSERTION_SEMANTICS ignore observe quick_enforce enforce)
set(LIBCXX_ASSERTION_SEMANTIC "" CACHE STRING
"Specify the default assertion semantic to use. This semantic will be used
inside the compiled library and will be the default when compiling user code.
If not defined, the library will select the assertion semantic based on the hardening
mode in effect. Note that users can override this setting in their own code.
This does not affect the ABI. Supported values are
${LIBCXX_SUPPORTED_ASSERTION_SEMANTICS}.")

if (NOT "${LIBCXX_ASSERTION_SEMANTIC}" STREQUAL "" AND NOT "${LIBCXX_ASSERTION_SEMANTIC}" IN_LIST LIBCXX_SUPPORTED_ASSERTION_SEMANTICS)
message(FATAL_ERROR
"Unsupported assertion semantic: '${LIBCXX_ASSERTION_SEMANTIC}'. Supported values are ${LIBCXX_SUPPORTED_ASSERTION_SEMANTICS}.")
endif()
set(LIBCXX_ASSERTION_HANDLER_FILE
"vendor/llvm/default_assertion_handler.in"
CACHE STRING
Expand Down Expand Up @@ -763,6 +776,15 @@ elseif (LIBCXX_HARDENING_MODE STREQUAL "extensive")
elseif (LIBCXX_HARDENING_MODE STREQUAL "debug")
config_define(8 _LIBCPP_HARDENING_MODE_DEFAULT)
endif()
if (LIBCXX_ASSERTION_SEMANTIC STREQUAL "ignore")
config_define(2 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "observe")
config_define(4 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "quick_enforce")
config_define(8 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
elseif (LIBCXX_ASSERTION_SEMANTIC STREQUAL "enforce")
config_define(16 _LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
endif()

if (LIBCXX_PSTL_BACKEND STREQUAL "serial")
config_define(1 _LIBCPP_PSTL_BACKEND_SERIAL)
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/__config_site.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

// Hardening.
#cmakedefine _LIBCPP_HARDENING_MODE_DEFAULT @_LIBCPP_HARDENING_MODE_DEFAULT@
#cmakedefine _LIBCPP_ASSERTION_SEMANTIC_DEFAULT @_LIBCPP_ASSERTION_SEMANTIC_DEFAULT@

// __USE_MINGW_ANSI_STDIO gets redefined on MinGW
#ifdef __clang__
Expand Down
47 changes: 34 additions & 13 deletions libcxx/include/__configuration/hardening.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,47 @@ _LIBCPP_HARDENING_MODE_DEBUG
# 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

#else

// If the user or the vendor attempt to configure the assertion semantic, check that it is allowed in the current
// environment.
#if defined(_LIBCPP_ASSERTION_SEMANTIC) || defined(_LIBCPP_ASSERTION_SEMANTIC_DEFAULT)
# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# error "Assertion semantics are an experimental feature."
# endif
# if defined(_LIBCPP_CXX03_LANG)
# error "Assertion semantics are not available in the C++03 mode."
# endif
#endif // defined(_LIBCPP_ASSERTION_SEMANTIC) || defined(_LIBCPP_ASSERTION_SEMANTIC_DEFAULT)

// There are 2 ways to configure the assertion semantic, listed in order of precedence:
// 1. The `_LIBCPP_ASSERTION_SEMANTIC` macro, defined directly by the user.
// 2. The `LIBCXX_ASSERTION_SEMANTIC` CMake variable, set by the vendor.
// If neither `_LIBCPP_ASSERTION_SEMANTIC` nor `LIBCXX_ASSERTION_SEMANTIC` are defined, the default mapping is used
// which determines the semantic based on the hardening mode in effect: production-capable modes map to `quick-enforce`
// (i.e., trap) and the `debug` mode maps to `enforce` (i.e., log and abort).
#ifndef _LIBCPP_ASSERTION_SEMANTIC // User-provided semantic takes top priority -- don't override if set.

# ifdef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT // Vendor-provided semantic takes second priority.
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_DEFAULT
# else // Fallback: use the default mapping.
# 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 // ifdef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT

#endif // _LIBCPP_ASSERTION_SEMANTIC

// Finally, validate the selected semantic (in case the user tries setting it to an incorrect value):
#if _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_IGNORE && \
_LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_OBSERVE && \
_LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE && \
_LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# 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

#endif // _LIBCPP___CONFIGURATION_HARDENING_H
Loading