Pointer field protection has the following characteristics: - Pointer fields in RTTI types are unsigned. Signing these fields is unnecessary because PFP is a mechanism for protecting the heap, and the RTTI objects typically live in global variables. Therefore, mark the fields with the no_field_protection to inhibit PFP for these fields. - libcxx's interim trivial relocatability implementation, which memcpy's some non-trivially-copyable objects according to the value of a trait, conflicts with PFP in tagged mode (in which the address of the pointer is used as part of the pointer encoding) by causing such copies to result in a crash in some cases where the object being copied includes a pointer field. These copies are undefined behavior. Therefore, make libcxx's trivially relocatable predicate simply return the value of the trivially copyable trait when PFP in tagged mode is enabled, which results in standards compliant behavior that is accommodated by PFP. Reviewers: philnik777, fmayer, ldionne Pull Request: https://github.com/llvm/llvm-project/pull/151651
467 lines
18 KiB
C++
467 lines
18 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___CONFIGURATION_ATTRIBUTES_H
|
|
#define _LIBCPP___CONFIGURATION_ATTRIBUTES_H
|
|
|
|
#include <__config_site>
|
|
#include <__configuration/hardening.h>
|
|
#include <__configuration/language.h>
|
|
|
|
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
|
# pragma GCC system_header
|
|
#endif
|
|
|
|
#ifndef __has_declspec_attribute
|
|
# define __has_declspec_attribute(__x) 0
|
|
#endif
|
|
|
|
// Attributes relevant for layout ABI
|
|
// ----------------------------------
|
|
|
|
#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.)
|
|
// However, MSVC implements [[msvc::no_unique_address]] which does what
|
|
// [[no_unique_address]] is supposed to do, in general.
|
|
# define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
|
|
#else
|
|
# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
|
|
#endif
|
|
|
|
#define _LIBCPP_PACKED __attribute__((__packed__))
|
|
|
|
// Attributes affecting overload resolution
|
|
// ----------------------------------------
|
|
|
|
#if __has_attribute(__enable_if__)
|
|
# define _LIBCPP_PREFERRED_OVERLOAD __attribute__((__enable_if__(true, "")))
|
|
#endif
|
|
|
|
// Visibility attributes
|
|
// ---------------------
|
|
|
|
#if defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
|
|
|
# ifdef _DLL
|
|
# define _LIBCPP_CRT_FUNC __declspec(dllimport)
|
|
# else
|
|
# define _LIBCPP_CRT_FUNC
|
|
# endif
|
|
|
|
# if defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCPP_BUILDING_LIBRARY))
|
|
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
|
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
|
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
|
|
# define _LIBCPP_EXPORTED_FROM_ABI
|
|
# elif defined(_LIBCPP_BUILDING_LIBRARY)
|
|
# if defined(__MINGW32__)
|
|
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllexport)
|
|
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
|
# else
|
|
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
|
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __declspec(dllexport)
|
|
# endif
|
|
# define _LIBCPP_OVERRIDABLE_FUNC_VIS __declspec(dllexport)
|
|
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport)
|
|
# else
|
|
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllimport)
|
|
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
|
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
|
|
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport)
|
|
# endif
|
|
|
|
# define _LIBCPP_HIDDEN
|
|
# define _LIBCPP_TEMPLATE_DATA_VIS
|
|
# define _LIBCPP_NAMESPACE_VISIBILITY
|
|
|
|
#else
|
|
|
|
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
|
# define _LIBCPP_VISIBILITY(vis) __attribute__((__visibility__(vis)))
|
|
# else
|
|
# define _LIBCPP_VISIBILITY(vis)
|
|
# endif
|
|
|
|
# define _LIBCPP_HIDDEN _LIBCPP_VISIBILITY("hidden")
|
|
# define _LIBCPP_TEMPLATE_DATA_VIS _LIBCPP_VISIBILITY("default")
|
|
# define _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_VISIBILITY("default")
|
|
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_VISIBILITY("default")
|
|
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
|
|
|
// TODO: Make this a proper customization point or remove the option to override it.
|
|
# ifndef _LIBCPP_OVERRIDABLE_FUNC_VIS
|
|
# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default")
|
|
# endif
|
|
|
|
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__)
|
|
# define _LIBCPP_NAMESPACE_VISIBILITY __attribute__((__type_visibility__("default")))
|
|
# elif !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
|
# define _LIBCPP_NAMESPACE_VISIBILITY __attribute__((__visibility__("default")))
|
|
# else
|
|
# define _LIBCPP_NAMESPACE_VISIBILITY
|
|
# endif
|
|
|
|
#endif // defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
|
|
|
// hide_from_abi
|
|
// -------------
|
|
|
|
#define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__))
|
|
|
|
#if __has_attribute(exclude_from_explicit_instantiation)
|
|
# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((__exclude_from_explicit_instantiation__))
|
|
#else
|
|
// Try to approximate the effect of exclude_from_explicit_instantiation
|
|
// (which is that entities are not assumed to be provided by explicit
|
|
// template instantiations in the dylib) by always inlining those entities.
|
|
# 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
|
|
|
|
#if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
|
|
# define _LIBCPP_ASSERTION_SEMANTIC_SIG o
|
|
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
|
|
# define _LIBCPP_ASSERTION_SEMANTIC_SIG q
|
|
#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
|
|
# define _LIBCPP_ASSERTION_SEMANTIC_SIG e
|
|
#else
|
|
# define _LIBCPP_ASSERTION_SEMANTIC_SIG i // `ignore`
|
|
#endif
|
|
|
|
#if !_LIBCPP_HAS_EXCEPTIONS
|
|
# define _LIBCPP_EXCEPTIONS_SIG n
|
|
#else
|
|
# define _LIBCPP_EXCEPTIONS_SIG e
|
|
#endif
|
|
|
|
#define _LIBCPP_ODR_SIGNATURE \
|
|
_LIBCPP_CONCAT( \
|
|
_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_ASSERTION_SEMANTIC_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 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.
|
|
//
|
|
// Also note that the _LIBCPP_HIDE_FROM_ABI_VIRTUAL macro should be used on virtual functions
|
|
// instead of _LIBCPP_HIDE_FROM_ABI. That macro does not use an ABI tag. Indeed, the mangled
|
|
// name of a virtual function is part of its ABI, since some architectures like arm64e can sign
|
|
// the virtual function pointer in the vtable based on the mangled name of the function. Since
|
|
// we use an ABI tag that changes with each released version, the mangled name of the virtual
|
|
// function would change, which is incorrect. Note that it doesn't make much sense to change
|
|
// the implementation of a virtual function in an ABI-incompatible way in the first place,
|
|
// since that would be an ABI break anyway. Hence, the lack of ABI tag should not be noticeable.
|
|
//
|
|
// The macro can be applied to record and enum types. When the tagged type is nested in
|
|
// a record this "parent" record needs to have the macro too. Another use case for applying
|
|
// this macro to records and unions is to apply an ABI tag to inline constexpr variables.
|
|
// This can be useful for inline variables that are implementation details which are expected
|
|
// to change in the future.
|
|
//
|
|
// TODO: We provide a escape hatch with _LIBCPP_NO_ABI_TAG for folks who want to avoid increasing
|
|
// the length of symbols with an ABI tag. In practice, we should remove the escape hatch and
|
|
// use compression mangling instead, see https://github.com/itanium-cxx-abi/cxx-abi/issues/70.
|
|
#ifndef _LIBCPP_NO_ABI_TAG
|
|
# define _LIBCPP_HIDE_FROM_ABI \
|
|
_LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION \
|
|
__attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_ODR_SIGNATURE))))
|
|
#else
|
|
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
|
|
#endif
|
|
#define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
|
|
|
|
// Optional attributes
|
|
// -------------------
|
|
|
|
// these are useful for a better QoI, but not required to be available
|
|
|
|
#define _LIBCPP_NOALIAS __attribute__((__malloc__))
|
|
#define _LIBCPP_NODEBUG [[__gnu__::__nodebug__]]
|
|
#define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__)))
|
|
#define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100)))
|
|
#define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \
|
|
__attribute__((__format__(archetype, format_string_index, first_format_arg_index)))
|
|
|
|
#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(__using_if_exists__)
|
|
# define _LIBCPP_USING_IF_EXISTS __attribute__((__using_if_exists__))
|
|
#else
|
|
# define _LIBCPP_USING_IF_EXISTS
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__no_destroy__)
|
|
# define _LIBCPP_NO_DESTROY [[_Clang::__no_destroy__]]
|
|
#else
|
|
# define _LIBCPP_NO_DESTROY
|
|
#endif
|
|
|
|
#if __has_attribute(__diagnose_if__)
|
|
# define _LIBCPP_DIAGNOSE_WARNING(...) __attribute__((__diagnose_if__(__VA_ARGS__, "warning")))
|
|
#else
|
|
# define _LIBCPP_DIAGNOSE_WARNING(...)
|
|
#endif
|
|
|
|
#if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_APPLE_CLANG_VER) && \
|
|
(!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2001)
|
|
# define _LIBCPP_DIAGNOSE_IF(...) __attribute__((__diagnose_if__(__VA_ARGS__)))
|
|
#else
|
|
# define _LIBCPP_DIAGNOSE_IF(...)
|
|
#endif
|
|
|
|
#define _LIBCPP_DIAGNOSE_NULLPTR_IF(condition, condition_description) \
|
|
_LIBCPP_DIAGNOSE_IF( \
|
|
condition, \
|
|
"null passed to callee that requires a non-null argument" condition_description, \
|
|
"warning", \
|
|
"nonnull")
|
|
|
|
#if __has_cpp_attribute(_Clang::__lifetimebound__)
|
|
# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]]
|
|
#else
|
|
# define _LIBCPP_LIFETIMEBOUND
|
|
#endif
|
|
|
|
// This is to work around https://llvm.org/PR156809
|
|
#ifndef _LIBCPP_CXX03_LANG
|
|
# define _LIBCPP_CTOR_LIFETIMEBOUND _LIBCPP_LIFETIMEBOUND
|
|
#else
|
|
# define _LIBCPP_CTOR_LIFETIMEBOUND
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__noescape__)
|
|
# define _LIBCPP_NOESCAPE [[_Clang::__noescape__]]
|
|
#else
|
|
# define _LIBCPP_NOESCAPE
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__no_specializations__)
|
|
# define _LIBCPP_NO_SPECIALIZATIONS \
|
|
[[_Clang::__no_specializations__("Users are not allowed to specialize this standard library entity")]]
|
|
#else
|
|
# define _LIBCPP_NO_SPECIALIZATIONS
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__preferred_name__)
|
|
# define _LIBCPP_PREFERRED_NAME(x) [[_Clang::__preferred_name__(x)]]
|
|
#else
|
|
# define _LIBCPP_PREFERRED_NAME(x)
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__scoped_lockable__)
|
|
# define _LIBCPP_SCOPED_LOCKABLE [[_Clang::__scoped_lockable__]]
|
|
#else
|
|
# define _LIBCPP_SCOPED_LOCKABLE
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__capability__)
|
|
# define _LIBCPP_CAPABILITY(...) [[_Clang::__capability__(__VA_ARGS__)]]
|
|
#else
|
|
# define _LIBCPP_CAPABILITY(...)
|
|
#endif
|
|
|
|
#if __has_attribute(__acquire_capability__)
|
|
# define _LIBCPP_ACQUIRE_CAPABILITY(...) __attribute__((__acquire_capability__(__VA_ARGS__)))
|
|
#else
|
|
# define _LIBCPP_ACQUIRE_CAPABILITY(...)
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__try_acquire_capability__)
|
|
# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) [[_Clang::__try_acquire_capability__(__VA_ARGS__)]]
|
|
#else
|
|
# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...)
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__acquire_shared_capability__)
|
|
# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY [[_Clang::__acquire_shared_capability__]]
|
|
#else
|
|
# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__try_acquire_shared_capability__)
|
|
# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) [[_Clang::__try_acquire_shared_capability__(__VA_ARGS__)]]
|
|
#else
|
|
# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...)
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__release_capability__)
|
|
# define _LIBCPP_RELEASE_CAPABILITY [[_Clang::__release_capability__]]
|
|
#else
|
|
# define _LIBCPP_RELEASE_CAPABILITY
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__release_shared_capability__)
|
|
# define _LIBCPP_RELEASE_SHARED_CAPABILITY [[_Clang::__release_shared_capability__]]
|
|
#else
|
|
# define _LIBCPP_RELEASE_SHARED_CAPABILITY
|
|
#endif
|
|
|
|
#if __has_attribute(__requires_capability__)
|
|
# define _LIBCPP_REQUIRES_CAPABILITY(...) __attribute__((__requires_capability__(__VA_ARGS__)))
|
|
#else
|
|
# define _LIBCPP_REQUIRES_CAPABILITY(...)
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__no_thread_safety_analysis__)
|
|
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS [[_Clang::__no_thread_safety_analysis__]]
|
|
#else
|
|
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
|
|
#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
|
|
|
|
#if __has_feature(nullability)
|
|
# define _LIBCPP_DIAGNOSE_NULLPTR _Nonnull
|
|
#else
|
|
# define _LIBCPP_DIAGNOSE_NULLPTR
|
|
#endif
|
|
|
|
#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
|
|
// The CUDA SDK contains an unfortunate definition for the __noinline__ macro,
|
|
// which breaks the regular __attribute__((__noinline__)) syntax. Therefore,
|
|
// when compiling for CUDA we use the non-underscored version of the noinline
|
|
// attribute.
|
|
//
|
|
// This is a temporary workaround and we still expect the CUDA SDK team to solve
|
|
// this issue properly in the SDK headers.
|
|
//
|
|
// See https://github.com/llvm/llvm-project/pull/73838 for more details.
|
|
# define _LIBCPP_NOINLINE __attribute__((noinline))
|
|
#elif __has_attribute(__noinline__)
|
|
# define _LIBCPP_NOINLINE __attribute__((__noinline__))
|
|
#else
|
|
# define _LIBCPP_NOINLINE
|
|
#endif
|
|
|
|
// Deprecation macros
|
|
// ------------------
|
|
|
|
// Deprecations warnings are always enabled, except when users explicitly opt-out
|
|
// by defining _LIBCPP_DISABLE_DEPRECATION_WARNINGS.
|
|
#if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)
|
|
# if __has_attribute(__deprecated__)
|
|
# define _LIBCPP_DEPRECATED __attribute__((__deprecated__))
|
|
# define _LIBCPP_DEPRECATED_(m) __attribute__((__deprecated__(m)))
|
|
# elif _LIBCPP_STD_VER >= 14
|
|
# define _LIBCPP_DEPRECATED [[deprecated]]
|
|
# define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]]
|
|
# else
|
|
# define _LIBCPP_DEPRECATED
|
|
# define _LIBCPP_DEPRECATED_(m)
|
|
# endif
|
|
#else
|
|
# define _LIBCPP_DEPRECATED
|
|
# define _LIBCPP_DEPRECATED_(m)
|
|
#endif
|
|
|
|
#if !defined(_LIBCPP_CXX03_LANG)
|
|
# define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_IN_CXX11
|
|
#endif
|
|
|
|
#if _LIBCPP_STD_VER >= 14
|
|
# define _LIBCPP_DEPRECATED_IN_CXX14 _LIBCPP_DEPRECATED
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_IN_CXX14
|
|
#endif
|
|
|
|
#if _LIBCPP_STD_VER >= 17
|
|
# define _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_DEPRECATED
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_IN_CXX17
|
|
#endif
|
|
|
|
#if _LIBCPP_STD_VER >= 20
|
|
# define _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_DEPRECATED
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_IN_CXX20
|
|
#endif
|
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_IN_CXX23
|
|
#endif
|
|
|
|
#if _LIBCPP_STD_VER >= 26
|
|
# define _LIBCPP_DEPRECATED_IN_CXX26 _LIBCPP_DEPRECATED
|
|
# define _LIBCPP_DEPRECATED_IN_CXX26_(m) _LIBCPP_DEPRECATED_(m)
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_IN_CXX26
|
|
# define _LIBCPP_DEPRECATED_IN_CXX26_(m)
|
|
#endif
|
|
|
|
#if _LIBCPP_HAS_CHAR8_T
|
|
# define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED
|
|
#else
|
|
# define _LIBCPP_DEPRECATED_WITH_CHAR8_T
|
|
#endif
|
|
|
|
#if __has_cpp_attribute(_Clang::__no_field_protection__)
|
|
# define _LIBCPP_DISABLE_POINTER_FIELD_PROTECTION [[_Clang::__no_field_protection__]]
|
|
#else
|
|
# define _LIBCPP_DISABLE_POINTER_FIELD_PROTECTION
|
|
#endif
|
|
|
|
#endif // _LIBCPP___CONFIGURATION_ATTRIBUTES_H
|