[libcxx-commits] [libcxx] Improvements to std::array<T, 0>. (PR #74657)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Dec 7 06:12:44 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Ryan Nicholl (rnicholl-google)
<details>
<summary>Changes</summary>
In the unstable ABI, std::array<T, 0> now uses only 1 byte with empty base optimization. In the stable ABI, it now can be used in constexpr context like std::array<int, 0> a; a.fill(1); return a;
Fixes llvm/llvm-project#<!-- -->74375
---
Full diff: https://github.com/llvm/llvm-project/pull/74657.diff
6 Files Affected:
- (modified) libcxx/include/__config (+4)
- (modified) libcxx/include/array (+8-1)
- (modified) libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp (-1)
- (modified) libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp (-15)
- (modified) libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp (+13-2)
- (modified) libcxx/test/std/containers/views/mdspan/extents/CtorTestCombinations.h (+1-1)
``````````diff
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 51eb484297f6b..9d256aeb222fa 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -168,6 +168,10 @@
// pointer from 16 to 8. This changes the output of std::string::max_size,
// which makes it ABI breaking
# define _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
+// Make std::array<T, N> where N == 0 have no data
+// This allows it to be used in constexpr contexts without
+// introducing runtime overhead
+# define _LIBCPP_ABI_ZERO_SIZE_ARRAY_HAS_NO_DATA
# elif _LIBCPP_ABI_VERSION == 1
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
// Enable compiling copies of now inline methods into the dylib to support
diff --git a/libcxx/include/array b/libcxx/include/array
index c01d13ef358a5..d4df7cd302b99 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -263,8 +263,13 @@ struct _LIBCPP_TEMPLATE_VIS array
const value_type* data() const _NOEXCEPT {return __elems_;}
};
+struct _EmptyAggregateType {};
+
template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
+#ifdef _LIBCPP_ABI_ZERO_SIZE_ARRAY_HAS_NO_DATA
+: _EmptyAggregateType
+#endif
{
// types:
typedef array __self;
@@ -282,8 +287,10 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
typedef __conditional_t<is_const<_Tp>::value, const char, char> _CharType;
+#ifndef _LIBCPP_ABI_ZERO_SIZE_ARRAY_HAS_NO_DATA
struct _ArrayInStructT { _Tp __data_[1]; };
- _ALIGNAS_TYPE(_ArrayInStructT) _CharType __elems_[sizeof(_ArrayInStructT)];
+ _ALIGNAS_TYPE(_ArrayInStructT) array<_EmptyAggregateType,sizeof(_ArrayInStructT)> __elems_;
+#endif
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
value_type* data() _NOEXCEPT {return nullptr;}
diff --git a/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp b/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp
index 4921a48bcccc1..07d346333f451 100644
--- a/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp
@@ -199,7 +199,6 @@ void test()
test_not_const<void(Empty::*)(const int&) noexcept(false)>();
// Sequence containers
- test_not_const<std::array< int, 0>>();
test_not_const<std::array< int, 1>>();
test_false <std::array<const int, 1>>();
test_not_const<std::array< volatile int, 1>>();
diff --git a/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp
index 0e1e77fc5f181..08634d242b0d6 100644
--- a/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp
@@ -59,14 +59,6 @@ TEST_CONSTEXPR_CXX14 bool tests()
static_assert(std::is_copy_constructible<Array>::value, "");
static_assert(std::is_copy_assignable<Array>::value, "");
}
- {
- // const arrays of size 0 should disable the implicit copy assignment operator.
- typedef std::array<double const, 0> Array;
- Array array = {};
- Array copy = array; (void)copy;
- static_assert(std::is_copy_constructible<Array>::value, "");
- TEST_NOT_COPY_ASSIGNABLE(Array);
- }
{
typedef std::array<NoDefault, 0> Array;
Array array = {};
@@ -75,13 +67,6 @@ TEST_CONSTEXPR_CXX14 bool tests()
static_assert(std::is_copy_constructible<Array>::value, "");
static_assert(std::is_copy_assignable<Array>::value, "");
}
- {
- typedef std::array<NoDefault const, 0> Array;
- Array array = {};
- Array copy = array; (void)copy;
- static_assert(std::is_copy_constructible<Array>::value, "");
- TEST_NOT_COPY_ASSIGNABLE(Array);
- }
// Make sure we can implicitly copy a std::array of a non-trivially copyable type
{
diff --git a/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp b/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp
index 6fbc844a11eac..0477cef42e43e 100644
--- a/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp
@@ -31,14 +31,25 @@ struct MyArray {
};
template <class T, std::size_t Size>
-void test() {
+struct test {
typedef T CArrayT[Size == 0 ? 1 : Size];
typedef std::array<T, Size> ArrayT;
typedef MyArray<T, Size == 0 ? 1 : Size> MyArrayT;
+
static_assert(sizeof(ArrayT) == sizeof(CArrayT), "");
static_assert(sizeof(ArrayT) == sizeof(MyArrayT), "");
static_assert(TEST_ALIGNOF(ArrayT) == TEST_ALIGNOF(MyArrayT), "");
-}
+};
+
+
+#ifdef _LIBCPP_ABI_ZERO_SIZE_ARRAY_HAS_NO_DATA
+template <class T>
+struct test<T, 0> {
+ using ArrayT = std::array<T, 0>;
+ static_assert(sizeof(ArrayT) == 1, "");
+ static_assert(TEST_ALIGNOF(ArrayT) == 1, "");
+};
+#endif
template <class T>
void test_type() {
diff --git a/libcxx/test/std/containers/views/mdspan/extents/CtorTestCombinations.h b/libcxx/test/std/containers/views/mdspan/extents/CtorTestCombinations.h
index 02731f8895ed8..62da3e0ca0089 100644
--- a/libcxx/test/std/containers/views/mdspan/extents/CtorTestCombinations.h
+++ b/libcxx/test/std/containers/views/mdspan/extents/CtorTestCombinations.h
@@ -45,7 +45,7 @@ constexpr void test_construction(AllExtents all_ext) {
// test construction from just dynamic extents
// create an array of just the extents corresponding to dynamic values
- std::array<typename AllExtents::value_type, E::rank_dynamic()> dyn_ext{0};
+ std::array<typename AllExtents::value_type, E::rank_dynamic()> dyn_ext{};
size_t dynamic_idx = 0;
for (size_t r = 0; r < E::rank(); r++) {
if (E::static_extent(r) == std::dynamic_extent) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/74657
More information about the libcxx-commits
mailing list