-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc++][hardening] Allow setting the assertion semantic via CMake. #167636
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++][hardening] Allow setting the assertion semantic via CMake. #167636
Conversation
Add a new CMake variable, `LIBCXX_ASSERTION_SEMANTIC`, that largely mirrors `LIBCXX_HARDENING_MODE`, except that not setting it is valid and results in the default mapping from the selected hardening mode: - `fast` and `extensive` map to `quick_enforce`; - `debug` maps to `enforce`. The default assertion semantic set via CMake takes precedence over the default mapping but can still be overridden by setting the `_LIBCPP_ASSERTION_SEMANTIC` macro directly.
|
@llvm/pr-subscribers-libcxx Author: Konstantin Varlamov (var-const) ChangesAdd a new CMake variable,
The default assertion semantic set via CMake takes precedence over the Full diff: https://github.com/llvm/llvm-project/pull/167636.diff 3 Files Affected:
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index a119850cd808e..ed577efc9dda8 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -66,6 +66,18 @@ 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 ("${LIBCXX_ASSERTION_SEMANTIC}" 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
@@ -763,6 +775,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)
diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in
index b68c0c8258366..6dcca1849a96c 100644
--- a/libcxx/include/__config_site.in
+++ b/libcxx/include/__config_site.in
@@ -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__
diff --git a/libcxx/include/__configuration/hardening.h b/libcxx/include/__configuration/hardening.h
index bc2a8d078fa77..591a66484d780 100644
--- a/libcxx/include/__configuration/hardening.h
+++ b/libcxx/include/__configuration/hardening.h
@@ -7,32 +7,32 @@
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___CONFIGURATION_HARDENING_H
-#define _LIBCPP___CONFIGURATION_HARDENING_H
+# define _LIBCPP___CONFIGURATION_HARDENING_H
-#include <__config_site>
-#include <__configuration/experimental.h>
-#include <__configuration/language.h>
+# include <__config_site>
+# include <__configuration/experimental.h>
+# include <__configuration/language.h>
-#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
-# pragma GCC system_header
-#endif
+# ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+# pragma GCC system_header
+# endif
// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated.
// Since hardening went through several changes (many of which impacted user-facing macros),
// we're keeping these checks around for a bit longer than usual. Failure to properly configure
// hardening results in checks being dropped silently, which is a pretty big deal.
-#if defined(_LIBCPP_ENABLE_ASSERTIONS)
-# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
-#endif
-#if defined(_LIBCPP_ENABLE_HARDENED_MODE)
-# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
-#endif
-#if defined(_LIBCPP_ENABLE_SAFE_MODE)
-# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
-#endif
-#if defined(_LIBCPP_ENABLE_DEBUG_MODE)
-# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
-#endif
+# if defined(_LIBCPP_ENABLE_ASSERTIONS)
+# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
+# endif
+# if defined(_LIBCPP_ENABLE_HARDENED_MODE)
+# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
+# endif
+# if defined(_LIBCPP_ENABLE_SAFE_MODE)
+# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
+# endif
+# if defined(_LIBCPP_ENABLE_DEBUG_MODE)
+# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
+# endif
// The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values:
//
@@ -115,25 +115,26 @@
# define _LIBCPP_HARDENING_MODE_DEBUG (1 << 3)
// clang-format on
-#ifndef _LIBCPP_HARDENING_MODE
+# ifndef _LIBCPP_HARDENING_MODE
-# ifndef _LIBCPP_HARDENING_MODE_DEFAULT
-# error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \
+# ifndef _LIBCPP_HARDENING_MODE_DEFAULT
+# error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \
`__config_site` header, please make sure your installation of libc++ is not broken.
-# endif
+# endif
-# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT
-#endif
+# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT
+# endif
-#if _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_NONE && _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_FAST && \
- _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \
- _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
-# error _LIBCPP_HARDENING_MODE must be set to one of the following values: \
+# if _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_NONE && \
+ _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_FAST && \
+ _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \
+ _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
+# error _LIBCPP_HARDENING_MODE must be set to one of the following values: \
_LIBCPP_HARDENING_MODE_NONE, \
_LIBCPP_HARDENING_MODE_FAST, \
_LIBCPP_HARDENING_MODE_EXTENSIVE, \
_LIBCPP_HARDENING_MODE_DEBUG
-#endif
+# 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
@@ -156,26 +157,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 !_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 // _LIBCPP_ASSERTION_SEMANTIC
-
-#endif // _LIBCPP___CONFIGURATION_HARDENING_H
+// 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
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
philnik777
left a comment
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.
Could you fix the formatting? Right now I have no idea what the actual change is.
Done. |
orthogonal to the selected hardening mode; - Tweak some checks in existing tests to rely on the assertion semantic rather than using the hardening mode as a proxy.
semantic (rather than relying on it being not set).
libcxx/test/libcxx/assertions/semantics/override_with_enforce_semantic.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/libcxx/assertions/semantics/assertion_semantic_incorrect_value.sh.cpp
Show resolved
Hide resolved
libcxx/test/libcxx/assertions/semantics/assertion_semantic_incorrect_value.sh.cpp
Outdated
Show resolved
Hide resolved
- Address other feedback.
ldionne
left a comment
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.
LGTM with comments applied and CI passing!
libcxx/test/extensions/libcxx/odr_signature.assertion_semantics.sh.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/extensions/libcxx/odr_signature.assertion_semantics.sh.cpp
Outdated
Show resolved
Hide resolved
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/17342 Here is the relevant piece of the build log for the reference |
Add a new CMake variable,
LIBCXX_ASSERTION_SEMANTIC, that largelymirrors
LIBCXX_HARDENING_MODE, except that it also supports aspecial value
hardening_dependentthat indicates the semantic will beselected based on the hardening mode in effect:
fastandextensivemap toquick_enforce;debugmaps toenforce.