[libcxx-commits] [libcxx] [libc++][string] Remove potential non-trailing 0-length array (PR #105865)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Sep 8 02:11:36 PDT 2024


https://github.com/serge-sans-paille updated https://github.com/llvm/llvm-project/pull/105865

>From 5cbdce6e0ad09d19061fc88258d17d64fc7850bd Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Fri, 23 Aug 2024 19:52:56 +0200
Subject: [PATCH 1/4] [libc++][string] Remove potential non-trailing 0-length
 array

It is a violation of the standard to use 0 length arrays, especially
when not at the end of a structure (not a FAM GNU extension). Compiler
generally accept it, but it's probably better to have a conforming
implementation.

This patch relies on `no_unique_address` being unconditionally
available, which is the case since 42f5277de16cd.
---
 libcxx/include/string | 52 ++++++++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 16 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 3480b57375c118..ecfda676aa3d85 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -749,6 +749,41 @@ struct __can_be_converted_to_string_view
 struct __uninitialized_size_tag {};
 struct __init_with_sentinel_tag {};
 
+#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
+template <class _CharT, size_t __min_cap, size_t _Padding = sizeof(_CharT) - 1>
+struct __short_impl {
+  _CharT __data_[__min_cap];
+  unsigned char __padding_[_Padding];
+  unsigned char __size_    : 7;
+  unsigned char __is_long_ : 1;
+};
+
+template <class _CharT, size_t __min_cap>
+struct __short_impl<_CharT, __min_cap, 0> {
+  value_type __data_[__min_cap];
+  unsigned char __size_    : 7;
+  unsigned char __is_long_ : 1;
+};
+#else
+template <class _CharT, size_t __min_cap, size_t _Padding = sizeof(_CharT) - 1>
+struct __short_impl {
+  struct _LIBCPP_PACKED {
+    unsigned char __is_long_ : 1;
+    unsigned char __size_    : 7;
+  };
+  char __padding_[_Padding];
+  _CharT __data_[__min_cap];
+};
+template <class _CharT, size_t __min_cap>
+struct __short_impl<_CharT, __min_cap, 0> {
+  struct _LIBCPP_PACKED {
+    unsigned char __is_long_ : 1;
+    unsigned char __size_    : 7;
+  };
+  _CharT __data_[__min_cap];
+};
+#endif
+
 template <class _CharT, class _Traits, class _Allocator>
 class basic_string {
 private:
@@ -851,13 +886,6 @@ private:
 
   enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 };
 
-  struct __short {
-    value_type __data_[__min_cap];
-    unsigned char __padding_[sizeof(value_type) - 1];
-    unsigned char __size_    : 7;
-    unsigned char __is_long_ : 1;
-  };
-
   // The __endian_factor is required because the field we use to store the size
   // has one fewer bit than it would if it were not a bitfield.
   //
@@ -900,17 +928,9 @@ private:
 
   enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 };
 
-  struct __short {
-    struct _LIBCPP_PACKED {
-      unsigned char __is_long_ : 1;
-      unsigned char __size_    : 7;
-    };
-    char __padding_[sizeof(value_type) - 1];
-    value_type __data_[__min_cap];
-  };
-
 #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
 
+  using __short = __short_impl<value_type, __min_cap>;
   static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
 
   union __rep {

>From 960e989c220dce2582446ba1e8e8a045f21bf4af Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Sat, 24 Aug 2024 14:11:35 +0200
Subject: [PATCH 2/4] fixup! [libc++][string] Remove potential non-trailing
 0-length array

---
 libcxx/include/string | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index ecfda676aa3d85..0415a8b47ad5df 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -760,7 +760,7 @@ struct __short_impl {
 
 template <class _CharT, size_t __min_cap>
 struct __short_impl<_CharT, __min_cap, 0> {
-  value_type __data_[__min_cap];
+  _CharT __data_[__min_cap];
   unsigned char __size_    : 7;
   unsigned char __is_long_ : 1;
 };

>From f17a95400593444883da0ce8472de415799cf640 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Thu, 29 Aug 2024 10:30:34 +0200
Subject: [PATCH 3/4] fixup! [libc++][string] Remove potential non-trailing
 0-length array

---
 libcxx/include/string | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 0415a8b47ad5df..4a0aa0ce48e539 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -751,7 +751,7 @@ struct __init_with_sentinel_tag {};
 
 #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
 template <class _CharT, size_t __min_cap, size_t _Padding = sizeof(_CharT) - 1>
-struct __short_impl {
+struct __short_layout_alternate {
   _CharT __data_[__min_cap];
   unsigned char __padding_[_Padding];
   unsigned char __size_    : 7;
@@ -759,14 +759,14 @@ struct __short_impl {
 };
 
 template <class _CharT, size_t __min_cap>
-struct __short_impl<_CharT, __min_cap, 0> {
+struct __short_layout_alternate<_CharT, __min_cap, 0> {
   _CharT __data_[__min_cap];
   unsigned char __size_    : 7;
   unsigned char __is_long_ : 1;
 };
 #else
 template <class _CharT, size_t __min_cap, size_t _Padding = sizeof(_CharT) - 1>
-struct __short_impl {
+struct __short_layout_classic {
   struct _LIBCPP_PACKED {
     unsigned char __is_long_ : 1;
     unsigned char __size_    : 7;
@@ -775,7 +775,7 @@ struct __short_impl {
   _CharT __data_[__min_cap];
 };
 template <class _CharT, size_t __min_cap>
-struct __short_impl<_CharT, __min_cap, 0> {
+struct __short_layout_classic<_CharT, __min_cap, 0> {
   struct _LIBCPP_PACKED {
     unsigned char __is_long_ : 1;
     unsigned char __size_    : 7;
@@ -930,7 +930,11 @@ private:
 
 #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
 
-  using __short = __short_impl<value_type, __min_cap>;
+#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
+  using __short = __short_layout_alternate<value_type, __min_cap>;
+#else
+  using __short = __short_layout_classic<value_type, __min_cap>;
+#endif
   static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
 
   union __rep {

>From 8d4bc538ea030e251d5527d95d994b31a60e04cc Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Sun, 8 Sep 2024 09:31:49 +0200
Subject: [PATCH 4/4] fixup! fixup! [libc++][string] Remove potential
 non-trailing 0-length array

---
 libcxx/include/string | 30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 4a0aa0ce48e539..ba51e3e9b90d83 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -749,40 +749,32 @@ struct __can_be_converted_to_string_view
 struct __uninitialized_size_tag {};
 struct __init_with_sentinel_tag {};
 
-#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
+
+template <size_t _PaddingSize>
+struct __padding {
+  char __padding_[_PaddingSize];
+};
+
+template <>
+struct __padding<0> {};
+
 template <class _CharT, size_t __min_cap, size_t _Padding = sizeof(_CharT) - 1>
 struct __short_layout_alternate {
   _CharT __data_[__min_cap];
-  unsigned char __padding_[_Padding];
+  _LIBCPP_NO_UNIQUE_ADDRESS __padding __padding_<_Padding>;
   unsigned char __size_    : 7;
   unsigned char __is_long_ : 1;
 };
 
-template <class _CharT, size_t __min_cap>
-struct __short_layout_alternate<_CharT, __min_cap, 0> {
-  _CharT __data_[__min_cap];
-  unsigned char __size_    : 7;
-  unsigned char __is_long_ : 1;
-};
-#else
 template <class _CharT, size_t __min_cap, size_t _Padding = sizeof(_CharT) - 1>
 struct __short_layout_classic {
   struct _LIBCPP_PACKED {
     unsigned char __is_long_ : 1;
     unsigned char __size_    : 7;
   };
-  char __padding_[_Padding];
+  _LIBCPP_NO_UNIQUE_ADDRESS __padding __padding_<_Padding>;
   _CharT __data_[__min_cap];
 };
-template <class _CharT, size_t __min_cap>
-struct __short_layout_classic<_CharT, __min_cap, 0> {
-  struct _LIBCPP_PACKED {
-    unsigned char __is_long_ : 1;
-    unsigned char __size_    : 7;
-  };
-  _CharT __data_[__min_cap];
-};
-#endif
 
 template <class _CharT, class _Traits, class _Allocator>
 class basic_string {



More information about the libcxx-commits mailing list