[libc++] Make __has_array_cookie a variable template (#212767)

Using variable templates is slightly faster to compile and more
readable, so we might as well use them.
This commit is contained in:
Nikolas Klauser 2026-07-31 13:24:04 +02:00 committed by GitHub
parent 5aec353bd6
commit 090b6569b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 9 additions and 11 deletions

View file

@ -14,9 +14,7 @@
#include <__configuration/abi.h>
#include <__cstddef/size_t.h>
#include <__memory/addressof.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/negation.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@ -37,10 +35,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// TODO: We should factor in the choice of the usual deallocation function in this determination:
// a cookie may be available in more cases but we ignore those for now.
template <class _Tp>
struct __has_array_cookie : _Not<is_trivially_destructible<_Tp> > {};
inline const bool __has_array_cookie_v = !is_trivially_destructible<_Tp>::value;
#else
template <class _Tp>
struct __has_array_cookie : false_type {};
inline const bool __has_array_cookie_v = false;
#endif
struct __itanium_array_cookie {
@ -97,7 +95,7 @@ template <class _Tp>
// Avoid failures when -fsanitize-address-poison-custom-array-cookie is enabled
_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") size_t __get_array_cookie([[__maybe_unused__]] _Tp const* __ptr) {
static_assert(
__has_array_cookie<_Tp>::value, "Trying to access the array cookie of a type that is not guaranteed to have one");
__has_array_cookie_v<_Tp>, "Trying to access the array cookie of a type that is not guaranteed to have one");
#if defined(_LIBCPP_ABI_ITANIUM)
using _ArrayCookie = __itanium_array_cookie;

View file

@ -319,7 +319,7 @@ struct __unique_ptr_array_bounds_stateless {
template <class _Deleter,
class _Tp,
__enable_if_t<__is_default_deleter_v<_Deleter> && __has_array_cookie<_Tp>::value, int> = 0>
__enable_if_t<__is_default_deleter_v<_Deleter> && __has_array_cookie_v<_Tp>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp* __ptr, size_t __index) const {
// In constant expressions, we can't check the array cookie so we just pretend that the index
// is in-bounds. The compiler catches invalid accesses anyway.
@ -331,7 +331,7 @@ struct __unique_ptr_array_bounds_stateless {
template <class _Deleter,
class _Tp,
__enable_if_t<!__is_default_deleter_v<_Deleter> || !__has_array_cookie<_Tp>::value, int> = 0>
__enable_if_t<!__is_default_deleter_v<_Deleter> || !__has_array_cookie_v<_Tp>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp*, size_t) const {
return true; // If we don't have an array cookie, we assume the access is in-bounds
}
@ -349,7 +349,7 @@ struct __unique_ptr_array_bounds_stored {
// Use the array cookie if there's one
template <class _Deleter,
class _Tp,
__enable_if_t<__is_default_deleter_v<_Deleter> && __has_array_cookie<_Tp>::value, int> = 0>
__enable_if_t<__is_default_deleter_v<_Deleter> && __has_array_cookie_v<_Tp>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp* __ptr, size_t __index) const {
if (__libcpp_is_constant_evaluated())
return true;
@ -360,7 +360,7 @@ struct __unique_ptr_array_bounds_stored {
// Otherwise, fall back on the stored size (if any)
template <class _Deleter,
class _Tp,
__enable_if_t<!__is_default_deleter_v<_Deleter> || !__has_array_cookie<_Tp>::value, int> = 0>
__enable_if_t<!__is_default_deleter_v<_Deleter> || !__has_array_cookie_v<_Tp>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp*, size_t __index) const {
return __index < __size_;
}

View file

@ -49,8 +49,8 @@ struct MyDeleter {
template <class WithCookie, class NoCookie>
void test() {
LIBCPP_STATIC_ASSERT(std::__has_array_cookie<WithCookie>::value);
LIBCPP_STATIC_ASSERT(!std::__has_array_cookie<NoCookie>::value);
LIBCPP_STATIC_ASSERT(std::__has_array_cookie_v<WithCookie>);
LIBCPP_STATIC_ASSERT(!std::__has_array_cookie_v<NoCookie>);
// For types with an array cookie, we can always detect OOB accesses. Note that reliance on an array
// cookie is limited to the default deleter, since a unique_ptr with a custom deleter may not have