[libcxx-commits] [libcxx] 77b9abf - [libc++] Complete overhaul of constexpr support in std::array

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu May 28 09:31:32 PDT 2020


Author: Louis Dionne
Date: 2020-05-28T12:31:06-04:00
New Revision: 77b9abfc8e89ca627e4f9a1cc206bea131db6db1

URL: https://github.com/llvm/llvm-project/commit/77b9abfc8e89ca627e4f9a1cc206bea131db6db1
DIFF: https://github.com/llvm/llvm-project/commit/77b9abfc8e89ca627e4f9a1cc206bea131db6db1.diff

LOG: [libc++] Complete overhaul of constexpr support in std::array

This commit adds missing support for constexpr in std::array under all
standard modes up to and including C++20. It also transforms the <array>
tests to check for constexpr-friendliness under the right standard modes.

Fixes https://llvm.org/PR40124
Fixes rdar://57522096
Supersedes https://reviews.llvm.org/D60666

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

Added: 
    libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
    libcxx/test/std/containers/sequences/array/at_const.pass.cpp
    libcxx/test/std/containers/sequences/array/front_back_const.pass.cpp
    libcxx/test/std/containers/sequences/array/indexing_const.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/array
    libcxx/include/version
    libcxx/test/std/containers/sequences/array/array.cons/deduct.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp
    libcxx/test/std/containers/sequences/array/array.creation/to_array.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/array.fill/fill.pass.cpp
    libcxx/test/std/containers/sequences/array/array.size/size.pass.cpp
    libcxx/test/std/containers/sequences/array/array.special/swap.pass.cpp
    libcxx/test/std/containers/sequences/array/array.swap/swap.pass.cpp
    libcxx/test/std/containers/sequences/array/array.tuple/get.pass.cpp
    libcxx/test/std/containers/sequences/array/array.tuple/get_const.pass.cpp
    libcxx/test/std/containers/sequences/array/array.tuple/get_const_rv.pass.cpp
    libcxx/test/std/containers/sequences/array/array.tuple/get_rv.pass.cpp
    libcxx/test/std/containers/sequences/array/array.tuple/tuple_element.fail.cpp
    libcxx/test/std/containers/sequences/array/at.pass.cpp
    libcxx/test/std/containers/sequences/array/compare.pass.cpp
    libcxx/test/std/containers/sequences/array/contiguous.pass.cpp
    libcxx/test/std/containers/sequences/array/empty.pass.cpp
    libcxx/test/std/containers/sequences/array/front_back.pass.cpp
    libcxx/test/std/containers/sequences/array/indexing.pass.cpp
    libcxx/test/std/containers/sequences/array/iterators.pass.cpp
    libcxx/test/std/containers/sequences/array/max_size.pass.cpp
    libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/test/support/test_macros.h
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    libcxx/test/std/containers/sequences/array/begin.pass.cpp


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index e8628408afd0..c04a883de179 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -168,6 +168,8 @@ Status
     ------------------------------------------------- -----------------
     **C++ 2a**                                                         
     -------------------------------------------------------------------
+    ``__cpp_lib_array_constexpr``                     ``201811L``      
+    ------------------------------------------------- -----------------
     ``__cpp_lib_atomic_ref``                          *unimplemented*  
     ------------------------------------------------- -----------------
     ``__cpp_lib_bind_front``                          *unimplemented*  

diff  --git a/libcxx/include/array b/libcxx/include/array
index 7ffa825a9652..215d4e89f0ea 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -32,24 +32,24 @@ struct array
     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
     // No explicit construct/copy/destroy for aggregate type
-    void fill(const T& u);
-    void swap(array& a) noexcept(is_nothrow_swappable_v<T>);
+    void fill(const T& u);                                      // constexpr in C++20
+    void swap(array& a) noexcept(is_nothrow_swappable_v<T>);    // constexpr in C++20
 
     // iterators:
-    iterator begin() noexcept;
-    const_iterator begin() const noexcept;
-    iterator end() noexcept;
-    const_iterator end() const noexcept;
+    iterator begin() noexcept;                                  // constexpr in C++17
+    const_iterator begin() const noexcept;                      // constexpr in C++17
+    iterator end() noexcept;                                    // constexpr in C++17
+    const_iterator end() const noexcept;                        // constexpr in C++17
 
-    reverse_iterator rbegin() noexcept;
-    const_reverse_iterator rbegin() const noexcept;
-    reverse_iterator rend() noexcept;
-    const_reverse_iterator rend() const noexcept;
+    reverse_iterator rbegin() noexcept;                         // constexpr in C++17
+    const_reverse_iterator rbegin() const noexcept;             // constexpr in C++17
+    reverse_iterator rend() noexcept;                           // constexpr in C++17
+    const_reverse_iterator rend() const noexcept;               // constexpr in C++17
 
-    const_iterator cbegin() const noexcept;
-    const_iterator cend() const noexcept;
-    const_reverse_iterator crbegin() const noexcept;
-    const_reverse_iterator crend() const noexcept;
+    const_iterator cbegin() const noexcept;                     // constexpr in C++17
+    const_iterator cend() const noexcept;                       // constexpr in C++17
+    const_reverse_iterator crbegin() const noexcept;            // constexpr in C++17
+    const_reverse_iterator crend() const noexcept;              // constexpr in C++17
 
     // capacity:
     constexpr size_type size() const noexcept;
@@ -57,46 +57,51 @@ struct array
     constexpr bool empty() const noexcept;
 
     // element access:
-    reference operator[](size_type n);
-    const_reference operator[](size_type n) const; // constexpr in C++14
-    const_reference at(size_type n) const; // constexpr in C++14
-    reference at(size_type n);
-
-    reference front();
-    const_reference front() const; // constexpr in C++14
-    reference back();
-    const_reference back() const; // constexpr in C++14
-
-    T* data() noexcept;
-    const T* data() const noexcept;
+    reference operator[](size_type n);                          // constexpr in C++17
+    const_reference operator[](size_type n) const;              // constexpr in C++14
+    reference at(size_type n);                                  // constexpr in C++17
+    const_reference at(size_type n) const;                      // constexpr in C++14
+
+    reference front();                                          // constexpr in C++17
+    const_reference front() const;                              // constexpr in C++14
+    reference back();                                           // constexpr in C++17
+    const_reference back() const;                               // constexpr in C++14
+
+    T* data() noexcept;                                         // constexpr in C++17
+    const T* data() const noexcept;                             // constexpr in C++17
 };
 
-  template <class T, class... U>
-    array(T, U...) -> array<T, 1 + sizeof...(U)>;
+template <class T, class... U>
+  array(T, U...) -> array<T, 1 + sizeof...(U)>;                 // C++17
 
 template <class T, size_t N>
-  bool operator==(const array<T,N>& x, const array<T,N>& y);
+  bool operator==(const array<T,N>& x, const array<T,N>& y);    // constexpr in C++20
 template <class T, size_t N>
-  bool operator!=(const array<T,N>& x, const array<T,N>& y);
+  bool operator!=(const array<T,N>& x, const array<T,N>& y);    // constexpr in C++20
 template <class T, size_t N>
-  bool operator<(const array<T,N>& x, const array<T,N>& y);
+  bool operator<(const array<T,N>& x, const array<T,N>& y);     // constexpr in C++20
 template <class T, size_t N>
-  bool operator>(const array<T,N>& x, const array<T,N>& y);
+  bool operator>(const array<T,N>& x, const array<T,N>& y);     // constexpr in C++20
 template <class T, size_t N>
-  bool operator<=(const array<T,N>& x, const array<T,N>& y);
+  bool operator<=(const array<T,N>& x, const array<T,N>& y);    // constexpr in C++20
 template <class T, size_t N>
-  bool operator>=(const array<T,N>& x, const array<T,N>& y);
+  bool operator>=(const array<T,N>& x, const array<T,N>& y);    // constexpr in C++20
 
 template <class T, size_t N >
-  void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // C++17
+  void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20
+
+template <class T, size_t N>
+  constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]);  // C++20
+template <class T, size_t N>
+  constexpr array<remove_cv_t<T>, N> to_array(T (&&a)[N]); // C++20
 
 template <class T> struct tuple_size;
 template <size_t I, class T> struct tuple_element;
 template <class T, size_t N> struct tuple_size<array<T, N>>;
 template <size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>;
-template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept; // constexpr in C++14
-template <size_t I, class T, size_t N> const T& get(const array<T, N>&) noexcept; // constexpr in C++14
-template <size_t I, class T, size_t N> T&& get(array<T, N>&&) noexcept; // constexpr in C++14
+template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept;               // constexpr in C++14
+template <size_t I, class T, size_t N> const T& get(const array<T, N>&) noexcept;   // constexpr in C++14
+template <size_t I, class T, size_t N> T&& get(array<T, N>&&) noexcept;             // constexpr in C++14
 template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexcept; // constexpr in C++14
 
 }  // std
@@ -143,11 +148,12 @@ struct _LIBCPP_TEMPLATE_VIS array
     _Tp __elems_[_Size];
 
     // No explicit construct/copy/destroy for aggregate type
-    _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u) {
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    void fill(const value_type& __u) {
       _VSTD::fill_n(__elems_, _Size, __u);
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
       std::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);
     }
@@ -236,50 +242,71 @@ 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
+
     // No explicit construct/copy/destroy for aggregate type
-    _LIBCPP_INLINE_VISIBILITY void fill(const value_type&) {
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    void fill(const value_type&) {
       static_assert(!is_const<_Tp>::value,
                     "cannot fill zero-sized array of type 'const T'");
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void swap(array&) _NOEXCEPT {
       static_assert(!is_const<_Tp>::value,
                     "cannot swap zero-sized array of type 'const T'");
     }
 
     // iterators:
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     iterator begin() _NOEXCEPT {return iterator(data());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     iterator end() _NOEXCEPT {return iterator(data());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_iterator end() const _NOEXCEPT {return const_iterator(data());}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_iterator cbegin() const _NOEXCEPT {return begin();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_iterator cend() const _NOEXCEPT {return end();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     const_reverse_iterator crend() const _NOEXCEPT {return rend();}
 
     // capacity:
@@ -291,7 +318,7 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
     _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return true;}
 
     // element access:
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     reference operator[](size_type) _NOEXCEPT {
       _LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
       _LIBCPP_UNREACHABLE();
@@ -303,46 +330,41 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
       _LIBCPP_UNREACHABLE();
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     reference at(size_type) {
       __throw_out_of_range("array<T, 0>::at");
       _LIBCPP_UNREACHABLE();
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
     const_reference at(size_type) const {
       __throw_out_of_range("array<T, 0>::at");
       _LIBCPP_UNREACHABLE();
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     reference front() _NOEXCEPT {
       _LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
       _LIBCPP_UNREACHABLE();
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
     const_reference front() const _NOEXCEPT {
       _LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
       _LIBCPP_UNREACHABLE();
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
     reference back() _NOEXCEPT {
       _LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
       _LIBCPP_UNREACHABLE();
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
     const_reference back() const _NOEXCEPT {
       _LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
       _LIBCPP_UNREACHABLE();
     }
-
-    _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_);}
 };
 
 
@@ -404,7 +426,7 @@ operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
 }
 
 template <class _Tp, size_t _Size>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename enable_if
 <
     _Size == 0 ||

diff  --git a/libcxx/include/version b/libcxx/include/version
index 3951693ea826..5a250471a03e 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -21,7 +21,8 @@ __cpp_lib_allocator_traits_is_always_equal              201411L <memory> <scoped
                                                                 <unordered_map> <unordered_set>
 __cpp_lib_any                                           201606L <any>
 __cpp_lib_apply                                         201603L <tuple>
-__cpp_lib_array_constexpr                               201603L <iterator> <array>
+__cpp_lib_array_constexpr                               201811L <iterator> <array>
+                                                        201603L // C++17
 __cpp_lib_as_const                                      201510L <utility>
 __cpp_lib_atomic_is_always_lock_free                    201603L <atomic>
 __cpp_lib_atomic_ref                                    201806L <atomic>
@@ -212,6 +213,8 @@ __cpp_lib_void_t                                        201411L <type_traits>
 #endif
 
 #if _LIBCPP_STD_VER > 17
+# undef  __cpp_lib_array_constexpr
+# define __cpp_lib_array_constexpr                      201811L
 # if !defined(_LIBCPP_HAS_NO_THREADS)
 // #   define __cpp_lib_atomic_ref                         201806L
 # endif

diff  --git a/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp b/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
new file mode 100644
index 000000000000..dd4064bb2fe8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 is an aggregate type.
+
+#include <array>
+#include <type_traits>
+
+template <typename T>
+void tests()
+{
+    // 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; };
+
+int main(int, char**)
+{
+    tests<char>();
+    tests<int>();
+    tests<long>();
+    tests<float>();
+    tests<double>();
+    tests<long double>();
+    tests<NonEmpty>();
+    tests<Empty>();
+
+    return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/array/array.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/deduct.pass.cpp
index 141aafc2a318..42ebef6ddc44 100644
--- a/libcxx/test/std/containers/sequences/array/array.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.cons/deduct.pass.cpp
@@ -30,37 +30,44 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
+constexpr bool tests()
 {
-//  Test the explicit deduction guides
+    //  Test the explicit deduction guides
     {
-    std::array arr{1,2,3};  // array(T, U...)
-    static_assert(std::is_same_v<decltype(arr), std::array<int, 3>>, "");
-    assert(arr[0] == 1);
-    assert(arr[1] == 2);
-    assert(arr[2] == 3);
+        std::array arr{1,2,3};  // array(T, U...)
+        static_assert(std::is_same_v<decltype(arr), std::array<int, 3>>, "");
+        assert(arr[0] == 1);
+        assert(arr[1] == 2);
+        assert(arr[2] == 3);
     }
 
     {
-    const long l1 = 42;
-    std::array arr{1L, 4L, 9L, l1}; // array(T, U...)
-    static_assert(std::is_same_v<decltype(arr)::value_type, long>, "");
-    static_assert(arr.size() == 4, "");
-    assert(arr[0] == 1);
-    assert(arr[1] == 4);
-    assert(arr[2] == 9);
-    assert(arr[3] == l1);
+        const long l1 = 42;
+        std::array arr{1L, 4L, 9L, l1}; // array(T, U...)
+        static_assert(std::is_same_v<decltype(arr)::value_type, long>, "");
+        static_assert(arr.size() == 4, "");
+        assert(arr[0] == 1);
+        assert(arr[1] == 4);
+        assert(arr[2] == 9);
+        assert(arr[3] == l1);
     }
 
-//  Test the implicit deduction guides
-  {
-  std::array<double, 2> source = {4.0, 5.0};
-  std::array arr(source);   // array(array)
-    static_assert(std::is_same_v<decltype(arr), decltype(source)>, "");
-    static_assert(std::is_same_v<decltype(arr), std::array<double, 2>>, "");
-    assert(arr[0] == 4.0);
-    assert(arr[1] == 5.0);
-  }
+    //  Test the implicit deduction guides
+    {
+        std::array<double, 2> source = {4.0, 5.0};
+        std::array arr(source);   // array(array)
+        static_assert(std::is_same_v<decltype(arr), decltype(source)>, "");
+        static_assert(std::is_same_v<decltype(arr), std::array<double, 2>>, "");
+        assert(arr[0] == 4.0);
+        assert(arr[1] == 5.0);
+    }
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    tests();
+    static_assert(tests(), "");
+    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
index 16671e3b5d1b..e73a9671f478 100644
--- a/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp
@@ -19,32 +19,43 @@
 #include "disable_missing_braces_warning.h"
 
 struct NoDefault {
-  NoDefault(int) {}
+    TEST_CONSTEXPR NoDefault(int) { }
 };
 
-int main(int, char**)
+struct Default {
+    TEST_CONSTEXPR Default() { }
+};
+
+TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        C c;
-        assert(c.size() == 3);
+        std::array<Default, 3> array;
+        assert(array.size() == 3);
     }
+
     {
-        typedef double T;
-        typedef std::array<T, 0> C;
-        C c;
-        assert(c.size() == 0);
+        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);
+        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 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 c0e205c8322a..cb9a18298031 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
@@ -23,72 +23,81 @@
 // generated operator would be ill-formed; like in the case of a struct with a
 // const member.
 #if TEST_STD_VER < 11
-#define TEST_NOT_COPY_ASSIGNABLE(T) ((void)0)
+#   define TEST_NOT_COPY_ASSIGNABLE(T) ((void)0)
 #else
-#define TEST_NOT_COPY_ASSIGNABLE(T) static_assert(!std::is_copy_assignable<T>::value, "")
+#   define TEST_NOT_COPY_ASSIGNABLE(T) static_assert(!std::is_copy_assignable<T>::value, "")
 #endif
 
 struct NoDefault {
-  NoDefault(int) {}
+    TEST_CONSTEXPR NoDefault(int) { }
 };
 
-int main(int, char**) {
-  {
-    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 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 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, "");
-  }
-  {
-    // 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 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 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);
-  }
+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 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 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, "");
+    }
+    {
+        // 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 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 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);
+    }
 
+    return true;
+}
 
-  return 0;
+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/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp
index cdc04b18d24f..49437546a8f7 100644
--- 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
@@ -18,12 +18,12 @@
 #include "test_macros.h"
 #include "disable_missing_braces_warning.h"
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
         typedef double T;
         typedef std::array<T, 3> C;
-        C c = {1, 2, 3.5};
+        C const c = {1, 2, 3.5};
         assert(c.size() == 3);
         assert(c[0] == 1);
         assert(c[1] == 2);
@@ -32,23 +32,32 @@ int main(int, char**)
     {
         typedef double T;
         typedef std::array<T, 0> C;
-        C c = {};
+        C const c = {};
         assert(c.size() == 0);
     }
 
     {
         typedef double T;
         typedef std::array<T, 3> C;
-        C c = {1};
+        C const c = {1};
         assert(c.size() == 3.0);
         assert(c[0] == 1);
     }
     {
         typedef int T;
         typedef std::array<T, 1> C;
-        C c = {};
+        C const c = {};
         assert(c.size() == 1);
     }
 
-  return 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.creation/to_array.pass.cpp b/libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp
index d5df96a27005..87165498416b 100644
--- a/libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp
@@ -23,7 +23,8 @@
 #include "test_macros.h"
 #include "MoveOnly.h"
 
-int main(int, char**) {
+constexpr bool tests()
+{
   //  Test deduced type.
   {
     auto arr = std::to_array({1, 2, 3});
@@ -110,13 +111,12 @@ int main(int, char**) {
     assert(arr[0].b == .1);
   }
 
-  // Test constexpr.
-  {
-    constexpr std::array<int, 3> arr = std::to_array({1, 2, 3});
-    static_assert(arr[0] == 1);
-    static_assert(arr[1] == 2);
-    static_assert(arr[2] == 3);
-  }
+  return true;
+}
 
+int main(int, char**)
+{
+  tests();
+  static_assert(tests(), "");
   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 434cbc5fe4e9..a41409f8df1c 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
@@ -21,7 +21,7 @@
 #include "disable_missing_braces_warning.h"
 
 struct NoDefault {
-  NoDefault(int) {}
+    TEST_CONSTEXPR NoDefault(int) { }
 };
 
 #if TEST_STD_VER < 11
@@ -33,7 +33,7 @@ struct natural_alignment {
 };
 #endif
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX17 bool tests()
 {
     {
         typedef double T;
@@ -52,33 +52,49 @@ int main(int, char**)
         LIBCPP_ASSERT(p != nullptr);
     }
     {
-      typedef double T;
-      typedef std::array<const T, 0> C;
-      C c = {{}};
-      const T* p = c.data();
-      static_assert((std::is_same<decltype(c.data()), const T*>::value), "");
-      LIBCPP_ASSERT(p != nullptr);
+        typedef double T;
+        typedef std::array<const T, 0> C;
+        C c = {{}};
+        const T* p = c.data();
+        LIBCPP_ASSERT(p != nullptr);
+        static_assert((std::is_same<decltype(c.data()), const T*>::value), "");
     }
-  {
-#if TEST_STD_VER < 11
-      typedef natural_alignment T;
-#else
-      typedef std::max_align_t T;
-#endif
-      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);
+    {
+        typedef NoDefault T;
+        typedef std::array<T, 0> C;
+        C c = {};
+        T* p = c.data();
+        LIBCPP_ASSERT(p != nullptr);
     }
     {
-      typedef NoDefault T;
-      typedef std::array<T, 0> C;
-      C c = {};
-      T* p = c.data();
-      LIBCPP_ASSERT(p != nullptr);
+        std::array<int, 5> c = {0, 1, 2, 3, 4};
+        assert(c.data() == &c[0]);
+        assert(*c.data() == c[0]);
     }
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 17
+    static_assert(tests(), "");
+#endif
+
+    // Test the alignment of data()
+    {
+#if TEST_STD_VER < 11
+        typedef natural_alignment T;
+#else
+        typedef std::max_align_t T;
+#endif
+        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);
+    }
+    return 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 92828eef0711..0f79237b48a6 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
@@ -21,7 +21,7 @@
 #include "disable_missing_braces_warning.h"
 
 struct NoDefault {
-  NoDefault(int) {}
+    TEST_CONSTEXPR NoDefault(int) { }
 };
 
 #if TEST_STD_VER < 11
@@ -33,7 +33,7 @@ struct natural_alignment {
 };
 #endif
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX17 bool tests()
 {
     {
         typedef double T;
@@ -49,40 +49,45 @@ int main(int, char**)
         typedef std::array<T, 0> C;
         const C c = {};
         const T* p = c.data();
-        (void)p; // to placate scan-build
+        LIBCPP_ASSERT(p != nullptr);
+    }
+    {
+        typedef NoDefault T;
+        typedef std::array<T, 0> C;
+        const C c = {};
+        const T* p = c.data();
+        LIBCPP_ASSERT(p != nullptr);
     }
     {
-      typedef NoDefault T;
-      typedef std::array<T, 0> C;
-      const C c = {};
-      const T* p = c.data();
-      LIBCPP_ASSERT(p != nullptr);
+        std::array<int, 5> const c = {0, 1, 2, 3, 4};
+        assert(c.data() == &c[0]);
+        assert(*c.data() == c[0]);
     }
+
+    return true;
+}
+
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 17
+    static_assert(tests(), "");
+#endif
+
+    // Test the alignment of data()
     {
 #if TEST_STD_VER < 11
-      typedef natural_alignment T;
+        typedef natural_alignment T;
 #else
-      typedef std::max_align_t T;
+        typedef std::max_align_t T;
 #endif
-      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);
-    }
-#if TEST_STD_VER > 14
-    {
-        typedef std::array<int, 5> C;
-        constexpr C c1{0,1,2,3,4};
-        constexpr const C c2{0,1,2,3,4};
-
-        static_assert (  c1.data()  == &c1[0], "");
-        static_assert ( *c1.data()  ==  c1[0], "");
-        static_assert (  c2.data()  == &c2[0], "");
-        static_assert ( *c2.data()  ==  c2[0], "");
+        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);
     }
-#endif
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.fill/fill.pass.cpp b/libcxx/test/std/containers/sequences/array/array.fill/fill.pass.cpp
index f480d17393d4..3a185110a91e 100644
--- a/libcxx/test/std/containers/sequences/array/array.fill/fill.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.fill/fill.pass.cpp
@@ -18,7 +18,7 @@
 #include "test_macros.h"
 #include "disable_missing_braces_warning.h"
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool tests()
 {
     {
         typedef double T;
@@ -30,6 +30,7 @@ int main(int, char**)
         assert(c[1] == 5.5);
         assert(c[2] == 5.5);
     }
+
     {
         typedef double T;
         typedef std::array<T, 0> C;
@@ -37,6 +38,14 @@ int main(int, char**)
         c.fill(5.5);
         assert(c.size() == 0);
     }
+    return true;
+}
 
-  return 0;
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 20
+    static_assert(tests(), "");
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.size/size.pass.cpp b/libcxx/test/std/containers/sequences/array/array.size/size.pass.cpp
index f837bdcf8fb8..e55030015b03 100644
--- a/libcxx/test/std/containers/sequences/array/array.size/size.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.size/size.pass.cpp
@@ -56,5 +56,5 @@ int main(int, char**)
     }
 #endif
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/array/array.special/swap.pass.cpp
index 6c9ed957b836..788f0ed486b8 100644
--- a/libcxx/test/std/containers/sequences/array/array.special/swap.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.special/swap.pass.cpp
@@ -19,10 +19,10 @@
 #include "disable_missing_braces_warning.h"
 
 struct NonSwappable {
-  NonSwappable() {}
+    TEST_CONSTEXPR NonSwappable() { }
 private:
-  NonSwappable(NonSwappable const&);
-  NonSwappable& operator=(NonSwappable const&);
+    NonSwappable(NonSwappable const&);
+    NonSwappable& operator=(NonSwappable const&);
 };
 
 template <class Tp>
@@ -33,9 +33,9 @@ template <class Tp>
 std::false_type can_swap_imp(...);
 
 template <class Tp>
-struct can_swap : std::is_same<decltype(can_swap_imp<Tp>(0)), void> {};
+struct can_swap : std::is_same<decltype(can_swap_imp<Tp>(0)), void> { };
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool tests()
 {
     {
         typedef double T;
@@ -82,5 +82,14 @@ int main(int, char**)
     }
 #endif
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 20
+    static_assert(tests(), "");
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.swap/swap.pass.cpp b/libcxx/test/std/containers/sequences/array/array.swap/swap.pass.cpp
index aac8a13b29a3..1f2d8e7de35f 100644
--- a/libcxx/test/std/containers/sequences/array/array.swap/swap.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.swap/swap.pass.cpp
@@ -21,13 +21,13 @@
 #include "disable_missing_braces_warning.h"
 
 struct NonSwappable {
-  NonSwappable() {}
+    TEST_CONSTEXPR NonSwappable() { }
 private:
-  NonSwappable(NonSwappable const&);
-  NonSwappable& operator=(NonSwappable const&);
+    NonSwappable(NonSwappable const&);
+    NonSwappable& operator=(NonSwappable const&);
 };
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool tests()
 {
     {
         typedef double T;
@@ -89,6 +89,14 @@ int main(int, char**)
 #endif
     }
 
+    return true;
+}
 
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 20
+    static_assert(tests(), "");
+#endif
   return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.tuple/get.pass.cpp b/libcxx/test/std/containers/sequences/array/array.tuple/get.pass.cpp
index 9e94417ac973..1b13d773b0de 100644
--- a/libcxx/test/std/containers/sequences/array/array.tuple/get.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.tuple/get.pass.cpp
@@ -20,41 +20,57 @@
 #include "disable_missing_braces_warning.h"
 
 
-#if TEST_STD_VER > 11
-struct S {
-   std::array<int, 3> a;
-   int k;
-   constexpr S() : a{1,2,3}, k(std::get<2>(a)) {}
-};
-
-constexpr std::array<int, 2> getArr () { return { 3, 4 }; }
-#endif
+template <typename ...T>
+TEST_CONSTEXPR std::array<int, sizeof...(T)> tempArray(T ...args)
+{
+    return {args...};
+}
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        C c = {1, 2, 3.5};
-        std::get<1>(c) = 5.5;
-        assert(c[0] == 1);
-        assert(c[1] == 5.5);
-        assert(c[2] == 3.5);
+        std::array<double, 1> array = {3.3};
+        assert(std::get<0>(array) == 3.3);
+        std::get<0>(array) = 99.1;
+        assert(std::get<0>(array) == 99.1);
     }
-#if TEST_STD_VER > 11
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        constexpr C c = {1, 2, 3.5};
-        static_assert(std::get<0>(c) == 1, "");
-        static_assert(std::get<1>(c) == 2, "");
-        static_assert(std::get<2>(c) == 3.5, "");
+        std::array<double, 2> array = {3.3, 4.4};
+        assert(std::get<0>(array) == 3.3);
+        assert(std::get<1>(array) == 4.4);
+        std::get<0>(array) = 99.1;
+        std::get<1>(array) = 99.2;
+        assert(std::get<0>(array) == 99.1);
+        assert(std::get<1>(array) == 99.2);
     }
     {
-        static_assert(S().k == 3, "");
-        static_assert(std::get<1>(getArr()) == 4, "");
+        std::array<double, 3> array = {3.3, 4.4, 5.5};
+        assert(std::get<0>(array) == 3.3);
+        assert(std::get<1>(array) == 4.4);
+        assert(std::get<2>(array) == 5.5);
+        std::get<1>(array) = 99.2;
+        assert(std::get<0>(array) == 3.3);
+        assert(std::get<1>(array) == 99.2);
+        assert(std::get<2>(array) == 5.5);
     }
-#endif
+    {
+        std::array<double, 1> array = {3.3};
+        static_assert(std::is_same<double&, decltype(std::get<0>(array))>::value, "");
+    }
+    {
+        assert(std::get<0>(tempArray(1, 2, 3)) == 1);
+        assert(std::get<1>(tempArray(1, 2, 3)) == 2);
+        assert(std::get<2>(tempArray(1, 2, 3)) == 3);
+    }
+
+    return true;
+}
 
-  return 0;
+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.tuple/get_const.pass.cpp b/libcxx/test/std/containers/sequences/array/array.tuple/get_const.pass.cpp
index b22a76185b6f..3c1941c031fb 100644
--- a/libcxx/test/std/containers/sequences/array/array.tuple/get_const.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.tuple/get_const.pass.cpp
@@ -19,26 +19,36 @@
 // Disable the missing braces warning for this reason.
 #include "disable_missing_braces_warning.h"
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        const C c = {1, 2, 3.5};
-        assert(std::get<0>(c) == 1);
-        assert(std::get<1>(c) == 2);
-        assert(std::get<2>(c) == 3.5);
+        std::array<double, 1> const array = {3.3};
+        assert(std::get<0>(array) == 3.3);
     }
-#if TEST_STD_VER > 11
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        constexpr const C c = {1, 2, 3.5};
-        static_assert(std::get<0>(c) == 1, "");
-        static_assert(std::get<1>(c) == 2, "");
-        static_assert(std::get<2>(c) == 3.5, "");
+        std::array<double, 2> const array = {3.3, 4.4};
+        assert(std::get<0>(array) == 3.3);
+        assert(std::get<1>(array) == 4.4);
+    }
+    {
+        std::array<double, 3> const array = {3.3, 4.4, 5.5};
+        assert(std::get<0>(array) == 3.3);
+        assert(std::get<1>(array) == 4.4);
+        assert(std::get<2>(array) == 5.5);
+    }
+    {
+        std::array<double, 1> const array = {3.3};
+        static_assert(std::is_same<double const&, decltype(std::get<0>(array))>::value, "");
     }
-#endif
 
-  return 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.tuple/get_const_rv.pass.cpp b/libcxx/test/std/containers/sequences/array/array.tuple/get_const_rv.pass.cpp
index ce8fc4fd3651..346978008c84 100644
--- a/libcxx/test/std/containers/sequences/array/array.tuple/get_const_rv.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.tuple/get_const_rv.pass.cpp
@@ -28,25 +28,25 @@ int main(int, char**)
 {
 
     {
-    typedef std::unique_ptr<double> T;
-    typedef std::array<T, 1> C;
-    const C c = {std::unique_ptr<double>(new double(3.5))};
-    static_assert(std::is_same<const T&&, decltype(std::get<0>(std::move(c)))>::value, "");
-    static_assert(noexcept(std::get<0>(std::move(c))), "");
-    const T&& t = std::get<0>(std::move(c));
-    assert(*t == 3.5);
+        typedef std::unique_ptr<double> T;
+        typedef std::array<T, 1> C;
+        const C c = {std::unique_ptr<double>(new double(3.5))};
+        static_assert(std::is_same<const T&&, decltype(std::get<0>(std::move(c)))>::value, "");
+        static_assert(noexcept(std::get<0>(std::move(c))), "");
+        const T&& t = std::get<0>(std::move(c));
+        assert(*t == 3.5);
     }
 
-#if TEST_STD_VER > 11
+#if TEST_STD_VER >= 14
     {
-    typedef double T;
-    typedef std::array<T, 3> C;
-    constexpr const C c = {1, 2, 3.5};
-    static_assert(std::get<0>(std::move(c)) == 1, "");
-    static_assert(std::get<1>(std::move(c)) == 2, "");
-    static_assert(std::get<2>(std::move(c)) == 3.5, "");
+        typedef double T;
+        typedef std::array<T, 3> C;
+        constexpr const C c = {1, 2, 3.5};
+        static_assert(std::get<0>(std::move(c)) == 1, "");
+        static_assert(std::get<1>(std::move(c)) == 2, "");
+        static_assert(std::get<2>(std::move(c)) == 3.5, "");
     }
 #endif
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.tuple/get_rv.pass.cpp b/libcxx/test/std/containers/sequences/array/array.tuple/get_rv.pass.cpp
index d1d8b28f4c9d..e557c19ba2a4 100644
--- a/libcxx/test/std/containers/sequences/array/array.tuple/get_rv.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.tuple/get_rv.pass.cpp
@@ -33,5 +33,5 @@ int main(int, char**)
         assert(*t == 3.5);
     }
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/array.tuple/tuple_element.fail.cpp b/libcxx/test/std/containers/sequences/array/array.tuple/tuple_element.fail.cpp
index a4fbd3ab4c21..cde4ba7c759f 100644
--- a/libcxx/test/std/containers/sequences/array/array.tuple/tuple_element.fail.cpp
+++ b/libcxx/test/std/containers/sequences/array/array.tuple/tuple_element.fail.cpp
@@ -18,7 +18,6 @@
 #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 "disable_missing_braces_warning.h"

diff  --git a/libcxx/test/std/containers/sequences/array/at.pass.cpp b/libcxx/test/std/containers/sequences/array/at.pass.cpp
index 0454643541c9..ed4ab80fb0cd 100644
--- a/libcxx/test/std/containers/sequences/array/at.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/at.pass.cpp
@@ -8,10 +8,7 @@
 
 // <array>
 
-// reference operator[] (size_type)
-// const_reference operator[] (size_type); // constexpr in C++14
-// reference at (size_type)
-// const_reference at (size_type); // constexpr in C++14
+// reference at (size_type); // constexpr in C++17
 
 #include <array>
 #include <cassert>
@@ -26,100 +23,91 @@
 // Disable the missing braces warning for this reason.
 #include "disable_missing_braces_warning.h"
 
-#if TEST_STD_VER > 14
-constexpr bool check_idx( size_t idx, double val )
-{
-    std::array<double, 3> arr = {1, 2, 3.5};
-    return arr.at(idx) == val;
-}
-#endif
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX17 bool tests()
 {
     {
         typedef double T;
         typedef std::array<T, 3> C;
         C c = {1, 2, 3.5};
-        C::reference r1 = c.at(0);
+        typename C::reference r1 = c.at(0);
         assert(r1 == 1);
         r1 = 5.5;
-        assert(c.front() == 5.5);
+        assert(c[0] == 5.5);
 
-        C::reference r2 = c.at(2);
+        typename C::reference r2 = c.at(2);
         assert(r2 == 3.5);
         r2 = 7.5;
-        assert(c.back() == 7.5);
-
-#ifndef TEST_HAS_NO_EXCEPTIONS
-        try
-        {
-            TEST_IGNORE_NODISCARD  c.at(3);
-            assert(false);
-        }
-        catch (const std::out_of_range &) {}
-#endif
+        assert(c[2] == 7.5);
     }
+    return true;
+}
+
+void test_exceptions()
+{
 #ifndef TEST_HAS_NO_EXCEPTIONS
     {
-        typedef double T;
-        typedef std::array<T, 0> C;
-        C c = {};
-        C const& cc = c;
-        try
-        {
-            TEST_IGNORE_NODISCARD  c.at(0);
+        std::array<int, 4> array = {1, 2, 3, 4};
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(4);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
             assert(false);
         }
-        catch (const std::out_of_range &) {}
-        try
-        {
-            TEST_IGNORE_NODISCARD  cc.at(0);
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(5);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
             assert(false);
         }
-        catch (const std::out_of_range &) {}
-    }
-#endif
-    {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        const C c = {1, 2, 3.5};
-        C::const_reference r1 = c.at(0);
-        assert(r1 == 1);
 
-        C::const_reference r2 = c.at(2);
-        assert(r2 == 3.5);
+        try {
+            TEST_IGNORE_NODISCARD array.at(6);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
 
-#ifndef TEST_HAS_NO_EXCEPTIONS
-        try
-        {
-            TEST_IGNORE_NODISCARD  c.at(3);
+        try {
+            TEST_IGNORE_NODISCARD array.at(-1);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
             assert(false);
         }
-        catch (const std::out_of_range &) {}
-#endif
     }
 
-#if TEST_STD_VER > 11
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        constexpr C c = {1, 2, 3.5};
-
-        constexpr T t1 = c.at(0);
-        static_assert (t1 == 1, "");
+        std::array<int, 0> array = {};
 
-        constexpr T t2 = c.at(2);
-        static_assert (t2 == 3.5, "");
+        try {
+            TEST_IGNORE_NODISCARD array.at(0);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
     }
 #endif
+}
 
-#if TEST_STD_VER > 14
-    {
-        static_assert (check_idx(0, 1), "");
-        static_assert (check_idx(1, 2), "");
-        static_assert (check_idx(2, 3.5), "");
-    }
-#endif
+int main(int, char**)
+{
+    tests();
+    test_exceptions();
 
-  return 0;
+#if TEST_STD_VER >= 17
+    static_assert(tests(), "");
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/at_const.pass.cpp b/libcxx/test/std/containers/sequences/array/at_const.pass.cpp
new file mode 100644
index 000000000000..d79c5054ae83
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/at_const.pass.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// const_reference at (size_type) const; // constexpr in C++14
+
+#include <array>
+#include <cassert>
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+#include <stdexcept>
+#endif
+
+#include "test_macros.h"
+
+// std::array is explicitly allowed to be initialized with A a = { init-list };.
+// Disable the missing braces warning for this reason.
+#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};
+        typename C::const_reference r1 = c.at(0);
+        assert(r1 == 1);
+
+        typename C::const_reference r2 = c.at(2);
+        assert(r2 == 3.5);
+    }
+    return true;
+}
+
+void test_exceptions()
+{
+#ifndef TEST_HAS_NO_EXCEPTIONS
+    {
+        std::array<int, 4> const array = {1, 2, 3, 4};
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(4);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(5);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(6);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(-1);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
+    }
+
+    {
+        std::array<int, 0> array = {};
+
+        try {
+            TEST_IGNORE_NODISCARD array.at(0);
+            assert(false);
+        } catch (std::out_of_range const&) {
+            // pass
+        } catch (...) {
+            assert(false);
+        }
+    }
+#endif
+}
+
+int main(int, char**)
+{
+    tests();
+    test_exceptions();
+
+#if TEST_STD_VER >= 14
+    static_assert(tests(), "");
+#endif
+    return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/array/begin.pass.cpp b/libcxx/test/std/containers/sequences/array/begin.pass.cpp
deleted file mode 100644
index 7b26d231dbdd..000000000000
--- a/libcxx/test/std/containers/sequences/array/begin.pass.cpp
+++ /dev/null
@@ -1,53 +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>
-
-// iterator begin();
-
-#include <array>
-#include <cassert>
-
-#include "test_macros.h"
-
-// std::array is explicitly allowed to be initialized with A a = { init-list };.
-// Disable the missing braces warning for this reason.
-#include "disable_missing_braces_warning.h"
-
-struct NoDefault {
-  NoDefault(int) {}
-};
-
-
-int main(int, char**)
-{
-    {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        C c = {1, 2, 3.5};
-        C::iterator i;
-        i = c.begin();
-        assert(*i == 1);
-        assert(&*i == c.data());
-        *i = 5.5;
-        assert(c[0] == 5.5);
-    }
-    {
-      typedef NoDefault T;
-      typedef std::array<T, 0> C;
-      C c = {};
-      C::iterator ib, ie;
-      ib = c.begin();
-      ie = c.end();
-      assert(ib == ie);
-      LIBCPP_ASSERT(ib != nullptr);
-      LIBCPP_ASSERT(ie != nullptr);
-    }
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/sequences/array/compare.pass.cpp b/libcxx/test/std/containers/sequences/array/compare.pass.cpp
index c05dd19405bf..c89216c8bb87 100644
--- a/libcxx/test/std/containers/sequences/array/compare.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/compare.pass.cpp
@@ -8,17 +8,15 @@
 
 // <array>
 
-//  These are all constexpr in C++20
-// bool operator==(array<T, N> const&, array<T, N> const&);
-// bool operator!=(array<T, N> const&, array<T, N> const&);
-// bool operator<(array<T, N> const&, array<T, N> const&);
-// bool operator<=(array<T, N> const&, array<T, N> const&);
-// bool operator>(array<T, N> const&, array<T, N> const&);
-// bool operator>=(array<T, N> const&, array<T, N> const&);
+// bool operator==(array<T, N> const&, array<T, N> const&);   // constexpr in C++20
+// bool operator!=(array<T, N> const&, array<T, N> const&);   // constexpr in C++20
+// bool operator<(array<T, N> const&, array<T, N> const&);    // constexpr in C++20
+// bool operator<=(array<T, N> const&, array<T, N> const&);   // constexpr in C++20
+// bool operator>(array<T, N> const&, array<T, N> const&);    // constexpr in C++20
+// bool operator>=(array<T, N> const&, array<T, N> const&);   // constexpr in C++20
 
 
 #include <array>
-#include <vector>
 #include <cassert>
 
 #include "test_macros.h"
@@ -28,36 +26,33 @@
 // Disable the missing braces warning for this reason.
 #include "disable_missing_braces_warning.h"
 
+TEST_CONSTEXPR_CXX20 bool tests()
+{
+    {
+        typedef std::array<int, 3> C;
+        C c1 = {1, 2, 3};
+        C c2 = {1, 2, 3};
+        C c3 = {3, 2, 1};
+        C c4 = {1, 2, 1};
+        assert(testComparisons6(c1, c2, true, false));
+        assert(testComparisons6(c1, c3, false, true));
+        assert(testComparisons6(c1, c4, false, false));
+    }
+    {
+        typedef std::array<int, 0> C;
+        C c1 = {};
+        C c2 = {};
+        assert(testComparisons6(c1, c2, true, false));
+    }
+
+    return true;
+}
+
 int main(int, char**)
 {
-  {
-    typedef int T;
-    typedef std::array<T, 3> C;
-    C c1 = {1, 2, 3};
-    C c2 = {1, 2, 3};
-    C c3 = {3, 2, 1};
-    C c4 = {1, 2, 1};
-    assert(testComparisons6(c1, c2, true, false));
-    assert(testComparisons6(c1, c3, false, true));
-    assert(testComparisons6(c1, c4, false, false));
-  }
-  {
-    typedef int T;
-    typedef std::array<T, 0> C;
-    C c1 = {};
-    C c2 = {};
-    assert(testComparisons6(c1, c2, true, false));
-  }
-
-#if TEST_STD_VER > 17
-  {
-  constexpr std::array<int, 3> a1 = {1, 2, 3};
-  constexpr std::array<int, 3> a2 = {2, 3, 4};
-  static_assert(testComparisons6(a1, a1, true, false), "");
-  static_assert(testComparisons6(a1, a2, false, true), "");
-  static_assert(testComparisons6(a2, a1, false, false), "");
-  }
+    tests();
+#if TEST_STD_VER >= 20
+    static_assert(tests(), "");
 #endif
-
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/contiguous.pass.cpp b/libcxx/test/std/containers/sequences/array/contiguous.pass.cpp
index 41a7153e88d4..9589e6364394 100644
--- a/libcxx/test/std/containers/sequences/array/contiguous.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/contiguous.pass.cpp
@@ -15,20 +15,33 @@
 
 #include "test_macros.h"
 
-template <class C>
-void test_contiguous ( const C &c )
+template <class Container>
+TEST_CONSTEXPR_CXX14 void assert_contiguous(Container const& c)
 {
-    for ( size_t i = 0; i < c.size(); ++i )
-        assert ( *(c.begin() + i) == *(std::addressof(*c.begin()) + i));
+    for (size_t i = 0; i < c.size(); ++i)
+        assert(*(c.begin() + i) == *(std::addressof(*c.begin()) + i));
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX17 bool tests()
 {
-    {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        test_contiguous (C());
-    }
+    assert_contiguous(std::array<double, 0>());
+    assert_contiguous(std::array<double, 1>());
+    assert_contiguous(std::array<double, 2>());
+    assert_contiguous(std::array<double, 3>());
+
+    assert_contiguous(std::array<char, 0>());
+    assert_contiguous(std::array<char, 1>());
+    assert_contiguous(std::array<char, 2>());
+    assert_contiguous(std::array<char, 3>());
+
+    return true;
+}
 
-  return 0;
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 17 // begin() & friends are constexpr in >= C++17 only
+    static_assert(tests(), "");
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/empty.pass.cpp b/libcxx/test/std/containers/sequences/array/empty.pass.cpp
index a17aa50c5b21..8b61575c2e73 100644
--- a/libcxx/test/std/containers/sequences/array/empty.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/empty.pass.cpp
@@ -10,28 +10,45 @@
 
 // class array
 
-// bool empty() const noexcept;
+// constexpr bool empty() const noexcept;
 
 #include <array>
 #include <cassert>
 
 #include "test_macros.h"
-#include "min_allocator.h"
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
-    typedef std::array<int, 2> C;
-    C c;
-    ASSERT_NOEXCEPT(c.empty());
-    assert(!c.empty());
+        typedef std::array<int, 2> C;
+        C c = {};
+        ASSERT_NOEXCEPT(c.empty());
+        assert(!c.empty());
+    }
+    {
+        typedef std::array<int, 0> C;
+        C c = {};
+        ASSERT_NOEXCEPT(c.empty());
+        assert(c.empty());
     }
+
+    return true;
+}
+
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 14
+    static_assert(tests(), "");
+#endif
+
+#if TEST_STD_VER >= 11
+    // Sanity check for constexpr in C++11
     {
-    typedef std::array<int, 0> C;
-    C c;
-    ASSERT_NOEXCEPT(c.empty());
-    assert( c.empty());
+        constexpr std::array<int, 3> array = {};
+        static_assert(!array.empty(), "");
     }
+#endif
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/front_back.pass.cpp b/libcxx/test/std/containers/sequences/array/front_back.pass.cpp
index 5e0cb08ede07..18985e90a89e 100644
--- a/libcxx/test/std/containers/sequences/array/front_back.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/front_back.pass.cpp
@@ -8,10 +8,8 @@
 
 // <array>
 
-// reference front();       // constexpr in C++17
-// reference back();        // constexpr in C++17
-// const_reference front(); // constexpr in C++14
-// const_reference back();  // constexpr in C++14
+// reference front();  // constexpr in C++17
+// reference back();   // constexpr in C++17
 
 #include <array>
 #include <cassert>
@@ -22,21 +20,8 @@
 // Disable the missing braces warning for this reason.
 #include "disable_missing_braces_warning.h"
 
-#if TEST_STD_VER > 14
-constexpr bool check_front( double val )
-{
-    std::array<double, 3> arr = {1, 2, 3.5};
-    return arr.front() == val;
-}
 
-constexpr bool check_back( double val )
-{
-    std::array<double, 3> arr = {1, 2, 3.5};
-    return arr.back() == val;
-}
-#endif
-
-int main(int, char**)
+TEST_CONSTEXPR_CXX17 bool tests()
 {
     {
         typedef double T;
@@ -55,74 +40,39 @@ int main(int, char**)
     }
     {
         typedef double T;
-        typedef std::array<T, 3> C;
-        const C c = {1, 2, 3.5};
-        C::const_reference r1 = c.front();
-        assert(r1 == 1);
-
-        C::const_reference r2 = c.back();
-        assert(r2 == 3.5);
-    }
-    {
-      typedef double T;
-      typedef std::array<T, 0> C;
-      C c = {};
-      C const& cc = c;
-      ASSERT_SAME_TYPE(decltype( c.back()), typename C::reference);
-      ASSERT_SAME_TYPE(decltype(cc.back()), typename C::const_reference);
-      LIBCPP_ASSERT_NOEXCEPT(    c.back());
-      LIBCPP_ASSERT_NOEXCEPT(   cc.back());
-      ASSERT_SAME_TYPE(decltype( c.front()), typename C::reference);
-      ASSERT_SAME_TYPE(decltype(cc.front()), typename C::const_reference);
-      LIBCPP_ASSERT_NOEXCEPT(    c.front());
-      LIBCPP_ASSERT_NOEXCEPT(   cc.front());
-      if (c.size() > (0)) { // always false
-        TEST_IGNORE_NODISCARD c.front();
-        TEST_IGNORE_NODISCARD c.back();
-        TEST_IGNORE_NODISCARD cc.front();
-        TEST_IGNORE_NODISCARD cc.back();
-      }
+        typedef std::array<T, 0> C;
+        C c = {};
+        ASSERT_SAME_TYPE(decltype(c.back()), C::reference);
+        LIBCPP_ASSERT_NOEXCEPT(c.back());
+        ASSERT_SAME_TYPE(decltype(c.front()), C::reference);
+        LIBCPP_ASSERT_NOEXCEPT(c.front());
+        if (c.size() > (0)) { // always false
+            TEST_IGNORE_NODISCARD c.front();
+            TEST_IGNORE_NODISCARD c.back();
+        }
     }
-    {
-      typedef double T;
-      typedef std::array<const T, 0> C;
-      C c = {{}};
-      C const& cc = c;
-      ASSERT_SAME_TYPE(decltype( c.back()), typename C::reference);
-      ASSERT_SAME_TYPE(decltype(cc.back()), typename C::const_reference);
-      LIBCPP_ASSERT_NOEXCEPT(    c.back());
-      LIBCPP_ASSERT_NOEXCEPT(   cc.back());
-      ASSERT_SAME_TYPE(decltype( c.front()), typename C::reference);
-      ASSERT_SAME_TYPE(decltype(cc.front()), typename C::const_reference);
-      LIBCPP_ASSERT_NOEXCEPT(    c.front());
-      LIBCPP_ASSERT_NOEXCEPT(   cc.front());
-      if (c.size() > (0)) {
-        TEST_IGNORE_NODISCARD c.front();
-        TEST_IGNORE_NODISCARD c.back();
-        TEST_IGNORE_NODISCARD cc.front();
-        TEST_IGNORE_NODISCARD cc.back();
-      }
-    }
-#if TEST_STD_VER > 11
     {
         typedef double T;
-        typedef std::array<T, 3> C;
-        constexpr C c = {1, 2, 3.5};
-
-        constexpr T t1 = c.front();
-        static_assert (t1 == 1, "");
-
-        constexpr T t2 = c.back();
-        static_assert (t2 == 3.5, "");
+        typedef std::array<const T, 0> C;
+        C c = {};
+        ASSERT_SAME_TYPE(decltype( c.back()), C::reference);
+        LIBCPP_ASSERT_NOEXCEPT(    c.back());
+        ASSERT_SAME_TYPE(decltype( c.front()), C::reference);
+        LIBCPP_ASSERT_NOEXCEPT(    c.front());
+        if (c.size() > (0)) {
+            TEST_IGNORE_NODISCARD c.front();
+            TEST_IGNORE_NODISCARD c.back();
+        }
     }
-#endif
 
-#if TEST_STD_VER > 14
-    {
-        static_assert (check_front(1),   "");
-        static_assert (check_back (3.5), "");
-    }
-#endif
+    return true;
+}
 
-  return 0;
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 17
+    static_assert(tests(), "");
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/front_back_const.pass.cpp b/libcxx/test/std/containers/sequences/array/front_back_const.pass.cpp
new file mode 100644
index 000000000000..af519127bed5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/front_back_const.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// const_reference front() const; // constexpr in C++14
+// const_reference back() const;  // constexpr in C++14
+
+#include <array>
+#include <cassert>
+
+#include "test_macros.h"
+
+// std::array is explicitly allowed to be initialized with A a = { init-list };.
+// Disable the missing braces warning for this reason.
+#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};
+        C::const_reference r1 = c.front();
+        assert(r1 == 1);
+
+        C::const_reference r2 = c.back();
+        assert(r2 == 3.5);
+    }
+    {
+        typedef double T;
+        typedef std::array<T, 0> C;
+        C const c = {};
+        ASSERT_SAME_TYPE(decltype(c.back()), C::const_reference);
+        LIBCPP_ASSERT_NOEXCEPT(c.back());
+        ASSERT_SAME_TYPE(decltype(c.front()), C::const_reference);
+        LIBCPP_ASSERT_NOEXCEPT(c.front());
+        if (c.size() > (0)) { // always false
+            TEST_IGNORE_NODISCARD c.front();
+            TEST_IGNORE_NODISCARD c.back();
+        }
+    }
+    {
+        typedef double T;
+        typedef std::array<const T, 0> C;
+        C const c = {};
+        ASSERT_SAME_TYPE(decltype(c.back()), C::const_reference);
+        LIBCPP_ASSERT_NOEXCEPT(c.back());
+        ASSERT_SAME_TYPE(decltype(c.front()), C::const_reference);
+        LIBCPP_ASSERT_NOEXCEPT(c.front());
+        if (c.size() > (0)) {
+            TEST_IGNORE_NODISCARD c.front();
+            TEST_IGNORE_NODISCARD c.back();
+        }
+    }
+
+    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/indexing.pass.cpp b/libcxx/test/std/containers/sequences/array/indexing.pass.cpp
index 0df672d8b019..6b5d8486fda2 100644
--- a/libcxx/test/std/containers/sequences/array/indexing.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/indexing.pass.cpp
@@ -8,11 +8,8 @@
 
 // <array>
 
-// reference operator[] (size_type)
-// const_reference operator[] (size_type); // constexpr in C++14
-// reference at (size_type)
-// const_reference at (size_type); // constexpr in C++14
-// Libc++ marks these as noexcept
+// reference operator[](size_type); // constexpr in C++17
+// Libc++ marks it as noexcept
 
 #include <array>
 #include <cassert>
@@ -23,15 +20,8 @@
 // Disable the missing braces warning for this reason.
 #include "disable_missing_braces_warning.h"
 
-#if TEST_STD_VER > 14
-constexpr bool check_idx( size_t idx, double val )
-{
-    std::array<double, 3> arr = {1, 2, 3.5};
-    return arr[idx] == val;
-}
-#endif
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX17 bool tests()
 {
     {
         typedef double T;
@@ -49,72 +39,41 @@ int main(int, char**)
         r2 = 7.5;
         assert(c.back() == 7.5);
     }
+
+    // Test operator[] "works" on zero sized arrays
     {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        const C c = {1, 2, 3.5};
-        LIBCPP_ASSERT_NOEXCEPT(c[0]);
-        ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
-        C::const_reference r1 = c[0];
-        assert(r1 == 1);
-        C::const_reference r2 = c[2];
-        assert(r2 == 3.5);
-    }
-    { // Test operator[] "works" on zero sized arrays
-        typedef double T;
-        typedef std::array<T, 0> C;
-        C c = {};
-        C const& cc = c;
-        LIBCPP_ASSERT_NOEXCEPT(c[0]);
-        LIBCPP_ASSERT_NOEXCEPT(cc[0]);
-        ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
-        ASSERT_SAME_TYPE(C::const_reference, decltype(cc[0]));
-        if (c.size() > (0)) { // always false
-          C::reference r1 = c[0];
-          C::const_reference r2 = cc[0];
-          ((void)r1);
-          ((void)r2);
+        {
+            typedef double T;
+            typedef std::array<T, 0> C;
+            C c = {};
+            LIBCPP_ASSERT_NOEXCEPT(c[0]);
+            ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
+            if (c.size() > (0)) { // always false
+              C::reference r = c[0];
+              (void)r;
+            }
         }
-    }
-    { // Test operator[] "works" on zero sized arrays
-        typedef double T;
-        typedef std::array<const T, 0> C;
-        C c = {{}};
-        C const& cc = c;
-        LIBCPP_ASSERT_NOEXCEPT(c[0]);
-        LIBCPP_ASSERT_NOEXCEPT(cc[0]);
-        ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
-        ASSERT_SAME_TYPE(C::const_reference, decltype(cc[0]));
-        if (c.size() > (0)) { // always false
-          C::reference r1 = c[0];
-          C::const_reference r2 = cc[0];
-          ((void)r1);
-          ((void)r2);
+        {
+            typedef double T;
+            typedef std::array<const T, 0> C;
+            C c = {};
+            LIBCPP_ASSERT_NOEXCEPT(c[0]);
+            ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
+            if (c.size() > (0)) { // always false
+              C::reference r = c[0];
+              (void)r;
+            }
         }
     }
-#if TEST_STD_VER > 11
-    {
-        typedef double T;
-        typedef std::array<T, 3> C;
-        constexpr C c = {1, 2, 3.5};
-        LIBCPP_ASSERT_NOEXCEPT(c[0]);
-        ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
 
-        constexpr T t1 = c[0];
-        static_assert (t1 == 1, "");
-
-        constexpr T t2 = c[2];
-        static_assert (t2 == 3.5, "");
-    }
-#endif
+    return true;
+}
 
-#if TEST_STD_VER > 14
-    {
-        static_assert (check_idx(0, 1), "");
-        static_assert (check_idx(1, 2), "");
-        static_assert (check_idx(2, 3.5), "");
-    }
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 17
+    static_assert(tests(), "");
 #endif
-
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/indexing_const.pass.cpp b/libcxx/test/std/containers/sequences/array/indexing_const.pass.cpp
new file mode 100644
index 000000000000..3f34dfe7dd32
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/indexing_const.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// const_reference operator[](size_type) const; // constexpr in C++14
+// Libc++ marks it as noexcept
+
+#include <array>
+#include <cassert>
+
+#include "test_macros.h"
+
+// std::array is explicitly allowed to be initialized with A a = { init-list };.
+// Disable the missing braces warning for this reason.
+#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};
+        LIBCPP_ASSERT_NOEXCEPT(c[0]);
+        ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
+        C::const_reference r1 = c[0];
+        assert(r1 == 1);
+        C::const_reference r2 = c[2];
+        assert(r2 == 3.5);
+    }
+    // Test operator[] "works" on zero sized arrays
+    {
+        {
+            typedef double T;
+            typedef std::array<T, 0> C;
+            C const c = {};
+            LIBCPP_ASSERT_NOEXCEPT(c[0]);
+            ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
+            if (c.size() > (0)) { // always false
+                C::const_reference r = c[0];
+                (void)r;
+            }
+        }
+        {
+            typedef double T;
+            typedef std::array<T const, 0> C;
+            C const c = {};
+            LIBCPP_ASSERT_NOEXCEPT(c[0]);
+            ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
+            if (c.size() > (0)) { // always false
+              C::const_reference r = c[0];
+              (void)r;
+            }
+        }
+    }
+
+    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/iterators.pass.cpp b/libcxx/test/std/containers/sequences/array/iterators.pass.cpp
index 71fad183ff73..39d8a1a5dfa4 100644
--- a/libcxx/test/std/containers/sequences/array/iterators.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/iterators.pass.cpp
@@ -8,7 +8,20 @@
 
 // <array>
 
-// iterator, const_iterator
+// iterator begin() noexcept;                         // constexpr in C++17
+// const_iterator begin() const noexcept;             // constexpr in C++17
+// iterator end() noexcept;                           // constexpr in C++17
+// const_iterator end() const noexcept;               // constexpr in C++17
+//
+// reverse_iterator rbegin() noexcept;                // constexpr in C++17
+// const_reverse_iterator rbegin() const noexcept;    // constexpr in C++17
+// reverse_iterator rend() noexcept;                  // constexpr in C++17
+// const_reverse_iterator rend() const noexcept;      // constexpr in C++17
+//
+// const_iterator cbegin() const noexcept;            // constexpr in C++17
+// const_iterator cend() const noexcept;              // constexpr in C++17
+// const_reverse_iterator crbegin() const noexcept;   // constexpr in C++17
+// const_reverse_iterator crend() const noexcept;     // constexpr in C++17
 
 #include <array>
 #include <iterator>
@@ -20,127 +33,157 @@
 // Disable the missing braces warning for this reason.
 #include "disable_missing_braces_warning.h"
 
-int main(int, char**)
+struct NoDefault {
+    TEST_CONSTEXPR NoDefault(int) { }
+};
+
+TEST_CONSTEXPR_CXX17 bool tests()
 {
     {
-    typedef std::array<int, 5> C;
-    C c;
-    C::iterator i;
-    i = c.begin();
-    C::const_iterator j;
-    j = c.cbegin();
-    assert(i == j);
+        typedef std::array<int, 5> C;
+        C array = {};
+        typename C::iterator i = array.begin();
+        typename C::const_iterator j = array.cbegin();
+        assert(i == j);
+    }
+    {
+        typedef std::array<int, 0> C;
+        C array = {};
+        typename C::iterator i = array.begin();
+        typename C::const_iterator j = array.cbegin();
+        assert(i == j);
+        LIBCPP_ASSERT(i != nullptr);
+        LIBCPP_ASSERT(j != nullptr);
+    }
+
+    {
+        typedef std::array<int, 0> C;
+        C array = {};
+        typename C::iterator i = array.begin();
+        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;
+        C array = {1};
+        typename C::iterator i = array.begin();
+        assert(*i == 1);
+        assert(&*i == array.data());
+        *i = 99;
+        assert(array[0] == 99);
     }
     {
-    typedef std::array<int, 0> C;
-    C c;
-    C::iterator i;
-    i = c.begin();
-    C::const_iterator j;
-    j = c.cbegin();
-    assert(i == j);
+        typedef std::array<int, 2> C;
+        C array = {1, 2};
+        typename C::iterator i = array.begin();
+        assert(*i == 1);
+        assert(&*i == array.data());
+        *i = 99;
+        assert(array[0] == 99);
+        assert(array[1] == 2);
+    }
+    {
+        typedef std::array<double, 3> C;
+        C array = {1, 2, 3.5};
+        typename C::iterator i = array.begin();
+        assert(*i == 1);
+        assert(&*i == array.data());
+        *i = 5.5;
+        assert(array[0] == 5.5);
+        assert(array[1] == 2.0);
+    }
+    {
+        typedef std::array<NoDefault, 0> C;
+        C array = {};
+        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 > 11
+#if TEST_STD_VER >= 14
     { // N3644 testing
         {
-        typedef std::array<int, 5> C;
-        C::iterator ii1{}, ii2{};
-        C::iterator ii4 = ii1;
-        C::const_iterator cii{};
-        assert ( ii1 == ii2 );
-        assert ( ii1 == ii4 );
-        assert ( ii1 == cii );
-
-        assert ( !(ii1 != ii2 ));
-        assert ( !(ii1 != cii ));
-
-        C c;
-        assert ( c.begin()   == std::begin(c));
-        assert ( c.cbegin()  == std::cbegin(c));
-        assert ( c.rbegin()  == std::rbegin(c));
-        assert ( c.crbegin() == std::crbegin(c));
-        assert ( c.end()     == std::end(c));
-        assert ( c.cend()    == std::cend(c));
-        assert ( c.rend()    == std::rend(c));
-        assert ( c.crend()   == std::crend(c));
-
-        assert ( std::begin(c)   != std::end(c));
-        assert ( std::rbegin(c)  != std::rend(c));
-        assert ( std::cbegin(c)  != std::cend(c));
-        assert ( std::crbegin(c) != std::crend(c));
+            typedef std::array<int, 5> C;
+            C::iterator ii1{}, ii2{};
+            C::iterator ii4 = ii1;
+            C::const_iterator cii{};
+            assert(ii1 == ii2);
+            assert(ii1 == ii4);
+            assert(ii1 == cii);
+
+            assert(!(ii1 != ii2));
+            assert(!(ii1 != cii));
+
+            C c = {};
+            assert(c.begin()   == std::begin(c));
+            assert(c.cbegin()  == std::cbegin(c));
+            assert(c.rbegin()  == std::rbegin(c));
+            assert(c.crbegin() == std::crbegin(c));
+            assert(c.end()     == std::end(c));
+            assert(c.cend()    == std::cend(c));
+            assert(c.rend()    == std::rend(c));
+            assert(c.crend()   == std::crend(c));
+
+            assert(std::begin(c)   != std::end(c));
+            assert(std::rbegin(c)  != std::rend(c));
+            assert(std::cbegin(c)  != std::cend(c));
+            assert(std::crbegin(c) != std::crend(c));
         }
         {
-        typedef std::array<int, 0> C;
-        C::iterator ii1{}, ii2{};
-        C::iterator ii4 = ii1;
-        C::const_iterator cii{};
-        assert ( ii1 == ii2 );
-        assert ( ii1 == ii4 );
-
-        assert (!(ii1 != ii2 ));
-
-        assert ( (ii1 == cii ));
-        assert ( (cii == ii1 ));
-        assert (!(ii1 != cii ));
-        assert (!(cii != ii1 ));
-        assert (!(ii1 <  cii ));
-        assert (!(cii <  ii1 ));
-        assert ( (ii1 <= cii ));
-        assert ( (cii <= ii1 ));
-        assert (!(ii1 >  cii ));
-        assert (!(cii >  ii1 ));
-        assert ( (ii1 >= cii ));
-        assert ( (cii >= ii1 ));
-        assert (cii - ii1 == 0);
-        assert (ii1 - cii == 0);
-
-        C c;
-        assert ( c.begin()   == std::begin(c));
-        assert ( c.cbegin()  == std::cbegin(c));
-        assert ( c.rbegin()  == std::rbegin(c));
-        assert ( c.crbegin() == std::crbegin(c));
-        assert ( c.end()     == std::end(c));
-        assert ( c.cend()    == std::cend(c));
-        assert ( c.rend()    == std::rend(c));
-        assert ( c.crend()   == std::crend(c));
-
-        assert ( std::begin(c)   == std::end(c));
-        assert ( std::rbegin(c)  == std::rend(c));
-        assert ( std::cbegin(c)  == std::cend(c));
-        assert ( std::crbegin(c) == std::crend(c));
+            typedef std::array<int, 0> C;
+            C::iterator ii1{}, ii2{};
+            C::iterator ii4 = ii1;
+            C::const_iterator cii{};
+            assert(ii1 == ii2);
+            assert(ii1 == ii4);
+
+            assert(!(ii1 != ii2));
+
+            assert( (ii1 == cii));
+            assert( (cii == ii1));
+            assert(!(ii1 != cii));
+            assert(!(cii != ii1));
+            assert(!(ii1 <  cii));
+            assert(!(cii <  ii1));
+            assert( (ii1 <= cii));
+            assert( (cii <= ii1));
+            assert(!(ii1 >  cii));
+            assert(!(cii >  ii1));
+            assert( (ii1 >= cii));
+            assert( (cii >= ii1));
+            assert(cii - ii1 == 0);
+            assert(ii1 - cii == 0);
+
+            C c = {};
+            assert(c.begin()   == std::begin(c));
+            assert(c.cbegin()  == std::cbegin(c));
+            assert(c.rbegin()  == std::rbegin(c));
+            assert(c.crbegin() == std::crbegin(c));
+            assert(c.end()     == std::end(c));
+            assert(c.cend()    == std::cend(c));
+            assert(c.rend()    == std::rend(c));
+            assert(c.crend()   == std::crend(c));
+
+            assert(std::begin(c)   == std::end(c));
+            assert(std::rbegin(c)  == std::rend(c));
+            assert(std::cbegin(c)  == std::cend(c));
+            assert(std::crbegin(c) == std::crend(c));
         }
     }
 #endif
-#if TEST_STD_VER > 14
-    {
-        typedef std::array<int, 5> C;
-        constexpr C c{0,1,2,3,4};
-
-        static_assert ( c.begin()   == std::begin(c), "");
-        static_assert ( c.cbegin()  == std::cbegin(c), "");
-        static_assert ( c.end()     == std::end(c), "");
-        static_assert ( c.cend()    == std::cend(c), "");
-
-        static_assert ( c.rbegin()  == std::rbegin(c), "");
-        static_assert ( c.crbegin() == std::crbegin(c), "");
-        static_assert ( c.rend()    == std::rend(c), "");
-        static_assert ( c.crend()   == std::crend(c), "");
-
-        static_assert ( std::begin(c)   != std::end(c), "");
-        static_assert ( std::rbegin(c)  != std::rend(c), "");
-        static_assert ( std::cbegin(c)  != std::cend(c), "");
-        static_assert ( std::crbegin(c) != std::crend(c), "");
-
-        static_assert ( *c.begin()  == 0, "");
-        static_assert ( *c.rbegin()  == 4, "");
-
-        static_assert ( *std::begin(c)   == 0, "" );
-        static_assert ( *std::cbegin(c)  == 0, "" );
-        static_assert ( *std::rbegin(c)  == 4, "" );
-        static_assert ( *std::crbegin(c) == 4, "" );
-    }
-#endif
+    return true;
+}
 
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 17
+    static_assert(tests(), "");
+#endif
   return 0;
 }

diff  --git a/libcxx/test/std/containers/sequences/array/max_size.pass.cpp b/libcxx/test/std/containers/sequences/array/max_size.pass.cpp
index a0b77392ee80..8ca8cd44725e 100644
--- a/libcxx/test/std/containers/sequences/array/max_size.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/max_size.pass.cpp
@@ -10,28 +10,45 @@
 
 // class array
 
-// bool max_size() const noexcept;
+// constexpr bool max_size() const noexcept;
 
 #include <array>
 #include <cassert>
 
 #include "test_macros.h"
-#include "min_allocator.h"
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX14 bool tests()
 {
     {
-    typedef std::array<int, 2> C;
-    C c;
-    ASSERT_NOEXCEPT(c.max_size());
-    assert(c.max_size() == 2);
+        typedef std::array<int, 2> C;
+        C c = {};
+        ASSERT_NOEXCEPT(c.max_size());
+        assert(c.max_size() == 2);
+    }
+    {
+        typedef std::array<int, 0> C;
+        C c = {};
+        ASSERT_NOEXCEPT(c.max_size());
+        assert(c.max_size() == 0);
     }
+
+    return true;
+}
+
+int main(int, char**)
+{
+    tests();
+#if TEST_STD_VER >= 14
+    static_assert(tests(), "");
+#endif
+
+#if TEST_STD_VER >= 11
+    // Sanity check for constexpr in C++11
     {
-    typedef std::array<int, 0> C;
-    C c;
-    ASSERT_NOEXCEPT(c.max_size());
-    assert(c.max_size() == 0);
+        constexpr std::array<int, 3> array = {};
+        static_assert(array.max_size() == 3, "");
     }
+#endif
 
-  return 0;
+    return 0;
 }

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 51982ea5cab1..11eac5cc825b 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
@@ -34,12 +34,6 @@ void test() {
   static_assert(sizeof(ArrayT) == sizeof(CArrayT), "");
   static_assert(sizeof(ArrayT) == sizeof(MyArrayT), "");
   static_assert(TEST_ALIGNOF(ArrayT) == TEST_ALIGNOF(MyArrayT), "");
-#if defined(_LIBCPP_VERSION)
-  ArrayT a;
-  ((void)a);
-  static_assert(sizeof(ArrayT) == sizeof(a.__elems_), "");
-  static_assert(TEST_ALIGNOF(ArrayT) == __alignof__(a.__elems_), "");
-#endif
 }
 
 template <class T>
@@ -67,8 +61,6 @@ struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType2 {
 };
 #endif
 
-//static_assert(sizeof(void*) == 4, "");
-
 int main(int, char**) {
   test_type<char>();
   test_type<int>();

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp
index 152458908e7d..933420be50c9 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp
@@ -15,6 +15,7 @@
 
 /*  Constant                                Value
     __cpp_lib_array_constexpr               201603L [C++17]
+                                            201811L [C++2a]
     __cpp_lib_constexpr_misc                201811L [C++2a]
     __cpp_lib_nonmember_container_access    201411L [C++17]
     __cpp_lib_to_array                      201907L [C++2a]
@@ -88,8 +89,8 @@
 # ifndef __cpp_lib_array_constexpr
 #   error "__cpp_lib_array_constexpr should be defined in c++2a"
 # endif
-# if __cpp_lib_array_constexpr != 201603L
-#   error "__cpp_lib_array_constexpr should have the value 201603L in c++2a"
+# if __cpp_lib_array_constexpr != 201811L
+#   error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
 # endif
 
 # if !defined(_LIBCPP_VERSION)

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp
index 9c1719b53cfe..4e68cf9a7232 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp
@@ -15,6 +15,7 @@
 
 /*  Constant                                Value
     __cpp_lib_array_constexpr               201603L [C++17]
+                                            201811L [C++2a]
     __cpp_lib_constexpr_misc                201811L [C++2a]
     __cpp_lib_make_reverse_iterator         201402L [C++14]
     __cpp_lib_nonmember_container_access    201411L [C++17]
@@ -126,8 +127,8 @@
 # ifndef __cpp_lib_array_constexpr
 #   error "__cpp_lib_array_constexpr should be defined in c++2a"
 # endif
-# if __cpp_lib_array_constexpr != 201603L
-#   error "__cpp_lib_array_constexpr should have the value 201603L in c++2a"
+# if __cpp_lib_array_constexpr != 201811L
+#   error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
 # endif
 
 # if !defined(_LIBCPP_VERSION)

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index 0c2cd5375758..901cb2539635 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -19,6 +19,7 @@
     __cpp_lib_any                                  201606L [C++17]
     __cpp_lib_apply                                201603L [C++17]
     __cpp_lib_array_constexpr                      201603L [C++17]
+                                                   201811L [C++2a]
     __cpp_lib_as_const                             201510L [C++17]
     __cpp_lib_atomic_is_always_lock_free           201603L [C++17]
     __cpp_lib_atomic_ref                           201806L [C++2a]
@@ -1537,8 +1538,8 @@
 # ifndef __cpp_lib_array_constexpr
 #   error "__cpp_lib_array_constexpr should be defined in c++2a"
 # endif
-# if __cpp_lib_array_constexpr != 201603L
-#   error "__cpp_lib_array_constexpr should have the value 201603L in c++2a"
+# if __cpp_lib_array_constexpr != 201811L
+#   error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
 # endif
 
 # ifndef __cpp_lib_as_const

diff  --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 79ee5ddace8c..63aa4f47a70f 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -149,6 +149,12 @@
 # define TEST_CONSTEXPR_CXX14
 #endif
 
+#if TEST_STD_VER >= 17
+# define TEST_CONSTEXPR_CXX17 constexpr
+#else
+# define TEST_CONSTEXPR_CXX17
+#endif
+
 #if TEST_STD_VER >= 20
 # define TEST_CONSTEXPR_CXX20 constexpr
 #else

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 4a9772cfc66d..7a3f441c1cab 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -409,6 +409,7 @@ def add_version_header(tc):
   {"name": "__cpp_lib_array_constexpr",
    "values": {
      "c++17": int(201603),
+     "c++2a": int(201811),
    },
    "headers": ["iterator", "array"],
    },


        


More information about the libcxx-commits mailing list