Skip to content

Commit

Permalink
[libc++] Fix __datasizeof_v for Clang17 and 18 in C++03
Browse files Browse the repository at this point in the history
  • Loading branch information
philnik777 committed Sep 3, 2024
1 parent fb14f1d commit 08c65bc
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 30 deletions.
14 changes: 1 addition & 13 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -997,21 +997,9 @@ typedef __char32_t char32_t;
// (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.

// Clang-cl does not yet (14.0) implement either [[no_unique_address]] or
// [[msvc::no_unique_address]] though. If/when it does implement
// [[msvc::no_unique_address]], this should be preferred though.
# define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
# elif __has_cpp_attribute(no_unique_address)
# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
# else
# define _LIBCPP_NO_UNIQUE_ADDRESS /* nothing */
// Note that this can be replaced by #error as soon as clang-cl
// implements msvc::no_unique_address, since there should be no C++20
// compiler that doesn't support one of the two attributes at that point.
// We generally don't want to use this macro outside of C++20-only code,
// because using it conditionally in one language version only would make
// the ABI inconsistent.
# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
# endif

// c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these
Expand Down
20 changes: 4 additions & 16 deletions libcxx/include/__type_traits/datasizeof.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,22 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_keyword(__datasizeof) || __has_extension(datasizeof)
// TODO: Enable this again once #94816 is fixed.
#if (__has_keyword(__datasizeof) || __has_extension(datasizeof)) && 0
template <class _Tp>
inline const size_t __datasizeof_v = __datasizeof(_Tp);
#else
// NOLINTNEXTLINE(readability-redundant-preprocessor) This is https://llvm.org/PR64825
# if __has_cpp_attribute(__no_unique_address__)
template <class _Tp>
struct _FirstPaddingByte {
[[__no_unique_address__]] _Tp __v_;
_LIBCPP_NO_UNIQUE_ADDRESS _Tp __v_;
char __first_padding_byte_;
};
# else
template <class _Tp, bool = __libcpp_is_final<_Tp>::value || !is_class<_Tp>::value>
struct _FirstPaddingByte : _Tp {
char __first_padding_byte_;
};

template <class _Tp>
struct _FirstPaddingByte<_Tp, true> {
_Tp __v_;
char __first_padding_byte_;
};
# endif // __has_cpp_attribute(__no_unique_address__)

// _FirstPaddingByte<> is sometimes non-standard layout. Using `offsetof` is UB in that case, but GCC and Clang allow
// the use as an extension.
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
template <class _Tp>
inline const size_t __datasizeof_v = offsetof(_FirstPaddingByte<_Tp>, __first_padding_byte_);
_LIBCPP_DIAGNOSTIC_POP
Expand Down
20 changes: 19 additions & 1 deletion libcxx/test/libcxx/type_traits/datasizeof.compile.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@

#include <__type_traits/datasizeof.h>
#include <cstdint>
#include <type_traits>

static_assert(std::__datasizeof_v<std::int8_t> == 1, "");
static_assert(std::__datasizeof_v<std::int16_t> == 2, "");
static_assert(std::__datasizeof_v<std::int32_t> == 4, "");
static_assert(std::__datasizeof_v<std::int64_t> == 8, "");

struct OneBytePadding {
struct NonStandardLayout {
virtual ~NonStandardLayout();
};

static_assert(!std::is_standard_layout<NonStandardLayout>::value, "");
static_assert(std::__datasizeof_v<NonStandardLayout> == sizeof(void*), "");

struct Empty {};

static_assert(std::__datasizeof_v<Empty> == 0, "");

struct OneBytePadding final {
OneBytePadding() {}

std::int16_t a;
Expand All @@ -36,3 +48,9 @@ struct InBetweenPadding {
};

static_assert(std::__datasizeof_v<InBetweenPadding> == 8, "");

struct NoDataButNoPadding {
OneBytePadding v;
};

static_assert(std::__datasizeof_v<NoDataButNoPadding> == 4, "");

0 comments on commit 08c65bc

Please sign in to comment.