Skip to content

Commit 7e348e5

Browse files
committed
Fix unnecessary padding for basic_string's __short
Originally, padding in the struct `__short` was done with arrays, but when no padding was required, we got undefined behavior due to a zero-length array. C++17 11.3.4 Arrays p1: ``` If the <<length of array>> is present, it shall be a converted constant expression of type std::size_t and its value shall be greater than zero. ``` A fix was proposed in commit d95597d, which worked around the undefined behavior by wrapping the padding array in a struct if there was padding required and omitting the array altogether, with the help of a specialization, when the padding is zero. This change doesn't just work around the problem but changes the semantics of the code, introducing an issue. Contrary to C, in C++ empty structs and classes must have a size greater than zero. C++ 17 12 Classes p4: ``` Complete objects and member subobjects of class type shall have nonzero size. ``` So whenever there is no padding required we insert an empty struct-sized padding, which is 1 byte on X86_64 (but we won't feel it there, since on that platform padding is required if I am correct). I would like to propose another standard compliant solution using unnamed 0 width bitfields. 12.2.4 Bit-fields p2: ``` As a special case, an unnamed bit-field with a width of zero specifies alignment of the next bit-field at an allocation unit boundary. Only when declaring an unnamed bit-field may the value of the constant-expression be equal to zero. ```
1 parent d3153ad commit 7e348e5

File tree

1 file changed

+2
-10
lines changed

1 file changed

+2
-10
lines changed

libcxx/include/string

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -715,14 +715,6 @@ struct __can_be_converted_to_string_view
715715
struct __uninitialized_size_tag {};
716716
struct __init_with_sentinel_tag {};
717717

718-
template <size_t _PaddingSize>
719-
struct __padding {
720-
char __padding_[_PaddingSize];
721-
};
722-
723-
template <>
724-
struct __padding<0> {};
725-
726718
template <class _CharT, class _Traits, class _Allocator>
727719
class basic_string {
728720
public:
@@ -827,9 +819,9 @@ private:
827819

828820
struct __short {
829821
value_type __data_[__min_cap];
830-
_LIBCPP_NO_UNIQUE_ADDRESS __padding<sizeof(value_type) - 1> __padding_;
831822
unsigned char __size_ : 7;
832823
unsigned char __is_long_ : 1;
824+
value_type : 0;
833825
};
834826

835827
// The __endian_factor is required because the field we use to store the size
@@ -879,7 +871,7 @@ private:
879871
unsigned char __is_long_ : 1;
880872
unsigned char __size_ : 7;
881873
};
882-
_LIBCPP_NO_UNIQUE_ADDRESS __padding<sizeof(value_type) - 1> __padding_;
874+
value_type : 0;
883875
value_type __data_[__min_cap];
884876
};
885877

0 commit comments

Comments
 (0)