[libcxx-commits] [libcxx] 7265ff9 - [libc++] Fix issues with the triviality of std::array

Fangrui Song via libcxx-commits libcxx-commits at lists.llvm.org
Fri May 29 16:34:51 PDT 2020


Author: Louis Dionne
Date: 2020-05-29T16:32:55-07:00
New Revision: 7265ff928a974a844b6301c139cbb0f957532da9

URL: https://github.com/llvm/llvm-project/commit/7265ff928a974a844b6301c139cbb0f957532da9
DIFF: https://github.com/llvm/llvm-project/commit/7265ff928a974a844b6301c139cbb0f957532da9.diff

LOG: [libc++] Fix issues with the triviality of std::array

The Standard is currently unimplementable. We have to pick between:

1. Not implementing constexpr support properly in std::array<T, 0>
2. Making std::array<T, 0> non-trivial even when T is trivial
3. Returning nullptr from std::array<T, 0>::begin()

Libc++ initially picked (1). In 77b9abfc8e89, we started implementing constexpr properly, but lost the guarantee of triviality. Since it seems like both (1) and (2) are really important, it seems like (3) is the only viable option for libc++, after all. This is also what other implementations are doing.

This patch moves libc++ from (1) to (3).

It also:
- Improves the test coverage for the various ways of initializing std::array
- Adds tests for the triviality of std::array
- Adds tests for the aggregate-ness of std::array

Reviewed By: #libc, miscco, EricWF, zoecarver

Differential Revision: https://reviews.llvm.org/D80821

Added: 
    libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp

Modified: 
    libcxx/include/array
    libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp
    libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp
    libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp
    libcxx/test/std/containers/sequences/array/iterators.pass.cpp

Removed: 
    libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp


################################################################################
diff  --git a/libcxx/include/array b/libcxx/include/array
index 215d4e89f0ea..68743773f1a3 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -242,31 +242,16 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
     typedef std::reverse_iterator<iterator>       reverse_iterator;
     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
-#ifndef _LIBCPP_CXX03_LANG
-    union __wrapper {
-        _LIBCPP_CONSTEXPR __wrapper() : __b() { }
-        ~__wrapper() = default;
-
-        bool __b;
-        _Tp __t;
-    } __w;
-
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
-    value_type* data() _NOEXCEPT {return &__w.__t;}
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
-    const value_type* data() const _NOEXCEPT {return &__w.__t;}
-#else // C++03
     typedef typename conditional<is_const<_Tp>::value, const char,
                                 char>::type _CharType;
 
     struct  _ArrayInStructT { _Tp __data_[1]; };
     _ALIGNAS_TYPE(_ArrayInStructT) _CharType __elems_[sizeof(_ArrayInStructT)];
 
-    _LIBCPP_INLINE_VISIBILITY
-    value_type* data() _NOEXCEPT {return reinterpret_cast<value_type*>(__elems_);}
-    _LIBCPP_INLINE_VISIBILITY
-    const value_type* data() const _NOEXCEPT {return reinterpret_cast<const value_type*>(__elems_);}
-#endif
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+    value_type* data() _NOEXCEPT {return nullptr;}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+    const value_type* data() const _NOEXCEPT {return nullptr;}
 
     // No explicit construct/copy/destroy for aggregate type
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17

diff  --git a/libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp b/libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp
new file mode 100644
index 000000000000..d124e8477165
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Make sure std::array<T, N> is trivially copyable whenever T is trivially copyable.
+// This is not technically mandated by the Standard, but libc++ has been providing
+// this property.
+
+#include <array>
+#include <type_traits>
+
+
+struct Empty { };
+
+struct TrivialCopy {
+    int i;
+    double j;
+};
+
+struct NonTrivialCopy {
+    NonTrivialCopy(NonTrivialCopy const&) { }
+    NonTrivialCopy& operator=(NonTrivialCopy const&) { return *this; }
+};
+
+template <typename T>
+void check_trivially_copyable()
+{
+    static_assert(std::is_trivially_copyable<std::array<T, 0> >::value, "");
+    static_assert(std::is_trivially_copyable<std::array<T, 1> >::value, "");
+    static_assert(std::is_trivially_copyable<std::array<T, 2> >::value, "");
+    static_assert(std::is_trivially_copyable<std::array<T, 3> >::value, "");
+}
+
+int main(int, char**)
+{
+    check_trivially_copyable<int>();
+    check_trivially_copyable<long>();
+    check_trivially_copyable<double>();
+    check_trivially_copyable<long double>();
+    check_trivially_copyable<Empty>();
+    check_trivially_copyable<TrivialCopy>();
+
+    // Check that std::array<T, 0> is still trivially copyable when T is not
+    static_assert( std::is_trivially_copyable<std::array<NonTrivialCopy, 0> >::value, "");
+    static_assert(!std::is_trivially_copyable<std::array<NonTrivialCopy, 1> >::value, "");
+    static_assert(!std::is_trivially_copyable<std::array<NonTrivialCopy, 2> >::value, "");
+    static_assert(!std::is_trivially_copyable<std::array<NonTrivialCopy, 3> >::value, "");
+
+    return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp b/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
index dd4064bb2fe8..9db25a9231bc 100644
--- a/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
@@ -7,44 +7,41 @@
 //===----------------------------------------------------------------------===//
 
 // Make sure std::array is an aggregate type.
+// We can only check this in C++17 and above, because we don't have the
+// trait before that.
+// UNSUPPORTED: c++03, c++11, c++14
 
 #include <array>
 #include <type_traits>
 
 template <typename T>
-void tests()
+void check_aggregate()
 {
-    // Test aggregate initialization
-    {
-        std::array<T, 0> a0 = {}; (void)a0;
-        std::array<T, 1> a1 = {T()}; (void)a1;
-        std::array<T, 2> a2 = {T(), T()}; (void)a2;
-        std::array<T, 3> a3 = {T(), T(), T()}; (void)a3;
-    }
-
-    // Test the is_aggregate trait.
-#if TEST_STD_VER >= 17 // The trait is only available in C++17 and above
     static_assert(std::is_aggregate<std::array<T, 0> >::value, "");
     static_assert(std::is_aggregate<std::array<T, 1> >::value, "");
     static_assert(std::is_aggregate<std::array<T, 2> >::value, "");
     static_assert(std::is_aggregate<std::array<T, 3> >::value, "");
     static_assert(std::is_aggregate<std::array<T, 4> >::value, "");
-#endif
 }
 
 struct Empty { };
-struct NonEmpty { int i; int j; };
+struct Trivial { int i; int j; };
+struct NonTrivial {
+    int i; int j;
+    NonTrivial(NonTrivial const&) { }
+};
 
 int main(int, char**)
 {
-    tests<char>();
-    tests<int>();
-    tests<long>();
-    tests<float>();
-    tests<double>();
-    tests<long double>();
-    tests<NonEmpty>();
-    tests<Empty>();
+    check_aggregate<char>();
+    check_aggregate<int>();
+    check_aggregate<long>();
+    check_aggregate<float>();
+    check_aggregate<double>();
+    check_aggregate<long double>();
+    check_aggregate<Empty>();
+    check_aggregate<Trivial>();
+    check_aggregate<NonTrivial>();
 
     return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp
deleted file mode 100644
index e73a9671f478..000000000000
--- a/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <array>
-
-// array();
-
-#include <array>
-#include <cassert>
-
-// std::array is explicitly allowed to be initialized with A a = { init-list };.
-// Disable the missing braces warning for this reason.
-#include "test_macros.h"
-#include "disable_missing_braces_warning.h"
-
-struct NoDefault {
-    TEST_CONSTEXPR NoDefault(int) { }
-};
-
-struct Default {
-    TEST_CONSTEXPR Default() { }
-};
-
-TEST_CONSTEXPR_CXX14 bool tests()
-{
-    {
-        std::array<Default, 3> array;
-        assert(array.size() == 3);
-    }
-
-    {
-        std::array<Default, 0> array;
-        assert(array.size() == 0);
-    }
-
-    {
-        typedef std::array<NoDefault, 0> C;
-        C c;
-        assert(c.size() == 0);
-        C c1 = {};
-        assert(c1.size() == 0);
-        C c2 = {{}};
-        assert(c2.size() == 0);
-    }
-
-    return true;
-}
-
-int main(int, char**)
-{
-    tests();
-#if TEST_STD_VER >= 14
-    static_assert(tests(), "");
-#endif
-    return 0;
-}

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 cb9a18298031..814d1df2d52f 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
@@ -32,62 +32,82 @@ struct NoDefault {
     TEST_CONSTEXPR NoDefault(int) { }
 };
 
+struct NonTrivialCopy {
+    TEST_CONSTEXPR NonTrivialCopy() { }
+    TEST_CONSTEXPR NonTrivialCopy(NonTrivialCopy const&) { }
+    TEST_CONSTEXPR_CXX14 NonTrivialCopy& operator=(NonTrivialCopy const&) { return *this; }
+};
+
 TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        C c = {1.1, 2.2, 3.3};
-        C c2 = c;
-        c2 = c;
-        static_assert(std::is_copy_constructible<C>::value, "");
-        static_assert(std::is_copy_assignable<C>::value, "");
+        typedef std::array<double, 3> Array;
+        Array array = {1.1, 2.2, 3.3};
+        Array copy = array;
+        copy = array;
+        static_assert(std::is_copy_constructible<Array>::value, "");
+        static_assert(std::is_copy_assignable<Array>::value, "");
     }
     {
-        typedef double T;
-        typedef std::array<const T, 3> C;
-        C c = {1.1, 2.2, 3.3};
-        C c2 = c;
-        ((void)c2);
-        static_assert(std::is_copy_constructible<C>::value, "");
-        TEST_NOT_COPY_ASSIGNABLE(C);
+        typedef std::array<double const, 3> Array;
+        Array array = {1.1, 2.2, 3.3};
+        Array copy = array; (void)copy;
+        static_assert(std::is_copy_constructible<Array>::value, "");
+        TEST_NOT_COPY_ASSIGNABLE(Array);
     }
     {
-        typedef double T;
-        typedef std::array<T, 0> C;
-        C c = {};
-        C c2 = c;
-        c2 = c;
-        static_assert(std::is_copy_constructible<C>::value, "");
-        static_assert(std::is_copy_assignable<C>::value, "");
+        typedef std::array<double, 0> Array;
+        Array array = {};
+        Array copy = array;
+        copy = array;
+        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 double T;
-        typedef std::array<const T, 0> C;
-        C c = {{}};
-        C c2 = c;
-        ((void)c2);
-        static_assert(std::is_copy_constructible<C>::value, "");
-        TEST_NOT_COPY_ASSIGNABLE(C);
+        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 = {};
+        Array copy = array;
+        copy = array;
+        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
+    {
+        typedef std::array<NonTrivialCopy, 0> Array;
+        Array array = {};
+        Array copy = array;
+        copy = array;
+        static_assert(std::is_copy_constructible<Array>::value, "");
     }
     {
-        typedef NoDefault T;
-        typedef std::array<T, 0> C;
-        C c = {};
-        C c2 = c;
-        c2 = c;
-        static_assert(std::is_copy_constructible<C>::value, "");
-        static_assert(std::is_copy_assignable<C>::value, "");
+        typedef std::array<NonTrivialCopy, 1> Array;
+        Array array = {};
+        Array copy = array;
+        copy = array;
+        static_assert(std::is_copy_constructible<Array>::value, "");
     }
     {
-        typedef NoDefault T;
-        typedef std::array<const T, 0> C;
-        C c = {{}};
-        C c2 = c;
-        ((void)c2);
-        static_assert(std::is_copy_constructible<C>::value, "");
-        TEST_NOT_COPY_ASSIGNABLE(C);
+        typedef std::array<NonTrivialCopy, 2> Array;
+        Array array = {};
+        Array copy = array;
+        copy = array;
+        static_assert(std::is_copy_constructible<Array>::value, "");
     }
 
     return true;

diff  --git a/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp
new file mode 100644
index 000000000000..9153106b384f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp
@@ -0,0 +1,188 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Test all the ways of initializing a std::array.
+
+#include <array>
+#include <cassert>
+#include <type_traits>
+#include "test_macros.h"
+
+
+struct NoDefault {
+    TEST_CONSTEXPR NoDefault(int) { }
+};
+
+// Test default initialization
+// This one isn't constexpr because omitting to initialize fundamental types
+// isn't valid in a constexpr context.
+struct test_default_initialization {
+    template <typename T>
+    void operator()() const
+    {
+        std::array<T, 0> a0; (void)a0;
+        std::array<T, 1> a1; (void)a1;
+        std::array<T, 2> a2; (void)a2;
+        std::array<T, 3> a3; (void)a3;
+
+        std::array<NoDefault, 0> nodefault; (void)nodefault;
+    }
+};
+
+struct test_nondefault_initialization {
+    template <typename T>
+    TEST_CONSTEXPR_CXX14 void operator()() const
+    {
+        // Check direct-list-initialization syntax (introduced in C++11)
+    #if TEST_STD_VER >= 11
+        {
+            {
+                std::array<T, 0> a0_0{}; (void)a0_0;
+            }
+            {
+                std::array<T, 1> a1_0{}; (void)a1_0;
+                std::array<T, 1> a1_1{T()}; (void)a1_1;
+            }
+            {
+                std::array<T, 2> a2_0{}; (void)a2_0;
+                std::array<T, 2> a2_1{T()}; (void)a2_1;
+                std::array<T, 2> a2_2{T(), T()}; (void)a2_2;
+            }
+            {
+                std::array<T, 3> a3_0{}; (void)a3_0;
+                std::array<T, 3> a3_1{T()}; (void)a3_1;
+                std::array<T, 3> a3_2{T(), T()}; (void)a3_2;
+                std::array<T, 3> a3_3{T(), T(), T()}; (void)a3_3;
+            }
+
+            std::array<NoDefault, 0> nodefault{}; (void)nodefault;
+        }
+    #endif
+
+        // Check copy-list-initialization syntax
+        {
+            {
+                std::array<T, 0> a0_0 = {}; (void)a0_0;
+            }
+            {
+                std::array<T, 1> a1_0 = {}; (void)a1_0;
+                std::array<T, 1> a1_1 = {T()}; (void)a1_1;
+            }
+            {
+                std::array<T, 2> a2_0 = {}; (void)a2_0;
+                std::array<T, 2> a2_1 = {T()}; (void)a2_1;
+                std::array<T, 2> a2_2 = {T(), T()}; (void)a2_2;
+            }
+            {
+                std::array<T, 3> a3_0 = {}; (void)a3_0;
+                std::array<T, 3> a3_1 = {T()}; (void)a3_1;
+                std::array<T, 3> a3_2 = {T(), T()}; (void)a3_2;
+                std::array<T, 3> a3_3 = {T(), T(), T()}; (void)a3_3;
+            }
+
+            std::array<NoDefault, 0> nodefault = {}; (void)nodefault;
+        }
+
+        // Test aggregate initialization
+        {
+            {
+                std::array<T, 0> a0_0 = {{}}; (void)a0_0;
+            }
+            {
+                std::array<T, 1> a1_0 = {{}}; (void)a1_0;
+                std::array<T, 1> a1_1 = {{T()}}; (void)a1_1;
+            }
+            {
+                std::array<T, 2> a2_0 = {{}}; (void)a2_0;
+                std::array<T, 2> a2_1 = {{T()}}; (void)a2_1;
+                std::array<T, 2> a2_2 = {{T(), T()}}; (void)a2_2;
+            }
+            {
+                std::array<T, 3> a3_0 = {{}}; (void)a3_0;
+                std::array<T, 3> a3_1 = {{T()}}; (void)a3_1;
+                std::array<T, 3> a3_2 = {{T(), T()}}; (void)a3_2;
+                std::array<T, 3> a3_3 = {{T(), T(), T()}}; (void)a3_3;
+            }
+
+            // See http://wg21.link/LWG2157
+            std::array<NoDefault, 0> nodefault = {{}}; (void)nodefault;
+        }
+    }
+};
+
+// Test construction from an initializer-list
+TEST_CONSTEXPR_CXX14 bool test_initializer_list()
+{
+    {
+        std::array<double, 3> const a3_0 = {};
+        assert(a3_0[0] == double());
+        assert(a3_0[1] == double());
+        assert(a3_0[2] == double());
+    }
+    {
+        std::array<double, 3> const a3_1 = {1};
+        assert(a3_1[0] == double(1));
+        assert(a3_1[1] == double());
+        assert(a3_1[2] == double());
+    }
+    {
+        std::array<double, 3> const a3_2 = {1, 2.2};
+        assert(a3_2[0] == double(1));
+        assert(a3_2[1] == 2.2);
+        assert(a3_2[2] == double());
+    }
+    {
+        std::array<double, 3> const a3_3 = {1, 2, 3.5};
+        assert(a3_3[0] == double(1));
+        assert(a3_3[1] == double(2));
+        assert(a3_3[2] == 3.5);
+    }
+
+    return true;
+}
+
+struct Empty { };
+struct Trivial { int i; int j; };
+struct NonTrivial {
+    TEST_CONSTEXPR NonTrivial() { }
+    TEST_CONSTEXPR NonTrivial(NonTrivial const&) { }
+};
+struct NonEmptyNonTrivial {
+    int i; int j;
+    TEST_CONSTEXPR NonEmptyNonTrivial() : i(22), j(33) { }
+    TEST_CONSTEXPR NonEmptyNonTrivial(NonEmptyNonTrivial const&) : i(22), j(33) { }
+};
+
+template <typename F>
+TEST_CONSTEXPR_CXX14 bool with_all_types()
+{
+    F().template operator()<char>();
+    F().template operator()<int>();
+    F().template operator()<long>();
+    F().template operator()<float>();
+    F().template operator()<double>();
+    F().template operator()<long double>();
+    F().template operator()<Empty>();
+    F().template operator()<Trivial>();
+    F().template operator()<NonTrivial>();
+    F().template operator()<NonEmptyNonTrivial>();
+    return true;
+}
+
+int main(int, char**)
+{
+    with_all_types<test_nondefault_initialization>();
+    with_all_types<test_default_initialization>(); // not constexpr
+    test_initializer_list();
+#if TEST_STD_VER >= 14
+    static_assert(with_all_types<test_nondefault_initialization>(), "");
+    static_assert(test_initializer_list(), "");
+#endif
+
+    return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp
deleted file mode 100644
index 49437546a8f7..000000000000
--- a/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <array>
-
-// Construct with initializer list
-
-#include <array>
-#include <cassert>
-
-// std::array is explicitly allowed to be initialized with A a = { init-list };.
-// Disable the missing braces warning for this reason.
-#include "test_macros.h"
-#include "disable_missing_braces_warning.h"
-
-TEST_CONSTEXPR_CXX14 bool tests()
-{
-    {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        C const c = {1, 2, 3.5};
-        assert(c.size() == 3);
-        assert(c[0] == 1);
-        assert(c[1] == 2);
-        assert(c[2] == 3.5);
-    }
-    {
-        typedef double T;
-        typedef std::array<T, 0> C;
-        C const c = {};
-        assert(c.size() == 0);
-    }
-
-    {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        C const c = {1};
-        assert(c.size() == 3.0);
-        assert(c[0] == 1);
-    }
-    {
-        typedef int T;
-        typedef std::array<T, 1> C;
-        C const c = {};
-        assert(c.size() == 1);
-    }
-
-    return true;
-}
-
-int main(int, char**)
-{
-    tests();
-#if TEST_STD_VER >= 14
-    static_assert(tests(), "");
-#endif
-    return 0;
-}

diff  --git a/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp b/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp
index a41409f8df1c..3493659f49a6 100644
--- a/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp
@@ -49,14 +49,14 @@ TEST_CONSTEXPR_CXX17 bool tests()
         typedef std::array<T, 0> C;
         C c = {};
         T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
+        (void)p;
     }
     {
         typedef double T;
         typedef std::array<const T, 0> C;
         C c = {{}};
         const T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
+        (void)p;
         static_assert((std::is_same<decltype(c.data()), const T*>::value), "");
     }
     {
@@ -64,7 +64,7 @@ TEST_CONSTEXPR_CXX17 bool tests()
         typedef std::array<T, 0> C;
         C c = {};
         T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
+        (void)p;
     }
     {
         std::array<int, 5> c = {0, 1, 2, 3, 4};
@@ -92,7 +92,6 @@ int main(int, char**)
         typedef std::array<T, 0> C;
         const C c = {};
         const T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
         std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
         assert(pint % TEST_ALIGNOF(T) == 0);
     }

diff  --git a/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp b/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp
index 0f79237b48a6..cce6e63d30da 100644
--- a/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp
@@ -49,14 +49,14 @@ TEST_CONSTEXPR_CXX17 bool tests()
         typedef std::array<T, 0> C;
         const C c = {};
         const T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
+        (void)p;
     }
     {
         typedef NoDefault T;
         typedef std::array<T, 0> C;
         const C c = {};
         const T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
+        (void)p;
     }
     {
         std::array<int, 5> const c = {0, 1, 2, 3, 4};
@@ -84,7 +84,6 @@ int main(int, char**)
         typedef std::array<T, 0> C;
         const C c = {};
         const T* p = c.data();
-        LIBCPP_ASSERT(p != nullptr);
         std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
         assert(pint % TEST_ALIGNOF(T) == 0);
     }

diff  --git a/libcxx/test/std/containers/sequences/array/iterators.pass.cpp b/libcxx/test/std/containers/sequences/array/iterators.pass.cpp
index 39d8a1a5dfa4..60b01dfc1abe 100644
--- a/libcxx/test/std/containers/sequences/array/iterators.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/iterators.pass.cpp
@@ -52,8 +52,6 @@ TEST_CONSTEXPR_CXX17 bool tests()
         typename C::iterator i = array.begin();
         typename C::const_iterator j = array.cbegin();
         assert(i == j);
-        LIBCPP_ASSERT(i != nullptr);
-        LIBCPP_ASSERT(j != nullptr);
     }
 
     {
@@ -63,8 +61,6 @@ TEST_CONSTEXPR_CXX17 bool tests()
         typename C::const_iterator j = array.cbegin();
         assert(i == array.end());
         assert(j == array.cend());
-        LIBCPP_ASSERT(i != nullptr);
-        LIBCPP_ASSERT(j != nullptr);
     }
     {
         typedef std::array<int, 1> C;
@@ -101,8 +97,6 @@ TEST_CONSTEXPR_CXX17 bool tests()
         typename C::iterator ib = array.begin();
         typename C::iterator ie = array.end();
         assert(ib == ie);
-        LIBCPP_ASSERT(ib != nullptr);
-        LIBCPP_ASSERT(ie != nullptr);
     }
 
 #if TEST_STD_VER >= 14


        


More information about the libcxx-commits mailing list