diff options
Diffstat (limited to 'libcxx/include/__config')
| -rw-r--r-- | libcxx/include/__config | 585 |
1 files changed, 304 insertions, 281 deletions
diff --git a/libcxx/include/__config b/libcxx/include/__config index 9759d3b9e8e0..7f66042f9025 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -12,12 +12,6 @@ #include <__config_site> -#if defined(_MSC_VER) && !defined(__clang__) -# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -# endif -#endif - #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header #endif @@ -31,24 +25,37 @@ # define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) #elif defined(__GNUC__) # define _LIBCPP_COMPILER_GCC +# define _LIBCPP_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) #endif #ifdef __cplusplus +// Warn if a compiler version is used that is not supported anymore +// LLVM RELEASE Update the minimum compiler versions +# if defined(_LIBCPP_CLANG_VER) +# if _LIBCPP_CLANG_VER < 1600 +# warning "Libc++ only supports Clang 16 and later" +# endif +# elif defined(_LIBCPP_APPLE_CLANG_VER) +# if _LIBCPP_APPLE_CLANG_VER < 1500 +# warning "Libc++ only supports AppleClang 15 and later" +# endif +# elif defined(_LIBCPP_GCC_VER) +# if _LIBCPP_GCC_VER < 1300 +# warning "Libc++ only supports GCC 13 and later" +# endif +# endif + // The attributes supported by clang are documented at https://clang.llvm.org/docs/AttributeReference.html // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. // Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is // defined to XXYYZZ. -# define _LIBCPP_VERSION 170000 +# define _LIBCPP_VERSION 180000 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) -// Valid C++ identifier that revs with every libc++ version. This can be used to -// generate identifiers that must be unique for every released libc++ version. -# define _LIBCPP_VERSIONED_IDENTIFIER _LIBCPP_CONCAT(v, _LIBCPP_VERSION) - # if __STDC_HOSTED__ == 0 # define _LIBCPP_FREESTANDING # endif @@ -156,6 +163,11 @@ // The implementation moved to the header, but we still export the symbols from // the dylib for backwards compatibility. # define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 +// Save memory by providing the allocator more freedom to allocate the most +// efficient size class by dropping the alignment requirements for std::string's +// pointer from 16 to 8. This changes the output of std::string::max_size, +// which makes it ABI breaking +# define _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT # elif _LIBCPP_ABI_VERSION == 1 # if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) // Enable compiling copies of now inline methods into the dylib to support @@ -170,7 +182,7 @@ # endif // Feature macros for disabling pre ABI v1 features. All of these options // are deprecated. -# if defined(__FreeBSD__) +# if defined(__FreeBSD__) && __FreeBSD__ < 14 # define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR # endif // For XCOFF linkers, we have problems if we see a weak hidden version of a symbol @@ -182,11 +194,6 @@ # endif # if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2 -// Enable additional explicit instantiations of iostreams components. This -// reduces the number of weak definitions generated in programs that use -// iostreams by providing a single strong definition in the shared library. -# define _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 - // Define a key function for `bad_function_call` in the library, to centralize // its vtable and typeinfo to libc++ rather than having all other libraries // using that class define their own copies. @@ -208,30 +215,39 @@ // HARDENING { -// TODO(hardening): remove this in LLVM 18. +// TODO(hardening): deprecate this in LLVM 19. // This is for backward compatibility -- make enabling `_LIBCPP_ENABLE_ASSERTIONS` (which predates hardening modes) -// equivalent to setting the hardened mode. +// equivalent to setting the extensive mode. # ifdef _LIBCPP_ENABLE_ASSERTIONS -# warning "_LIBCPP_ENABLE_ASSERTIONS is deprecated, please use _LIBCPP_ENABLE_HARDENED_MODE instead." # if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 # error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" # endif # if _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ENABLE_HARDENED_MODE 1 +# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_EXTENSIVE # endif # endif -// Enables the hardened mode which consists of all checks intended to be used in production. Hardened mode prioritizes -// security-critical checks that can be done with relatively little overhead in constant time. Mutually exclusive with -// `_LIBCPP_ENABLE_DEBUG_MODE`. +// The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values: // -// #define _LIBCPP_ENABLE_HARDENED_MODE 1 - -// Enables the debug mode which contains all the checks from the hardened mode and additionally more expensive checks -// that may affect the complexity of algorithms. The debug mode is intended to be used for testing, not in production. -// Mutually exclusive with `_LIBCPP_ENABLE_HARDENED_MODE`. +// - `_LIBCPP_HARDENING_MODE_NONE`; +// - `_LIBCPP_HARDENING_MODE_FAST`; +// - `_LIBCPP_HARDENING_MODE_EXTENSIVE`; +// - `_LIBCPP_HARDENING_MODE_DEBUG`. // -// #define _LIBCPP_ENABLE_DEBUG_MODE 1 +// These values have the following effects: +// +// - `_LIBCPP_HARDENING_MODE_NONE` -- sets the hardening mode to "none" which disables all runtime hardening checks; +// +// - `_LIBCPP_HARDENING_MODE_FAST` -- sets that hardening mode to "fast". The fast mode enables security-critical checks +// that can be done with relatively little runtime overhead in constant time; +// +// - `_LIBCPP_HARDENING_MODE_EXTENSIVE` -- sets the hardening mode to "extensive". The extensive mode is a superset of +// the fast mode that additionally enables checks that are relatively cheap and prevent common types of logic errors +// but are not necessarily security-critical; +// +// - `_LIBCPP_HARDENING_MODE_DEBUG` -- sets the hardening mode to "debug". The debug mode is a superset of the extensive +// mode and enables all checks available in the library, including internal assertions. Checks that are part of the +// debug mode can be very expensive and thus the debug mode is intended to be used for testing, not in production. // Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These // macros are only for internal use -- users should only pick one of the high-level hardening modes described above. @@ -246,6 +262,11 @@ // a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like // `optional` and `function` are considered one-element containers for the purposes of this check. // +// - `_LIBCPP_ASSERT_NON_NULL` -- checks that the pointer being dereferenced is not null. On most modern platforms zero +// address does not refer to an actual location in memory, so a null pointer dereference would not compromize the +// memory security of a program (however, it is still undefined behavior that can result in strange errors due to +// compiler optimizations). +// // - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the // given ranges do not overlap. // @@ -257,33 +278,39 @@ // // - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet. -# ifndef _LIBCPP_ENABLE_HARDENED_MODE -# define _LIBCPP_ENABLE_HARDENED_MODE _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT -# endif -# if _LIBCPP_ENABLE_HARDENED_MODE != 0 && _LIBCPP_ENABLE_HARDENED_MODE != 1 -# error "_LIBCPP_ENABLE_HARDENED_MODE must be set to 0 or 1." -# endif +// clang-format off +# define _LIBCPP_HARDENING_MODE_NONE (1 << 1) +# define _LIBCPP_HARDENING_MODE_FAST (1 << 2) +# define _LIBCPP_HARDENING_MODE_EXTENSIVE (1 << 4) // Deliberately not ordered. +# define _LIBCPP_HARDENING_MODE_DEBUG (1 << 3) +// clang-format on -# ifndef _LIBCPP_ENABLE_DEBUG_MODE -# define _LIBCPP_ENABLE_DEBUG_MODE _LIBCPP_ENABLE_DEBUG_MODE_DEFAULT -# endif -# if _LIBCPP_ENABLE_DEBUG_MODE != 0 && _LIBCPP_ENABLE_DEBUG_MODE != 1 -# error "_LIBCPP_ENABLE_DEBUG_MODE must be set to 0 or 1." +# ifndef _LIBCPP_HARDENING_MODE +# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT # endif -# if _LIBCPP_ENABLE_HARDENED_MODE && _LIBCPP_ENABLE_DEBUG_MODE -# error "Only one of _LIBCPP_ENABLE_HARDENED_MODE and _LIBCPP_ENABLE_DEBUG_MODE can be enabled." +# 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 -// Hardened mode checks. - // clang-format off -# if _LIBCPP_ENABLE_HARDENED_MODE +// Fast hardening mode checks. + +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST // Enabled checks. # define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) # define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) // Disabled checks. +// On most modern platforms, dereferencing a null pointer does not lead to an actual memory access. +# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSUME(expression) // Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security // vulnerability. # define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression) @@ -291,13 +318,28 @@ # define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) # define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression) -// Debug mode checks. +// Extensive hardening mode checks. + +# elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE + +// Enabled checks. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message) +// Disabled checks. +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) + +// Debug hardening mode checks. -# elif _LIBCPP_ENABLE_DEBUG_MODE +# elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG // All checks enabled. # define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) # define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSERT(expression, message) # define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSERT(expression, message) # define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSERT(expression, message) # define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSERT(expression, message) @@ -310,12 +352,13 @@ // All checks disabled. # define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSUME(expression) # define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSUME(expression) # define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression) # define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression) # define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) # define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression) -# endif // _LIBCPP_ENABLE_HARDENED_MODE +# endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST // clang-format on // } HARDENING @@ -405,10 +448,9 @@ // easier to grep for target specific flags once the feature is complete. # if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) # define _LIBCPP_HAS_NO_INCOMPLETE_PSTL -# endif - -# if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) # define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN +# define _LIBCPP_HAS_NO_INCOMPLETE_TZDB +# define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM # endif // Need to detect which libc we're using if we're on Linux. @@ -425,48 +467,19 @@ # include <features.h> // for __NATIVE_ASCII_F # endif -# ifdef __LITTLE_ENDIAN__ -# if __LITTLE_ENDIAN__ -# define _LIBCPP_LITTLE_ENDIAN -# endif // __LITTLE_ENDIAN__ -# endif // __LITTLE_ENDIAN__ - -# ifdef __BIG_ENDIAN__ -# if __BIG_ENDIAN__ -# define _LIBCPP_BIG_ENDIAN -# endif // __BIG_ENDIAN__ -# endif // __BIG_ENDIAN__ - -# ifdef __BYTE_ORDER__ -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define _LIBCPP_LITTLE_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define _LIBCPP_BIG_ENDIAN -# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# endif // __BYTE_ORDER__ - -# ifdef __FreeBSD__ -# include <osreldate.h> -# include <sys/endian.h> -# if _BYTE_ORDER == _LITTLE_ENDIAN -# define _LIBCPP_LITTLE_ENDIAN -# else // _BYTE_ORDER == _LITTLE_ENDIAN -# define _LIBCPP_BIG_ENDIAN -# endif // _BYTE_ORDER == _LITTLE_ENDIAN -# endif // __FreeBSD__ +# ifndef __BYTE_ORDER__ +# error \ + "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform" +# endif -# if defined(__NetBSD__) || defined(__OpenBSD__) -# include <sys/endian.h> -# if _BYTE_ORDER == _LITTLE_ENDIAN -# define _LIBCPP_LITTLE_ENDIAN -# else // _BYTE_ORDER == _LITTLE_ENDIAN -# define _LIBCPP_BIG_ENDIAN -# endif // _BYTE_ORDER == _LITTLE_ENDIAN -# endif // defined(__NetBSD__) || defined(__OpenBSD__) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define _LIBCPP_LITTLE_ENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define _LIBCPP_BIG_ENDIAN +# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # if defined(_WIN32) # define _LIBCPP_WIN32API -# define _LIBCPP_LITTLE_ENDIAN # define _LIBCPP_SHORT_WCHAR 1 // Both MinGW and native MSVC provide a "MSVC"-like environment # define _LIBCPP_MSVCRT_LIKE @@ -539,23 +552,6 @@ # define _LIBCPP_USING_DEV_RANDOM # endif -# if !defined(_LIBCPP_LITTLE_ENDIAN) && !defined(_LIBCPP_BIG_ENDIAN) -# include <endian.h> -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define _LIBCPP_LITTLE_ENDIAN -# elif __BYTE_ORDER == __BIG_ENDIAN -# define _LIBCPP_BIG_ENDIAN -# else // __BYTE_ORDER == __BIG_ENDIAN -# error unable to determine endian -# endif -# endif // !defined(_LIBCPP_LITTLE_ENDIAN) && !defined(_LIBCPP_BIG_ENDIAN) - -# if __has_attribute(__no_sanitize__) && !defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) -# else -# define _LIBCPP_NO_CFI -# endif - # ifndef _LIBCPP_CXX03_LANG # define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp) @@ -627,11 +623,6 @@ typedef __char32_t char32_t; # define _LIBCPP_HAS_NO_ASAN # endif -// Allow for build-time disabling of unsigned integer sanitization -# if __has_attribute(no_sanitize) -# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) -# endif - # define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) # define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ @@ -685,7 +676,7 @@ typedef __char32_t char32_t; # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # define _LIBCPP_TEMPLATE_VIS # define _LIBCPP_TEMPLATE_DATA_VIS -# define _LIBCPP_ENUM_VIS +# define _LIBCPP_TYPE_VISIBILITY_DEFAULT # else @@ -713,20 +704,17 @@ typedef __char32_t char32_t; # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # endif -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -# if __has_attribute(__type_visibility__) -# define _LIBCPP_TEMPLATE_VIS __attribute__((__type_visibility__("default"))) -# else -# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default"))) -# endif +// GCC doesn't support the type_visibility attribute, so we have to keep the visibility attribute on templates +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && !__has_attribute(__type_visibility__) +# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default"))) # else # define _LIBCPP_TEMPLATE_VIS # endif # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__) -# define _LIBCPP_ENUM_VIS __attribute__((__type_visibility__("default"))) +# define _LIBCPP_TYPE_VISIBILITY_DEFAULT __attribute__((__type_visibility__("default"))) # else -# define _LIBCPP_ENUM_VIS +# define _LIBCPP_TYPE_VISIBILITY_DEFAULT # endif # endif // defined(_LIBCPP_OBJECT_FORMAT_COFF) @@ -740,22 +728,54 @@ typedef __char32_t char32_t; # define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE # endif +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST +# define _LIBCPP_HARDENING_SIG f +# elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE +# define _LIBCPP_HARDENING_SIG s +# elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +# define _LIBCPP_HARDENING_SIG d +# else +# define _LIBCPP_HARDENING_SIG n // "none" +# endif + +# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# define _LIBCPP_EXCEPTIONS_SIG n +# else +# define _LIBCPP_EXCEPTIONS_SIG e +# endif + +# define _LIBCPP_ODR_SIGNATURE \ + _LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_EXCEPTIONS_SIG), _LIBCPP_VERSION) + // This macro marks a symbol as being hidden from libc++'s ABI. This is achieved // on two levels: // 1. The symbol is given hidden visibility, which ensures that users won't start exporting // symbols from their dynamic library by means of using the libc++ headers. This ensures // that those symbols stay private to the dynamic library in which it is defined. // -// 2. The symbol is given an ABI tag that changes with each version of libc++. This ensures -// that no ODR violation can arise from mixing two TUs compiled with different versions -// of libc++ where we would have changed the definition of a symbol. If the symbols shared -// the same name, the ODR would require that their definitions be token-by-token equivalent, -// which basically prevents us from being able to make any change to any function in our -// headers. Using this ABI tag ensures that the symbol name is "bumped" artificially at -// each release, which lets us change the definition of these symbols at our leisure. -// Note that historically, this has been achieved in various ways, including force-inlining -// all functions or giving internal linkage to all functions. Both these (previous) solutions -// suffer from drawbacks that lead notably to code bloat. +// 2. The symbol is given an ABI tag that encodes the ODR-relevant properties of the library. +// This ensures that no ODR violation can arise from mixing two TUs compiled with different +// versions or configurations of libc++ (such as exceptions vs no-exceptions). Indeed, if the +// program contains two definitions of a function, the ODR requires them to be token-by-token +// equivalent, and the linker is allowed to pick either definition and discard the other one. +// +// For example, if a program contains a copy of `vector::at()` compiled with exceptions enabled +// *and* a copy of `vector::at()` compiled with exceptions disabled (by means of having two TUs +// compiled with different settings), the two definitions are both visible by the linker and they +// have the same name, but they have a meaningfully different implementation (one throws an exception +// and the other aborts the program). This violates the ODR and makes the program ill-formed, and in +// practice what will happen is that the linker will pick one of the definitions at random and will +// discard the other one. This can quite clearly lead to incorrect program behavior. +// +// A similar reasoning holds for many other properties that are ODR-affecting. Essentially any +// property that causes the code of a function to differ from the code in another configuration +// can be considered ODR-affecting. In practice, we don't encode all such properties in the ABI +// tag, but we encode the ones that we think are most important: library version, exceptions, and +// hardening mode. +// +// Note that historically, solving this problem has been achieved in various ways, including +// force-inlining all functions or giving internal linkage to all functions. Both these previous +// solutions suffer from drawbacks that lead notably to code bloat. // // Note that we use _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION to ensure that we don't depend // on _LIBCPP_HIDE_FROM_ABI methods of classes explicitly instantiated in the dynamic library. @@ -775,7 +795,7 @@ typedef __char32_t char32_t; # ifndef _LIBCPP_NO_ABI_TAG # define _LIBCPP_HIDE_FROM_ABI \ _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION \ - __attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_VERSIONED_IDENTIFIER)))) + __attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_ODR_SIGNATURE)))) # else # define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # endif @@ -795,30 +815,23 @@ typedef __char32_t char32_t; # define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI # endif -// Just so we can migrate to the new macros gradually. +// TODO(LLVM-19): Remove _LIBCPP_INLINE_VISIBILITY and _VSTD, which we're keeping around +// only to ease the renaming for downstreams. # define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI +# define _VSTD std // Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. // clang-format off -# define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_ABI_NAMESPACE { +# define _LIBCPP_BEGIN_NAMESPACE_STD namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \ + inline namespace _LIBCPP_ABI_NAMESPACE { # define _LIBCPP_END_NAMESPACE_STD }} -# define _VSTD std - -_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD -# if _LIBCPP_STD_VER >= 17 -# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ - _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { -# else -# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ - _LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem { -# endif +# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD \ + inline namespace __fs { namespace filesystem { # define _LIBCPP_END_NAMESPACE_FILESYSTEM _LIBCPP_END_NAMESPACE_STD }} // clang-format on -# define _VSTD_FS std::__fs::filesystem - # if __has_attribute(__enable_if__) # define _LIBCPP_PREFERRED_OVERLOAD __attribute__((__enable_if__(true, ""))) # endif @@ -827,18 +840,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_HAS_NO_INT128 # endif -# if __has_attribute(__malloc__) -# define _LIBCPP_NOALIAS __attribute__((__malloc__)) -# else -# define _LIBCPP_NOALIAS -# endif - -# if __has_attribute(__using_if_exists__) -# define _LIBCPP_USING_IF_EXISTS __attribute__((__using_if_exists__)) -# else -# define _LIBCPP_USING_IF_EXISTS -# endif - # ifdef _LIBCPP_CXX03_LANG # define _LIBCPP_DECLARE_STRONG_ENUM(x) \ struct _LIBCPP_EXPORTED_FROM_ABI x { \ @@ -846,14 +847,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // clang-format off # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ __lx __v_; \ - _LIBCPP_INLINE_VISIBILITY x(__lx __v) : __v_(__v) {} \ - _LIBCPP_INLINE_VISIBILITY explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ - _LIBCPP_INLINE_VISIBILITY operator int() const { return __v_; } \ + _LIBCPP_HIDE_FROM_ABI x(__lx __v) : __v_(__v) {} \ + _LIBCPP_HIDE_FROM_ABI explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ + _LIBCPP_HIDE_FROM_ABI operator int() const { return __v_; } \ }; // clang-format on # else // _LIBCPP_CXX03_LANG -# define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x +# define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class x # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) # endif // _LIBCPP_CXX03_LANG @@ -1008,44 +1009,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_CONSTEXPR_SINCE_CXX23 # endif -# if __has_cpp_attribute(nodiscard) -# define _LIBCPP_NODISCARD [[__nodiscard__]] -# else -// We can't use GCC's [[gnu::warn_unused_result]] and -// __attribute__((warn_unused_result)), because GCC does not silence them via -// (void) cast. -# define _LIBCPP_NODISCARD -# endif - -// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not -// specified as such as an extension. -# if !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_EXT -# endif - -# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_AFTER_CXX17 -# endif - -# if __has_attribute(__no_destroy__) -# define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) -# else -# define _LIBCPP_NO_DESTROY -# endif - # ifndef _LIBCPP_HAS_NO_ASAN extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); -# if _LIBCPP_CLANG_VER >= 1600 extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_double_ended_contiguous_container( const void*, const void*, const void*, const void*, const void*, const void*); extern "C" _LIBCPP_EXPORTED_FROM_ABI int __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); -# endif # endif // Try to find out if RTTI is disabled. @@ -1174,10 +1144,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # endif # endif -# ifndef _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK -# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK -# endif - # if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(__no_thread_safety_analysis__) # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((__no_thread_safety_analysis__)) # else @@ -1210,49 +1176,10 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_CONSTINIT # endif -# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) -# define _LIBCPP_DIAGNOSE_WARNING(...) __attribute__((__diagnose_if__(__VA_ARGS__, "warning"))) -# else -# define _LIBCPP_DIAGNOSE_WARNING(...) -# endif - -// Use a function like macro to imply that it must be followed by a semicolon -# if __has_cpp_attribute(fallthrough) -# define _LIBCPP_FALLTHROUGH() [[fallthrough]] -# elif __has_attribute(__fallthrough__) -# define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__)) -# else -# define _LIBCPP_FALLTHROUGH() ((void)0) -# endif - -# if __has_cpp_attribute(_Clang::__lifetimebound__) -# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] -# else -# define _LIBCPP_LIFETIMEBOUND -# endif - -# if __has_attribute(__nodebug__) -# define _LIBCPP_NODEBUG __attribute__((__nodebug__)) -# else -# define _LIBCPP_NODEBUG -# endif - -# if __has_attribute(__standalone_debug__) -# define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__)) -# else -# define _LIBCPP_STANDALONE_DEBUG -# endif - -# if __has_attribute(__preferred_name__) -# define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x))) -# else -# define _LIBCPP_PREFERRED_NAME(x) -# endif - -# if __has_attribute(__no_sanitize__) -# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__))) +# if __has_attribute(__noinline__) +# define _LIBCPP_NOINLINE __attribute__((__noinline__)) # else -# define _LIBCPP_NO_SANITIZE(...) +# define _LIBCPP_NOINLINE # endif // We often repeat things just for handling wide characters in the library. @@ -1265,12 +1192,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_IF_WIDE_CHARACTERS(...) __VA_ARGS__ # endif -# if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases) -# define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) -# else -# define _LIBCPP_DECLSPEC_EMPTY_BASES -# endif - # if defined(_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) # define _LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR # define _LIBCPP_ENABLE_CXX17_REMOVED_BINDERS @@ -1314,28 +1235,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_FOPEN_CLOEXEC_MODE # endif -// Support for _FILE_OFFSET_BITS=64 landed gradually in Android, so the full set -// of functions used in cstdio may not be available for low API levels when -// using 64-bit file offsets on LP32. -# if defined(__BIONIC__) && defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 24 -# define _LIBCPP_HAS_NO_FGETPOS_FSETPOS -# endif - -# if __has_attribute(__init_priority__) -# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100))) -# else -# define _LIBCPP_INIT_PRIORITY_MAX -# endif - -# if __has_attribute(__format__) -// The attribute uses 1-based indices for ordinary and static member functions. -// The attribute uses 2-based indices for non-static member functions. -# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \ - __attribute__((__format__(archetype, format_string_index, first_format_arg_index))) -# else -# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) /* nothing */ -# endif - # if __has_cpp_attribute(msvc::no_unique_address) // MSVC implements [[no_unique_address]] as a silent no-op currently. // (If/when MSVC breaks its C++ ABI, it will be changed to work as intended.) @@ -1375,20 +1274,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) # endif -# if defined(_AIX) && !defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_PACKED_BYTE_FOR_AIX _Pragma("pack(1)") -# define _LIBCPP_PACKED_BYTE_FOR_AIX_END _Pragma("pack(pop)") -# else -# define _LIBCPP_PACKED_BYTE_FOR_AIX /* empty */ -# define _LIBCPP_PACKED_BYTE_FOR_AIX_END /* empty */ -# endif - -# if __has_attribute(__packed__) -# define _LIBCPP_PACKED __attribute__((__packed__)) -# else -# define _LIBCPP_PACKED -# endif - // c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these // functions is gradually being added to existing C libraries. The conditions // below check for known C library versions and conditions under which these @@ -1453,6 +1338,16 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) \ _PSTL_PRAGMA(omp declare reduction(NAME:OP : omp_out(omp_in)) initializer(omp_priv = omp_orig)) +# elif defined(_LIBCPP_COMPILER_CLANG_BASED) + +# define _PSTL_PRAGMA_SIMD _Pragma("clang loop vectorize(enable) interleave(enable)") +# define _PSTL_PRAGMA_DECLARE_SIMD +# define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) _Pragma("clang loop vectorize(enable) interleave(enable)") +# define _PSTL_PRAGMA_SIMD_SCAN(PRM) _Pragma("clang loop vectorize(enable) interleave(enable)") +# define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) +# define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) +# define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) + # else // (defined(_OPENMP) && _OPENMP >= 201307) # define _PSTL_PRAGMA_SIMD @@ -1467,6 +1362,134 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED +// Optional attributes - these are useful for a better QoI, but not required to be available + +# if __has_attribute(__no_sanitize__) && !defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) +# else +# define _LIBCPP_NO_CFI +# endif + +# if __has_attribute(__malloc__) +# define _LIBCPP_NOALIAS __attribute__((__malloc__)) +# else +# define _LIBCPP_NOALIAS +# endif + +# if __has_attribute(__using_if_exists__) +# define _LIBCPP_USING_IF_EXISTS __attribute__((__using_if_exists__)) +# else +# define _LIBCPP_USING_IF_EXISTS +# endif + +# if __has_cpp_attribute(nodiscard) +# define _LIBCPP_NODISCARD [[__nodiscard__]] +# else +// We can't use GCC's [[gnu::warn_unused_result]] and +// __attribute__((warn_unused_result)), because GCC does not silence them via +// (void) cast. +# define _LIBCPP_NODISCARD +# endif + +// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not +// specified as such as an extension. +# if !defined(_LIBCPP_DISABLE_NODISCARD_EXT) +# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD +# else +# define _LIBCPP_NODISCARD_EXT +# endif + +# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) +# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD +# else +# define _LIBCPP_NODISCARD_AFTER_CXX17 +# endif + +# if __has_attribute(__no_destroy__) +# define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) +# else +# define _LIBCPP_NO_DESTROY +# endif + +# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) +# define _LIBCPP_DIAGNOSE_WARNING(...) __attribute__((__diagnose_if__(__VA_ARGS__, "warning"))) +# else +# define _LIBCPP_DIAGNOSE_WARNING(...) +# endif + +// Use a function like macro to imply that it must be followed by a semicolon +# if __has_cpp_attribute(fallthrough) +# define _LIBCPP_FALLTHROUGH() [[fallthrough]] +# elif __has_attribute(__fallthrough__) +# define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__)) +# else +# define _LIBCPP_FALLTHROUGH() ((void)0) +# endif + +# if __has_cpp_attribute(_Clang::__lifetimebound__) +# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] +# else +# define _LIBCPP_LIFETIMEBOUND +# endif + +# if __has_attribute(__nodebug__) +# define _LIBCPP_NODEBUG __attribute__((__nodebug__)) +# else +# define _LIBCPP_NODEBUG +# endif + +# if __has_attribute(__standalone_debug__) +# define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__)) +# else +# define _LIBCPP_STANDALONE_DEBUG +# endif + +# if __has_attribute(__preferred_name__) +# define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x))) +# else +# define _LIBCPP_PREFERRED_NAME(x) +# endif + +# if __has_attribute(__no_sanitize__) +# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__))) +# else +# define _LIBCPP_NO_SANITIZE(...) +# endif + +# if __has_attribute(__init_priority__) +# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100))) +# else +# define _LIBCPP_INIT_PRIORITY_MAX +# endif + +# if __has_attribute(__format__) +// The attribute uses 1-based indices for ordinary and static member functions. +// The attribute uses 2-based indices for non-static member functions. +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \ + __attribute__((__format__(archetype, format_string_index, first_format_arg_index))) +# else +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) /* nothing */ +# endif + +# if __has_attribute(__packed__) +# define _LIBCPP_PACKED __attribute__((__packed__)) +# else +# define _LIBCPP_PACKED +# endif + +# if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases) +# define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) +# else +# define _LIBCPP_DECLSPEC_EMPTY_BASES +# endif + +// Allow for build-time disabling of unsigned integer sanitization +# if __has_attribute(no_sanitize) && !defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) +# else +# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +# endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG |
