diff --git a/libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp b/libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/array/triviality.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure std::array is trivially copyable whenever T is trivially copyable. +// This is not technically mandated by the Standard, but libc++ has been providing +// this property. + +#include +#include + + +struct Empty { }; + +struct TrivialCopy { + int i; + double j; +}; + +struct NonTrivialCopy { + NonTrivialCopy(NonTrivialCopy const&) { } + NonTrivialCopy& operator=(NonTrivialCopy const&) { return *this; } +}; + +template +void check_trivially_copyable() +{ + static_assert(std::is_trivially_copyable >::value, ""); + static_assert(std::is_trivially_copyable >::value, ""); + static_assert(std::is_trivially_copyable >::value, ""); + static_assert(std::is_trivially_copyable >::value, ""); +} + +int main(int, char**) +{ + check_trivially_copyable(); + check_trivially_copyable(); + check_trivially_copyable(); + check_trivially_copyable(); + check_trivially_copyable(); + check_trivially_copyable(); + + // Check that std::array is still trivially copyable when T is not + static_assert( std::is_trivially_copyable >::value, ""); + static_assert(!std::is_trivially_copyable >::value, ""); + static_assert(!std::is_trivially_copyable >::value, ""); + static_assert(!std::is_trivially_copyable >::value, ""); + + return 0; +} diff --git a/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp b/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp --- a/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/aggregate.pass.cpp @@ -7,44 +7,41 @@ //===----------------------------------------------------------------------===// // Make sure std::array is an aggregate type. +// We can only check this in C++17 and above, because we don't have the +// trait before that. +// UNSUPPORTED: c++03, c++11, c++14 #include #include template -void tests() +void check_aggregate() { - // Test aggregate initialization - { - std::array a0 = {}; (void)a0; - std::array a1 = {T()}; (void)a1; - std::array a2 = {T(), T()}; (void)a2; - std::array 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 >::value, ""); static_assert(std::is_aggregate >::value, ""); static_assert(std::is_aggregate >::value, ""); static_assert(std::is_aggregate >::value, ""); static_assert(std::is_aggregate >::value, ""); -#endif } struct Empty { }; -struct NonEmpty { int i; int j; }; +struct Trivial { int i; int j; }; +struct NonTrivial { + int i; int j; + NonTrivial(NonTrivial const&) { } +}; int main(int, char**) { - tests(); - tests(); - tests(); - tests(); - tests(); - tests(); - tests(); - tests(); + check_aggregate(); + check_aggregate(); + check_aggregate(); + check_aggregate(); + check_aggregate(); + check_aggregate(); + check_aggregate(); + check_aggregate(); + check_aggregate(); return 0; } diff --git a/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/containers/sequences/array/array.cons/default.pass.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// array(); - -#include -#include - -// std::array is explicitly allowed to be initialized with A a = { init-list };. -// Disable the missing braces warning for this reason. -#include "test_macros.h" -#include "disable_missing_braces_warning.h" - -struct NoDefault { - TEST_CONSTEXPR NoDefault(int) { } -}; - -struct Default { - TEST_CONSTEXPR Default() { } -}; - -TEST_CONSTEXPR_CXX14 bool tests() -{ - { - std::array array; - assert(array.size() == 3); - } - - { - std::array array; - assert(array.size() == 0); - } - - { - typedef std::array C; - C c; - assert(c.size() == 0); - C c1 = {}; - assert(c1.size() == 0); - C c2 = {{}}; - assert(c2.size() == 0); - } - - return true; -} - -int main(int, char**) -{ - tests(); -#if TEST_STD_VER >= 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp --- a/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp @@ -32,62 +32,82 @@ TEST_CONSTEXPR NoDefault(int) { } }; +struct NonTrivialCopy { + TEST_CONSTEXPR NonTrivialCopy() { } + NonTrivialCopy(NonTrivialCopy const&) { } + NonTrivialCopy& operator=(NonTrivialCopy const&) { return *this; } +}; + TEST_CONSTEXPR_CXX14 bool tests() { { - typedef double T; - typedef std::array C; - C c = {1.1, 2.2, 3.3}; - C c2 = c; - c2 = c; - static_assert(std::is_copy_constructible::value, ""); - static_assert(std::is_copy_assignable::value, ""); + typedef std::array Array; + Array array = {1.1, 2.2, 3.3}; + Array copy = array; + copy = array; + static_assert(std::is_copy_constructible::value, ""); + static_assert(std::is_copy_assignable::value, ""); } { - typedef double T; - typedef std::array C; - C c = {1.1, 2.2, 3.3}; - C c2 = c; - ((void)c2); - static_assert(std::is_copy_constructible::value, ""); - TEST_NOT_COPY_ASSIGNABLE(C); + typedef std::array Array; + Array array = {1.1, 2.2, 3.3}; + Array copy = array; (void)copy; + static_assert(std::is_copy_constructible::value, ""); + TEST_NOT_COPY_ASSIGNABLE(Array); } { - typedef double T; - typedef std::array C; - C c = {}; - C c2 = c; - c2 = c; - static_assert(std::is_copy_constructible::value, ""); - static_assert(std::is_copy_assignable::value, ""); + typedef std::array Array; + Array array = {}; + Array copy = array; + copy = array; + static_assert(std::is_copy_constructible::value, ""); + static_assert(std::is_copy_assignable::value, ""); } { // const arrays of size 0 should disable the implicit copy assignment operator. - typedef double T; - typedef std::array C; - C c = {{}}; - C c2 = c; - ((void)c2); - static_assert(std::is_copy_constructible::value, ""); - TEST_NOT_COPY_ASSIGNABLE(C); + typedef std::array Array; + Array array = {}; + Array copy = array; (void)copy; + static_assert(std::is_copy_constructible::value, ""); + TEST_NOT_COPY_ASSIGNABLE(Array); + } + { + typedef std::array Array; + Array array = {}; + Array copy = array; + copy = array; + static_assert(std::is_copy_constructible::value, ""); + static_assert(std::is_copy_assignable::value, ""); + } + { + typedef std::array Array; + Array array = {}; + Array copy = array; (void)copy; + static_assert(std::is_copy_constructible::value, ""); + TEST_NOT_COPY_ASSIGNABLE(Array); + } + + // Make sure we can implicitly copy a std::array of a non-trivially copyable type + { + typedef std::array Array; + Array array = {}; + Array copy = array; + copy = array; + static_assert(std::is_copy_constructible::value, ""); } { - typedef NoDefault T; - typedef std::array C; - C c = {}; - C c2 = c; - c2 = c; - static_assert(std::is_copy_constructible::value, ""); - static_assert(std::is_copy_assignable::value, ""); + typedef std::array Array; + Array array = {}; + Array copy = array; + copy = array; + static_assert(std::is_copy_constructible::value, ""); } { - typedef NoDefault T; - typedef std::array C; - C c = {{}}; - C c2 = c; - ((void)c2); - static_assert(std::is_copy_constructible::value, ""); - TEST_NOT_COPY_ASSIGNABLE(C); + typedef std::array Array; + Array array = {}; + Array copy = array; + copy = array; + static_assert(std::is_copy_constructible::value, ""); } return true; diff --git a/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp @@ -0,0 +1,188 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Test all the ways of initializing a std::array. + +#include +#include +#include +#include "test_macros.h" + + +struct NoDefault { + TEST_CONSTEXPR NoDefault(int) { } +}; + +// Test default initialization +// This one isn't constexpr because omitting to initialize fundamental types +// isn't valid in a constexpr context. +struct test_default_initialization { + template + void operator()() const + { + std::array a0; (void)a0; + std::array a1; (void)a1; + std::array a2; (void)a2; + std::array a3; (void)a3; + + std::array nodefault; (void)nodefault; + } +}; + +struct test_nondefault_initialization { + template + TEST_CONSTEXPR_CXX14 void operator()() const + { + // Check direct-list-initialization syntax (introduced in C++11) + #if TEST_STD_VER >= 11 + { + { + std::array a0_0{}; (void)a0_0; + } + { + std::array a1_0{}; (void)a1_0; + std::array a1_1{T()}; (void)a1_1; + } + { + std::array a2_0{}; (void)a2_0; + std::array a2_1{T()}; (void)a2_1; + std::array a2_2{T(), T()}; (void)a2_2; + } + { + std::array a3_0{}; (void)a3_0; + std::array a3_1{T()}; (void)a3_1; + std::array a3_2{T(), T()}; (void)a3_2; + std::array a3_3{T(), T(), T()}; (void)a3_3; + } + + std::array nodefault{}; (void)nodefault; + } + #endif + + // Check copy-list-initialization syntax + { + { + std::array a0_0 = {}; (void)a0_0; + } + { + std::array a1_0 = {}; (void)a1_0; + std::array a1_1 = {T()}; (void)a1_1; + } + { + std::array a2_0 = {}; (void)a2_0; + std::array a2_1 = {T()}; (void)a2_1; + std::array a2_2 = {T(), T()}; (void)a2_2; + } + { + std::array a3_0 = {}; (void)a3_0; + std::array a3_1 = {T()}; (void)a3_1; + std::array a3_2 = {T(), T()}; (void)a3_2; + std::array a3_3 = {T(), T(), T()}; (void)a3_3; + } + + std::array nodefault = {}; (void)nodefault; + } + + // Test aggregate initialization + { + { + std::array a0_0 = {{}}; (void)a0_0; + } + { + std::array a1_0 = {{}}; (void)a1_0; + std::array a1_1 = {{T()}}; (void)a1_1; + } + { + std::array a2_0 = {{}}; (void)a2_0; + std::array a2_1 = {{T()}}; (void)a2_1; + std::array a2_2 = {{T(), T()}}; (void)a2_2; + } + { + std::array a3_0 = {{}}; (void)a3_0; + std::array a3_1 = {{T()}}; (void)a3_1; + std::array a3_2 = {{T(), T()}}; (void)a3_2; + std::array a3_3 = {{T(), T(), T()}}; (void)a3_3; + } + + // See http://wg21.link/LWG2157 + std::array nodefault = {{}}; (void)nodefault; + } + } +}; + +// Test construction from an initializer-list +TEST_CONSTEXPR_CXX14 bool test_initializer_list() +{ + { + std::array const a3_0 = {}; + assert(a3_0[0] == double()); + assert(a3_0[1] == double()); + assert(a3_0[2] == double()); + } + { + std::array const a3_1 = {1}; + assert(a3_1[0] == double(1)); + assert(a3_1[1] == double()); + assert(a3_1[2] == double()); + } + { + std::array const a3_2 = {1, 2.2}; + assert(a3_2[0] == double(1)); + assert(a3_2[1] == 2.2); + assert(a3_2[2] == double()); + } + { + std::array const a3_3 = {1, 2, 3.5}; + assert(a3_3[0] == double(1)); + assert(a3_3[1] == double(2)); + assert(a3_3[2] == 3.5); + } + + return true; +} + +struct Empty { }; +struct Trivial { int i; int j; }; +struct NonTrivial { + TEST_CONSTEXPR NonTrivial() { } + TEST_CONSTEXPR NonTrivial(NonTrivial const&) { } +}; +struct NonEmptyNonTrivial { + int i; int j; + TEST_CONSTEXPR NonEmptyNonTrivial() : i(22), j(33) { } + TEST_CONSTEXPR NonEmptyNonTrivial(NonEmptyNonTrivial const&) : i(22), j(33) { } +}; + +template +TEST_CONSTEXPR_CXX14 bool with_all_types() +{ + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + F().template operator()(); + return true; +} + +int main(int, char**) +{ + with_all_types(); + with_all_types(); // not constexpr + test_initializer_list(); +#if TEST_STD_VER >= 14 + static_assert(with_all_types(), ""); + static_assert(test_initializer_list(), ""); +#endif + + return 0; +} diff --git a/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp +++ /dev/null @@ -1,63 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Construct with initializer list - -#include -#include - -// std::array is explicitly allowed to be initialized with A a = { init-list };. -// Disable the missing braces warning for this reason. -#include "test_macros.h" -#include "disable_missing_braces_warning.h" - -TEST_CONSTEXPR_CXX14 bool tests() -{ - { - typedef double T; - typedef std::array C; - C const c = {1, 2, 3.5}; - assert(c.size() == 3); - assert(c[0] == 1); - assert(c[1] == 2); - assert(c[2] == 3.5); - } - { - typedef double T; - typedef std::array C; - C const c = {}; - assert(c.size() == 0); - } - - { - typedef double T; - typedef std::array C; - C const c = {1}; - assert(c.size() == 3.0); - assert(c[0] == 1); - } - { - typedef int T; - typedef std::array C; - C const c = {}; - assert(c.size() == 1); - } - - return true; -} - -int main(int, char**) -{ - tests(); -#if TEST_STD_VER >= 14 - static_assert(tests(), ""); -#endif - return 0; -}