Skip to content

Commit 42f5277

Browse files
authored
[libc++] Fix __datasizeof_v for Clang17 and 18 in C++03 (#106832)
This also disables the use of `__datasizeof`, since it's currently broken for empty types.
1 parent fb14f1d commit 42f5277

File tree

3 files changed

+24
-30
lines changed

3 files changed

+24
-30
lines changed

libcxx/include/__config

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -997,21 +997,9 @@ typedef __char32_t char32_t;
997997
// (If/when MSVC breaks its C++ ABI, it will be changed to work as intended.)
998998
// However, MSVC implements [[msvc::no_unique_address]] which does what
999999
// [[no_unique_address]] is supposed to do, in general.
1000-
1001-
// Clang-cl does not yet (14.0) implement either [[no_unique_address]] or
1002-
// [[msvc::no_unique_address]] though. If/when it does implement
1003-
// [[msvc::no_unique_address]], this should be preferred though.
10041000
# define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
1005-
# elif __has_cpp_attribute(no_unique_address)
1006-
# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
10071001
# else
1008-
# define _LIBCPP_NO_UNIQUE_ADDRESS /* nothing */
1009-
// Note that this can be replaced by #error as soon as clang-cl
1010-
// implements msvc::no_unique_address, since there should be no C++20
1011-
// compiler that doesn't support one of the two attributes at that point.
1012-
// We generally don't want to use this macro outside of C++20-only code,
1013-
// because using it conditionally in one language version only would make
1014-
// the ABI inconsistent.
1002+
# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
10151003
# endif
10161004

10171005
// c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these

libcxx/include/__type_traits/datasizeof.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,22 @@
2626

2727
_LIBCPP_BEGIN_NAMESPACE_STD
2828

29-
#if __has_keyword(__datasizeof) || __has_extension(datasizeof)
29+
// TODO: Enable this again once #94816 is fixed.
30+
#if (__has_keyword(__datasizeof) || __has_extension(datasizeof)) && 0
3031
template <class _Tp>
3132
inline const size_t __datasizeof_v = __datasizeof(_Tp);
3233
#else
33-
// NOLINTNEXTLINE(readability-redundant-preprocessor) This is https://llvm.org/PR64825
34-
# if __has_cpp_attribute(__no_unique_address__)
3534
template <class _Tp>
3635
struct _FirstPaddingByte {
37-
[[__no_unique_address__]] _Tp __v_;
36+
_LIBCPP_NO_UNIQUE_ADDRESS _Tp __v_;
3837
char __first_padding_byte_;
3938
};
40-
# else
41-
template <class _Tp, bool = __libcpp_is_final<_Tp>::value || !is_class<_Tp>::value>
42-
struct _FirstPaddingByte : _Tp {
43-
char __first_padding_byte_;
44-
};
45-
46-
template <class _Tp>
47-
struct _FirstPaddingByte<_Tp, true> {
48-
_Tp __v_;
49-
char __first_padding_byte_;
50-
};
51-
# endif // __has_cpp_attribute(__no_unique_address__)
5239

5340
// _FirstPaddingByte<> is sometimes non-standard layout. Using `offsetof` is UB in that case, but GCC and Clang allow
5441
// the use as an extension.
5542
_LIBCPP_DIAGNOSTIC_PUSH
5643
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
44+
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
5745
template <class _Tp>
5846
inline const size_t __datasizeof_v = offsetof(_FirstPaddingByte<_Tp>, __first_padding_byte_);
5947
_LIBCPP_DIAGNOSTIC_POP

libcxx/test/libcxx/type_traits/datasizeof.compile.pass.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,25 @@
88

99
#include <__type_traits/datasizeof.h>
1010
#include <cstdint>
11+
#include <type_traits>
1112

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

17-
struct OneBytePadding {
18+
struct NonStandardLayout {
19+
virtual ~NonStandardLayout();
20+
};
21+
22+
static_assert(!std::is_standard_layout<NonStandardLayout>::value, "");
23+
static_assert(std::__datasizeof_v<NonStandardLayout> == sizeof(void*), "");
24+
25+
struct Empty {};
26+
27+
static_assert(std::__datasizeof_v<Empty> == 0, "");
28+
29+
struct OneBytePadding final {
1830
OneBytePadding() {}
1931

2032
std::int16_t a;
@@ -36,3 +48,9 @@ struct InBetweenPadding {
3648
};
3749

3850
static_assert(std::__datasizeof_v<InBetweenPadding> == 8, "");
51+
52+
struct NoDataButNoPadding {
53+
OneBytePadding v;
54+
};
55+
56+
static_assert(std::__datasizeof_v<NoDataButNoPadding> == 4, "");

0 commit comments

Comments
 (0)