diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:58 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:58 +0000 |
commit | 53a420fba21cf1644972b34dcd811a43cdb8368d (patch) | |
tree | 66a19f6f8b65215772549a51d688492ab8addc0d /test/std/utilities | |
parent | b50f1549701eb950921e5d6f2e55ba1a1dadbb43 (diff) |
Notes
Diffstat (limited to 'test/std/utilities')
380 files changed, 19409 insertions, 1207 deletions
diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp index a5663a2e063e..0aef2af85ccf 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -23,8 +25,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A1<int> a3(3); @@ -108,5 +108,4 @@ int main() std::scoped_allocator_adaptor<A2<int>, A3<int>>(A2<int>(5), A3<int>(6)))); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_copy.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_copy.pass.cpp index 9d40cf55a144..8fbbcebe1268 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_copy.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_copy.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -23,8 +25,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<double>> B; typedef std::scoped_allocator_adaptor<A1<int>> A; @@ -65,5 +65,4 @@ int main() assert(a2 == a1); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_move.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_move.pass.cpp index 02e9dff7d7d3..8b585e5f6243 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_move.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/converting_move.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -23,8 +25,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<double>> B; typedef std::scoped_allocator_adaptor<A1<int>> A; @@ -70,6 +70,4 @@ int main() assert(A3<int>::move_called == true); assert(a2 == a1); } - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/copy.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/copy.pass.cpp index 21055325112f..86f16891ac3c 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/copy.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/copy.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a1(A1<int>(3)); @@ -65,6 +65,4 @@ int main() assert(A3<int>::move_called == false); assert(a2 == a1); } - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/default.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/default.pass.cpp index 2a1d781eb9cd..b335935e333d 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/default.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/default.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a; @@ -54,5 +54,4 @@ int main() assert(A3<int>::move_called == false); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size.pass.cpp index 727907e3ec76..dd8cf4273272 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a; @@ -45,5 +45,4 @@ int main() assert(A1<int>::allocate_called == true); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size_hint.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size_hint.pass.cpp index cae42de66905..f5ce83aa4f6c 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size_hint.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/allocate_size_hint.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a; @@ -66,5 +66,4 @@ int main() assert(a.allocate(10, (const void*)20) == (int*)20); assert(A2<int>::allocate_called == true); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct.pass.cpp index f94b0e19ac90..dc629edec54a 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -20,8 +22,6 @@ #include "allocators.h" -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - struct B { static bool constructed; @@ -111,11 +111,8 @@ struct F bool F::constructed = false; -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::scoped_allocator_adaptor<A1<std::string>> A; @@ -188,6 +185,4 @@ int main() assert(A3<F>::constructed); s->~S(); } - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp new file mode 100644 index 000000000000..4e73d8064317 --- /dev/null +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 0>; + using U = UsesAllocatorV2<VoidAlloc, 0>; + using Pair = std::pair<T, U>; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&>&&, + std::tuple<SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 0>; + using U = NotUsesAllocator<VoidAlloc, 0>; + using Pair = std::pair<T, U>; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&>&&, + std::tuple<>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 0>; + using U = UsesAllocatorV2<VoidAlloc2, 0>; + using Pair = std::pair<T, U>; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&>&&, + std::tuple<SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 0>; + using U = NotUsesAllocator<VoidAlloc2, 0>; + using Pair = std::pair<T, U>; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&>&&, + std::tuple<>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp new file mode 100644 index 000000000000..9effb6eded37 --- /dev/null +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, pair<T1, T2>const&) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + const PairIn in(x, std::move(y)); + A.construct(ptr, in); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&>&&, + std::tuple<int const&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + const PairIn in(x, y); + A.construct(ptr, in); + assert(checkConstruct<int const&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int const&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + const PairIn in(x, std::move(y)); + A.construct(ptr, in); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&>&&, + std::tuple<int const&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const &>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + const PairIn in(x, y); + A.construct(ptr, in); + assert(checkConstruct<int const&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int const&>&&, + std::tuple<int const&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp new file mode 100644 index 000000000000..4d371f206e65 --- /dev/null +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp @@ -0,0 +1,156 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2, class ...Args1, class ...Args2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, +// piecewise_construct_t, tuple<Args1...>, tuple<Args2...>) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(x), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&>&&, + std::tuple<int const&&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(std::move(x)), + std::forward_as_tuple(y)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(x), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int &&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&>&&, + std::tuple<int &&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(std::move(x)), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&&>&&, + std::tuple<int const&&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp new file mode 100644 index 000000000000..1d0fb5157c02 --- /dev/null +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, pair<T1, T2>&&) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + PairIn in(x, std::move(y)); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&>&&, + std::tuple<int const&&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + PairIn in(x, y); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + PairIn in(x, std::move(y)); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&>&&, + std::tuple<int const&&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const &>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + PairIn in(x, y); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&&>&&, + std::tuple<int const&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp new file mode 100644 index 000000000000..840f4ecc616d --- /dev/null +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2, class Tp, class Vp> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, Tp&&, Up&&) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, x, std::move(y)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&>&&, + std::tuple<int const&&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::move(x), y); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SA&, int&&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, x, std::move(y)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int &&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&>&&, + std::tuple<int &&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::move(x), std::move(y)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t, SAInner&, int&&>&&, + std::tuple<int const&&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_type.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_type.pass.cpp new file mode 100644 index 000000000000..867cc74082e7 --- /dev/null +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_type.pass.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class T, class ...Args> +// void scoped_allocator_adaptor::construct(T*, Args&&...) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + +// — If uses_allocator_v<T, inner_allocator_type> is false and +// is_constructible_v<T, Args...> is true, calls +// OUTERMOST_ALLOC_TRAITS(*this)::construct( +// OUTERMOST (*this), p, std::forward<Args>(args)...). +void test_bullet_one() { + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = NotUsesAllocator<VoidAlloc2, 3>; + using Outer = CountingAllocator<T, 1>; + using Inner = CountingAllocator<T, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(!std::uses_allocator<T, Inner>::value, ""); + T* ptr = (T*)::operator new(sizeof(T)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + int x = 42; + int const& cx = x; + A.construct(ptr, x, cx, std::move(x)); + assert((checkConstruct<int&, int const&, int&&>(*ptr, UA_None))); + assert((POuter.checkConstruct<int&, int const&, int&&>(O, ptr))); + A.destroy(ptr); + ::operator delete((void*)ptr); + } + PInner.reset(); + POuter.reset(); +} + + +// Otherwise, if uses_allocator_v<T, inner_allocator_type> is true and +// is_constructible_v<T, allocator_arg_t, inner_allocator_type&, Args...> is +// true, calls OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p, +// allocator_arg, inner_allocator(), std::forward<Args>(args)...). +void test_bullet_two() { + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 3>; + using Outer = CountingAllocator<T, 1>; + using Inner = CountingAllocator<T, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + T* ptr = (T*)::operator new(sizeof(T)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + int x = 42; + int const& cx = x; + A.construct(ptr, x, cx, std::move(x)); + assert((checkConstruct<int&, int const&, int&&>(*ptr, UA_AllocArg, I))); + assert((POuter.checkConstruct<std::allocator_arg_t const&, + SA::inner_allocator_type&, int&, int const&, int&&>(O, ptr))); + A.destroy(ptr); + ::operator delete((void*)ptr); + } + PInner.reset(); + POuter.reset(); +} + +// Otherwise, if uses_allocator_v<T, inner_allocator_type> is true and +// is_constructible_v<T, Args..., inner_allocator_type&> is true, calls +// OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p, +// std::forward<Args>(args)..., inner_allocator()). +void test_bullet_three() { + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV2<VoidAlloc2, 3>; + using Outer = CountingAllocator<T, 1>; + using Inner = CountingAllocator<T, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + T* ptr = (T*)::operator new(sizeof(T)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + int x = 42; + int const& cx = x; + A.construct(ptr, x, cx, std::move(x)); + assert((checkConstruct<int&, int const&, int&&>(*ptr, UA_AllocLast, I))); + assert((POuter.checkConstruct< + int&, int const&, int&&, + SA::inner_allocator_type&>(O, ptr))); + A.destroy(ptr); + ::operator delete((void*)ptr); + } + PInner.reset(); + POuter.reset(); +} + +int main() { + test_bullet_one(); + test_bullet_two(); + test_bullet_three(); +} diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/deallocate.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/deallocate.pass.cpp index bf77f29f7145..7924140cf2cd 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/deallocate.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/deallocate.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,7 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::scoped_allocator_adaptor<A1<int>> A; @@ -42,5 +43,4 @@ int main() assert((A1<int>::deallocate_called == std::pair<int*, std::size_t>((int*)10, 20))); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/destroy.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/destroy.pass.cpp index 0ff3880f9fc1..96850d783b99 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/destroy.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/destroy.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -32,8 +34,6 @@ bool B::constructed = false; int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<B>> A; A a; @@ -66,5 +66,4 @@ int main() assert(A3<S>::destroy_called); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/inner_allocator.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/inner_allocator.pass.cpp index 0fb55b692cdb..9b892abd81f3 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/inner_allocator.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/inner_allocator.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -22,8 +24,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a(A1<int>(5)); @@ -41,5 +41,4 @@ int main() std::scoped_allocator_adaptor<A2<int>, A3<int>>(A2<int>(6), A3<int>(8)))); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/max_size.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/max_size.pass.cpp index a5275ee30253..8b88dcc963dd 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/max_size.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/max_size.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; const A a(A1<int>(100)); @@ -39,5 +39,4 @@ int main() assert(a.max_size() == 200); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/outer_allocator.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/outer_allocator.pass.cpp index 2297612e6098..238d46017b0a 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/outer_allocator.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/outer_allocator.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -22,7 +24,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::scoped_allocator_adaptor<A1<int>> A; @@ -39,6 +40,4 @@ int main() A a(A1<int>(5), A2<int>(6), A3<int>(8)); assert(a.outer_allocator() == A1<int>(5)); } - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/select_on_container_copy_construction.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/select_on_container_copy_construction.pass.cpp index f9f0ffa2ad2a..8ee048bb99f1 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/select_on_container_copy_construction.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/select_on_container_copy_construction.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a1(A1<int>(3)); @@ -51,5 +51,4 @@ int main() assert(a2.inner_allocator().inner_allocator().outer_allocator().id() == -1); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/inner_allocator_type.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/inner_allocator_type.pass.cpp index 4303b95166c7..f4c106014a15 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/inner_allocator_type.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/inner_allocator_type.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - static_assert((std::is_same< std::scoped_allocator_adaptor<A1<int>>::inner_allocator_type, std::scoped_allocator_adaptor<A1<int>>>::value), ""); @@ -34,6 +34,4 @@ int main() static_assert((std::is_same< std::scoped_allocator_adaptor<A1<int>, A2<int>, A3<int>>::inner_allocator_type, std::scoped_allocator_adaptor<A2<int>, A3<int>>>::value), ""); - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/is_always_equal.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/is_always_equal.pass.cpp index 90fe944125b5..f8a9ea0f9eca 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/is_always_equal.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/is_always_equal.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -22,8 +24,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - // sanity checks static_assert( (std::is_same< std::allocator_traits<A1<int>>::is_always_equal, std::false_type>::value @@ -69,7 +69,4 @@ int main() std::allocator_traits<A2<int>>::is_always_equal::value && std::allocator_traits<A3<int>>::is_always_equal::value) ), ""); - - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_copy_assignment.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_copy_assignment.pass.cpp index ceb941380dc7..4c6aabe2160e 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_copy_assignment.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_copy_assignment.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - static_assert((std::is_same< std::scoped_allocator_adaptor<A1<int>>::propagate_on_container_copy_assignment, std::false_type>::value), ""); @@ -35,5 +35,4 @@ int main() std::scoped_allocator_adaptor<A1<int>, A2<int>, A3<int>>::propagate_on_container_copy_assignment, std::true_type>::value), ""); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_move_assignment.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_move_assignment.pass.cpp index 04da50706536..f6f092ba575a 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_move_assignment.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_move_assignment.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - static_assert((std::is_same< std::scoped_allocator_adaptor<A1<int>>::propagate_on_container_move_assignment, std::false_type>::value), ""); @@ -35,5 +35,4 @@ int main() std::scoped_allocator_adaptor<A1<int>, A2<int>, A3<int>>::propagate_on_container_move_assignment, std::true_type>::value), ""); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_swap.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_swap.pass.cpp index 4a66bbd46749..6b7273e266be 100644 --- a/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_swap.pass.cpp +++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.types/propagate_on_container_swap.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -21,8 +23,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - static_assert((std::is_same< std::scoped_allocator_adaptor<A1<int>>::propagate_on_container_swap, std::false_type>::value), ""); @@ -34,6 +34,4 @@ int main() static_assert((std::is_same< std::scoped_allocator_adaptor<A1<int>, A2<int>, A3<int>>::propagate_on_container_swap, std::true_type>::value), ""); - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/copy_assign.pass.cpp b/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/copy_assign.pass.cpp index 72f0e867b1d2..2cf548550e1f 100644 --- a/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/copy_assign.pass.cpp +++ b/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/copy_assign.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -22,7 +24,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::scoped_allocator_adaptor<A1<int>> A; A a1(A1<int>(3)); @@ -68,5 +69,4 @@ int main() assert(A3<int>::move_called == false); assert(aN == a1); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/eq.pass.cpp b/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/eq.pass.cpp index 51dd67f9ffdc..4f7a3af12544 100644 --- a/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/eq.pass.cpp +++ b/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/eq.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -29,8 +31,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { typedef std::scoped_allocator_adaptor<A1<int>> A; A a1(A1<int>(3)); @@ -59,6 +59,4 @@ int main() assert(a2 != a1); assert(!(a2 == a1)); } - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/move_assign.pass.cpp b/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/move_assign.pass.cpp index 0dc479c246c9..68f5a7ea2879 100644 --- a/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/move_assign.pass.cpp +++ b/test/std/utilities/allocator.adaptor/scoped.adaptor.operators/move_assign.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -22,7 +24,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::scoped_allocator_adaptor<A1<int>> A; A a1(A1<int>(3)); @@ -68,5 +69,4 @@ int main() assert(A3<int>::move_called == true); assert(aN == a1); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/allocator.adaptor/types.pass.cpp b/test/std/utilities/allocator.adaptor/types.pass.cpp index 7beff48bbf46..fcc99b191108 100644 --- a/test/std/utilities/allocator.adaptor/types.pass.cpp +++ b/test/std/utilities/allocator.adaptor/types.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // template <class OuterAlloc, class... InnerAllocs> @@ -30,8 +32,6 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - static_assert((std::is_base_of< A1<int>, std::scoped_allocator_adaptor<A1<int>> @@ -97,6 +97,4 @@ int main() static_assert((std::is_same< std::scoped_allocator_adaptor<A2<int>, A1<int>>::const_void_pointer, const void*>::value), ""); - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/any/any.class/any.assign/copy.pass.cpp b/test/std/utilities/any/any.class/any.assign/copy.pass.cpp new file mode 100644 index 000000000000..eba9bc6d5feb --- /dev/null +++ b/test/std/utilities/any/any.class/any.assign/copy.pass.cpp @@ -0,0 +1,197 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any& operator=(any const &); + +// Test copy assignment + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +template <class LHS, class RHS> +void test_copy_assign() { + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any const rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::copied == 1); + assert(LHS::count == 0); + assert(RHS::count == 2); + + assertContains<RHS>(lhs, 2); + assertContains<RHS>(rhs, 2); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class LHS> +void test_copy_assign_empty() { + assert(LHS::count == 0); + LHS::reset(); + { + any lhs; + any const rhs(LHS(42)); + + assert(LHS::count == 1); + assert(LHS::copied == 0); + + lhs = rhs; + + assert(LHS::copied == 1); + assert(LHS::count == 2); + + assertContains<LHS>(lhs, 42); + assertContains<LHS>(rhs, 42); + } + assert(LHS::count == 0); + LHS::reset(); + { + any lhs(LHS(1)); + any const rhs; + + assert(LHS::count == 1); + assert(LHS::copied == 0); + + lhs = rhs; + + assert(LHS::copied == 0); + assert(LHS::count == 0); + + assertEmpty<LHS>(lhs); + assertEmpty(rhs); + } + assert(LHS::count == 0); +} + +void test_copy_assign_self() { + // empty + { + any a; + a = a; + assertEmpty(a); + assert(globalMemCounter.checkOutstandingNewEq(0)); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + // small + { + any a((small(1))); + assert(small::count == 1); + + a = a; + + assert(small::count == 1); + assertContains<small>(a, 1); + assert(globalMemCounter.checkOutstandingNewEq(0)); + } + assert(small::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + // large + { + any a(large(1)); + assert(large::count == 1); + + a = a; + + assert(large::count == 1); + assertContains<large>(a, 1); + assert(globalMemCounter.checkOutstandingNewEq(1)); + } + assert(large::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); +} + +template <class Tp> +void test_copy_assign_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + auto try_throw = + [](any& lhs, any const& rhs) { + try { + lhs = rhs; + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + }; + // const lvalue to empty + { + any lhs; + any const rhs((Tp(1))); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(Tp::count == 1); + assertEmpty<Tp>(lhs); + assertContains<Tp>(rhs, 1); + } + { + any lhs((small(2))); + any const rhs((Tp(1))); + assert(small::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(small::count == 1); + assert(Tp::count == 1); + assertContains<small>(lhs, 2); + assertContains<Tp>(rhs, 1); + } + { + any lhs((large(2))); + any const rhs((Tp(1))); + assert(large::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(large::count == 1); + assert(Tp::count == 1); + assertContains<large>(lhs, 2); + assertContains<Tp>(rhs, 1); + } +#endif +} + +int main() { + test_copy_assign<small1, small2>(); + test_copy_assign<large1, large2>(); + test_copy_assign<small, large>(); + test_copy_assign<large, small>(); + test_copy_assign_empty<small>(); + test_copy_assign_empty<large>(); + test_copy_assign_self(); + test_copy_assign_throws<small_throws_on_copy>(); + test_copy_assign_throws<large_throws_on_copy>(); +} diff --git a/test/std/utilities/any/any.class/any.assign/move.pass.cpp b/test/std/utilities/any/any.class/any.assign/move.pass.cpp new file mode 100644 index 000000000000..2063e4f1e9f1 --- /dev/null +++ b/test/std/utilities/any/any.class/any.assign/move.pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any& operator=(any &&); + +// Test move assignment. + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +template <class LHS, class RHS> +void test_move_assign() { + assert(LHS::count == 0); + assert(RHS::count == 0); + { + LHS const s1(1); + any a(s1); + RHS const s2(2); + any a2(s2); + + assert(LHS::count == 2); + assert(RHS::count == 2); + + a = std::move(a2); + + assert(LHS::count == 1); + assert(RHS::count == 2 + a2.has_value()); + LIBCPP_ASSERT(RHS::count == 2); // libc++ leaves the object empty + + assertContains<RHS>(a, 2); + if (a2.has_value()) + assertContains<RHS>(a2, 0); + LIBCPP_ASSERT(!a2.has_value()); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class LHS> +void test_move_assign_empty() { + assert(LHS::count == 0); + { + any a; + any a2((LHS(1))); + + assert(LHS::count == 1); + + a = std::move(a2); + + assert(LHS::count == 1 + a2.has_value()); + LIBCPP_ASSERT(LHS::count == 1); + + assertContains<LHS>(a, 1); + if (a2.has_value()) + assertContains<LHS>(a2, 0); + LIBCPP_ASSERT(!a2.has_value()); + } + assert(LHS::count == 0); + { + any a((LHS(1))); + any a2; + + assert(LHS::count == 1); + + a = std::move(a2); + + assert(LHS::count == 0); + + assertEmpty<LHS>(a); + assertEmpty(a2); + } + assert(LHS::count == 0); +} + +void test_move_assign_noexcept() { + any a1; + any a2; + static_assert( + noexcept(a1 = std::move(a2)) + , "any & operator=(any &&) must be noexcept" + ); +} + +int main() { + test_move_assign_noexcept(); + test_move_assign<small1, small2>(); + test_move_assign<large1, large2>(); + test_move_assign<small, large>(); + test_move_assign<large, small>(); + test_move_assign_empty<small>(); + test_move_assign_empty<large>(); +} diff --git a/test/std/utilities/any/any.class/any.assign/value.pass.cpp b/test/std/utilities/any/any.class/any.assign/value.pass.cpp new file mode 100644 index 000000000000..6af481714922 --- /dev/null +++ b/test/std/utilities/any/any.class/any.assign/value.pass.cpp @@ -0,0 +1,209 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// any& operator=(ValueType&&); + +// Test value copy and move assignment. + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +template <class LHS, class RHS> +void test_assign_value() { + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any const rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::copied == 1); + assert(LHS::count == 0); + assert(RHS::count == 2); + + assertContains<RHS>(lhs, 2); + assertContains<RHS>(rhs, 2); + } + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::moved == 1); + + lhs = std::move(rhs); + + assert(RHS::moved >= 1); + assert(RHS::copied == 0); + assert(LHS::count == 0); + assert(RHS::count == 1 + rhs.has_value()); + LIBCPP_ASSERT(!rhs.has_value()); + + assertContains<RHS>(lhs, 2); + if (rhs.has_value()) + assertContains<RHS>(rhs, 0); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class RHS> +void test_assign_value_empty() { + assert(RHS::count == 0); + RHS::reset(); + { + any lhs; + RHS rhs(42); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::count == 2); + assert(RHS::copied == 1); + assert(RHS::moved >= 0); + assertContains<RHS>(lhs, 42); + } + assert(RHS::count == 0); + RHS::reset(); + { + any lhs; + RHS rhs(42); + assert(RHS::count == 1); + assert(RHS::moved == 0); + + lhs = std::move(rhs); + + assert(RHS::count == 2); + assert(RHS::copied == 0); + assert(RHS::moved >= 1); + assertContains<RHS>(lhs, 42); + } + assert(RHS::count == 0); + RHS::reset(); +} + + +template <class Tp, bool Move = false> +void test_assign_throws() { +#if !defined(TEST_HAS_NO_EXCEPTIONS) + auto try_throw = + [](any& lhs, auto&& rhs) { + try { + Move ? lhs = std::move(rhs) + : lhs = rhs; + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + }; + // const lvalue to empty + { + any lhs; + Tp rhs(1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(Tp::count == 1); + assertEmpty<Tp>(lhs); + } + { + any lhs((small(2))); + Tp rhs(1); + assert(small::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(small::count == 1); + assert(Tp::count == 1); + assertContains<small>(lhs, 2); + } + { + any lhs((large(2))); + Tp rhs(1); + assert(large::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(large::count == 1); + assert(Tp::count == 1); + assertContains<large>(lhs, 2); + } +#endif +} + + +// Test that any& operator=(ValueType&&) is *never* selected for: +// * std::in_place type. +// * Non-copyable types +void test_sfinae_constraints() { + { // Only the constructors are required to SFINAE on in_place_t + using Tag = std::in_place_type_t<int>; + using RawTag = std::remove_reference_t<Tag>; + static_assert(std::is_assignable<std::any, RawTag&&>::value, ""); + } + { + struct Dummy { Dummy() = delete; }; + using T = std::in_place_type_t<Dummy>; + static_assert(std::is_assignable<std::any, T>::value, ""); + } + { + // Test that the ValueType&& constructor SFINAE's away when the + // argument is non-copyable + struct NoCopy { + NoCopy() = default; + NoCopy(NoCopy const&) = delete; + NoCopy(NoCopy&&) = default; + }; + static_assert(!std::is_assignable<std::any, NoCopy>::value, ""); + static_assert(!std::is_assignable<std::any, NoCopy&>::value, ""); + } +} + +int main() { + test_assign_value<small1, small2>(); + test_assign_value<large1, large2>(); + test_assign_value<small, large>(); + test_assign_value<large, small>(); + test_assign_value_empty<small>(); + test_assign_value_empty<large>(); + test_assign_throws<small_throws_on_copy>(); + test_assign_throws<large_throws_on_copy>(); + test_assign_throws<throws_on_move, /* Move = */ true>(); + test_sfinae_constraints(); +} diff --git a/test/std/utilities/any/any.class/any.cons/copy.pass.cpp b/test/std/utilities/any/any.class/any.cons/copy.pass.cpp new file mode 100644 index 000000000000..021c9e452841 --- /dev/null +++ b/test/std/utilities/any/any.class/any.cons/copy.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any(any const &); + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +template <class Type> +void test_copy_throws() { +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(Type::count == 0); + { + any const a((Type(42))); + assert(Type::count == 1); + try { + any const a2(a); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(Type::count == 1); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); +#endif +} + +void test_copy_empty() { + DisableAllocationGuard g; ((void)g); // No allocations should occur. + any a1; + any a2(a1); + + assertEmpty(a1); + assertEmpty(a2); +} + +template <class Type> +void test_copy() +{ + // Copying small types should not perform any allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + assert(Type::count == 1); + assert(Type::copied == 0); + + any a2(a); + + assert(Type::copied == 1); + assert(Type::count == 2); + assertContains<Type>(a, 42); + assertContains<Type>(a2, 42); + + // Modify a and check that a2 is unchanged + modifyValue<Type>(a, -1); + assertContains<Type>(a, -1); + assertContains<Type>(a2, 42); + + // modify a2 and check that a is unchanged + modifyValue<Type>(a2, 999); + assertContains<Type>(a, -1); + assertContains<Type>(a2, 999); + + // clear a and check that a2 is unchanged + a.reset(); + assertEmpty(a); + assertContains<Type>(a2, 999); + } + assert(Type::count == 0); +} + +int main() { + test_copy<small>(); + test_copy<large>(); + test_copy_empty(); + test_copy_throws<small_throws_on_copy>(); + test_copy_throws<large_throws_on_copy>(); +} diff --git a/test/std/utilities/any/any.class/any.cons/default.pass.cpp b/test/std/utilities/any/any.class/any.cons/default.pass.cpp new file mode 100644 index 000000000000..ed7a948e00a2 --- /dev/null +++ b/test/std/utilities/any/any.class/any.cons/default.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any() noexcept; + +#include <any> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "any_helpers.h" +#include "count_new.hpp" + +int main() +{ + using std::any; + { + static_assert( + std::is_nothrow_default_constructible<any>::value + , "Must be default constructible" + ); + } + { + struct TestConstexpr : public std::any { + constexpr TestConstexpr() : std::any() {} + }; +#ifdef _LIBCPP_SAFE_STATIC + _LIBCPP_SAFE_STATIC static std::any a; + ((void)a); +#endif + } + { + DisableAllocationGuard g; ((void)g); + any const a; + assertEmpty(a); + } +} diff --git a/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp b/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp new file mode 100644 index 000000000000..4cf5d914f31d --- /dev/null +++ b/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp @@ -0,0 +1,194 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class T, class ...Args> any(in_place_type_t<T>, Args&&...); +// template <class T, class U, class ...Args> +// any(in_place_type_t<T>, initializer_list<U>, Args&&...); + +// Test construction from a value. +// Concerns: +// --------- +// 1. The value is properly move/copied depending on the value category. +// 2. Both small and large values are properly handled. + + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" +#include "test_convertible.hpp" + +using std::any; +using std::any_cast; + +template <class Type> +void test_in_place_type() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + any a(std::in_place_type<Type>); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 0); + } + assert(Type::count == 0); + Type::reset(); + { // Test that the in_place argument is properly decayed + any a(std::in_place_type<Type&>); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 0); + } + assert(Type::count == 0); + Type::reset(); + { + any a(std::in_place_type<Type>, 101); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 101); + } + assert(Type::count == 0); + Type::reset(); + { + any a(std::in_place_type<Type>, -1, 42, -1); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); +} + +template <class Type> +void test_in_place_type_tracked() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + { + any a(std::in_place_type<Type>); + assertArgsMatch<Type>(a); + } + { + any a(std::in_place_type<Type>, -1, 42, -1); + assertArgsMatch<Type, int, int, int>(a); + } + // initializer_list constructor tests + { + any a(std::in_place_type<Type>, {-1, 42, -1}); + assertArgsMatch<Type, std::initializer_list<int>>(a); + } + { + int x = 42; + any a(std::in_place_type<Type&>, {-1, 42, -1}, x); + assertArgsMatch<Type, std::initializer_list<int>, int&>(a); + } +} + +void test_func() {} + +void test_in_place_type_decayed() { + { + using Type = decltype(test_func); + using DecayT = void(*)(); + any a(std::in_place_type<Type>, test_func); + assert(containsType<DecayT>(a)); + assert(any_cast<DecayT>(a) == test_func); + } + { + int my_arr[5]; + using Type = int(&)[5]; + using DecayT = int*; + any a(std::in_place_type<Type>, my_arr); + assert(containsType<DecayT>(a)); + assert(any_cast<DecayT>(a) == my_arr); + } + { + using Type = int[5]; + using DecayT = int*; + any a(std::in_place_type<Type>); + assert(containsType<DecayT>(a)); + assert(any_cast<DecayT>(a) == nullptr); + } +} + +void test_ctor_sfinae() { + { + // Test that the init-list ctor SFINAE's away properly when + // construction would be ill-formed. + using IL = std::initializer_list<int>; + static_assert(!std::is_constructible<std::any, + std::in_place_type_t<int>, IL>::value, ""); + static_assert(std::is_constructible<std::any, + std::in_place_type_t<small_tracked_t>, IL>::value, ""); + } + { + // Test that the tagged dispatch constructor SFINAE's away when the + // argument is non-copyable + struct NoCopy { + NoCopy() = default; + NoCopy(NoCopy const&) = delete; + NoCopy(int) {} + NoCopy(std::initializer_list<int>, int) {} + }; + using Tag = std::in_place_type_t<NoCopy>; + using RefTag = std::in_place_type_t<NoCopy&>; + using IL = std::initializer_list<int>; + static_assert(!std::is_constructible<std::any, Tag>::value, ""); + static_assert(!std::is_constructible<std::any, Tag, int>::value, ""); + static_assert(!std::is_constructible<std::any, Tag, IL, int>::value, ""); + static_assert(!std::is_constructible<std::any, RefTag>::value, ""); + static_assert(!std::is_constructible<std::any, RefTag, int>::value, ""); + static_assert(!std::is_constructible<std::any, RefTag, IL, int>::value, ""); + } +} + +struct Implicit { + Implicit(int) {} + Implicit(int, int, int) {} + Implicit(std::initializer_list<int>, int) {} +}; + +void test_constructor_explicit() { + using I = Implicit; + using IT = std::in_place_type_t<I>; + static_assert(!test_convertible<std::any, IT, int>(), ""); + static_assert(std::is_constructible<std::any, IT, int>::value, ""); + static_assert(!test_convertible<std::any, IT, int, int, int>(), ""); + static_assert(std::is_constructible<std::any, IT, int, int, int>::value, ""); + static_assert(!test_convertible<std::any, IT, std::initializer_list<int>&, int>(), ""); + static_assert(std::is_constructible<std::any, IT, std::initializer_list<int>&, int>::value, ""); +} + +int main() { + test_in_place_type<small>(); + test_in_place_type<large>(); + test_in_place_type<small_throws_on_copy>(); + test_in_place_type<large_throws_on_copy>(); + test_in_place_type<throws_on_move>(); + test_in_place_type_tracked<small_tracked_t>(); + test_in_place_type_tracked<large_tracked_t>(); + test_in_place_type_decayed(); + test_ctor_sfinae(); + test_constructor_explicit(); +} diff --git a/test/std/utilities/any/any.class/any.cons/move.pass.cpp b/test/std/utilities/any/any.class/any.cons/move.pass.cpp new file mode 100644 index 000000000000..fb7dda886fe7 --- /dev/null +++ b/test/std/utilities/any/any.class/any.cons/move.pass.cpp @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any(any &&) noexcept; + +#include <any> +#include <utility> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +// Moves are always noexcept. The throws_on_move object +// must be stored dynamically so the pointer is moved and +// not the stored object. +void test_move_does_not_throw() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(throws_on_move::count == 0); + { + throws_on_move v(42); + any a(v); + assert(throws_on_move::count == 2); + // No allocations should be performed after this point. + DisableAllocationGuard g; ((void)g); + try { + any const a2(std::move(a)); + assertEmpty(a); + assertContains<throws_on_move>(a2, 42); + } catch (...) { + assert(false); + } + assert(throws_on_move::count == 1); + assertEmpty(a); + } + assert(throws_on_move::count == 0); +#endif +} + +void test_move_empty() { + DisableAllocationGuard g; ((void)g); // no allocations should be performed. + + any a1; + any a2(std::move(a1)); + + assertEmpty(a1); + assertEmpty(a2); +} + +template <class Type> +void test_move() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Moving should not perform allocations since it must be noexcept. + DisableAllocationGuard g; ((void)g); + + any a2(std::move(a)); + + assert(Type::moved == 1 || Type::moved == 2); // zero or more move operations can be performed. + assert(Type::copied == 0); // no copies can be performed. + assert(Type::count == 1 + a.has_value()); + assertContains<Type>(a2, 42); + LIBCPP_ASSERT(!a.has_value()); // Moves are always destructive. + if (a.has_value()) + assertContains<Type>(a, 0); + } + assert(Type::count == 0); +} + +int main() +{ + // noexcept test + { + static_assert( + std::is_nothrow_move_constructible<any>::value + , "any must be nothrow move constructible" + ); + } + test_move<small>(); + test_move<large>(); + test_move_empty(); + test_move_does_not_throw(); +} diff --git a/test/std/utilities/any/any.class/any.cons/value.pass.cpp b/test/std/utilities/any/any.class/any.cons/value.pass.cpp new file mode 100644 index 000000000000..a164fbeb52fe --- /dev/null +++ b/test/std/utilities/any/any.class/any.cons/value.pass.cpp @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class Value> any(Value &&) + +// Test construction from a value. +// Concerns: +// --------- +// 1. The value is properly move/copied depending on the value category. +// 2. Both small and large values are properly handled. + + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +template <class Type> +void test_copy_value_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(Type::count == 0); + { + Type const t(42); + assert(Type::count == 1); + try { + any const a2(t); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(Type::count == 1); + assert(t.value == 42); + } + assert(Type::count == 0); +#endif +} + +void test_move_value_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(throws_on_move::count == 0); + { + throws_on_move v; + assert(throws_on_move::count == 1); + try { + any const a(std::move(v)); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(throws_on_move::count == 1); + } + assert(throws_on_move::count == 0); +#endif +} + +template <class Type> +void test_copy_move_value() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + Type t(42); + assert(Type::count == 1); + + any a(t); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); + { + Type t(42); + assert(Type::count == 1); + + any a(std::move(t)); + + assert(Type::count == 2); + assert(Type::copied == 0); + assert(Type::moved == 1); + assertContains<Type>(a, 42); + } +} + +// Test that any(ValueType&&) is *never* selected for a std::in_place_type_t specialization. +void test_sfinae_constraints() { + using BadTag = std::in_place_type_t<int>; + using OKTag = std::in_place_t; + // Test that the tag type is properly handled in SFINAE + BadTag t = std::in_place_type<int>; + OKTag ot = std::in_place; + { + std::any a(t); + assertContains<int>(a, 0); + } + { + std::any a(std::move(t)); + assertContains<int>(a, 0); + } + { + std::any a(ot); + assert(containsType<OKTag>(a)); + } + { + struct Dummy { Dummy() = delete; }; + using T = std::in_place_type_t<Dummy>; + static_assert(!std::is_constructible<std::any, T>::value, ""); + } + { + // Test that the ValueType&& constructor SFINAE's away when the + // argument is non-copyable + struct NoCopy { + NoCopy() = default; + NoCopy(NoCopy const&) = delete; + NoCopy(int) {} + }; + static_assert(!std::is_constructible<std::any, NoCopy>::value, ""); + static_assert(!std::is_constructible<std::any, NoCopy&>::value, ""); + static_assert(!std::is_convertible<NoCopy, std::any>::value, ""); + } +} + +int main() { + test_copy_move_value<small>(); + test_copy_move_value<large>(); + test_copy_value_throws<small_throws_on_copy>(); + test_copy_value_throws<large_throws_on_copy>(); + test_move_value_throws(); + test_sfinae_constraints(); +}
\ No newline at end of file diff --git a/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp b/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp new file mode 100644 index 000000000000..65d94fd1e0a4 --- /dev/null +++ b/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp @@ -0,0 +1,262 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class T, class ...Args> emplace(Args&&...); +// template <class T, class U, class ...Args> +// void emplace(initializer_list<U>, Args&&...); + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +struct Tracked { + static int count; + Tracked() {++count;} + ~Tracked() { --count; } +}; +int Tracked::count = 0; + +template <class Type> +void test_emplace_type() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + + a.emplace<Type>(); + + assert(Tracked::count == 0); + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 0); + } + assert(Type::count == 0); + Type::reset(); + { + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + + a.emplace<Type>(101); + + assert(Tracked::count == 0); + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 101); + } + assert(Type::count == 0); + Type::reset(); + { + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + + a.emplace<Type>(-1, 42, -1); + + assert(Tracked::count == 0); + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); +} + +template <class Type> +void test_emplace_type_tracked() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + { + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + a.emplace<Type>(); + assert(Tracked::count == 0); + assertArgsMatch<Type>(a); + } + { + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + a.emplace<Type>(-1, 42, -1); + assert(Tracked::count == 0); + assertArgsMatch<Type, int, int, int>(a); + } + // initializer_list constructor tests + { + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + a.emplace<Type>({-1, 42, -1}); + assert(Tracked::count == 0); + assertArgsMatch<Type, std::initializer_list<int>>(a); + } + { + int x = 42; + any a(std::in_place_type<Tracked>); + assert(Tracked::count == 1); + a.emplace<Type>({-1, 42, -1}, x); + assert(Tracked::count == 0); + assertArgsMatch<Type, std::initializer_list<int>, int&>(a); + } +} + +#ifndef TEST_HAS_NO_EXCEPTIONS + +struct SmallThrows { + SmallThrows(int) { throw 42; } + SmallThrows(std::initializer_list<int>, int) { throw 42; } +}; +static_assert(IsSmallObject<SmallThrows>::value, ""); + +struct LargeThrows { + LargeThrows(int) { throw 42; } + LargeThrows(std::initializer_list<int>, int) { throw 42; } + int data[sizeof(std::any)]; +}; +static_assert(!IsSmallObject<LargeThrows>::value, ""); + +template <class Type> +void test_emplace_throws() +{ + // any stores small type + { + std::any a(small{42}); + assert(small::count == 1); + try { + a.emplace<Type>(101); + assert(false); + } catch (int const&) { + } + assert(small::count == 0); + } + { + std::any a(small{42}); + assert(small::count == 1); + try { + a.emplace<Type>({1, 2, 3}, 101); + assert(false); + } catch (int const&) { + } + assert(small::count == 0); + } + // any stores large type + { + std::any a(large{42}); + assert(large::count == 1); + try { + a.emplace<Type>(101); + assert(false); + } catch (int const&) { + } + assert(large::count == 0); + } + { + std::any a(large{42}); + assert(large::count == 1); + try { + a.emplace<Type>({1, 2, 3}, 101); + assert(false); + } catch (int const&) { + } + assert(large::count == 0); + } +} + +#endif + +template <class T, class ...Args> +constexpr auto has_emplace(int) + -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; } + +template <class ...Args> +constexpr bool has_emplace(long) { return false; } + +template <class ...Args> +constexpr bool has_emplace() { return has_emplace<Args...>(0); } + + +template <class T, class IT, class ...Args> +constexpr auto has_emplace_init_list(int) + -> decltype(std::any{}.emplace<T>( + {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()}, + std::declval<Args>()...), true) { return true; } + +template <class ...Args> +constexpr bool has_emplace_init_list(long) { return false; } + +template <class ...Args> +constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); } + + +void test_emplace_sfinae_constraints() { + { + static_assert(has_emplace<int>(), ""); + static_assert(has_emplace<int, int>(), ""); + static_assert(!has_emplace<int, int, int>(), "not constructible"); + static_assert(!has_emplace_init_list<int, int>(), "not constructible from il"); + } + { + static_assert(has_emplace<small>(), ""); + static_assert(has_emplace<large>(), ""); + static_assert(!has_emplace<small, void*>(), ""); + static_assert(!has_emplace<large, void*>(), ""); + + static_assert(has_emplace_init_list<small, int>(), ""); + static_assert(has_emplace_init_list<large, int>(), ""); + static_assert(!has_emplace_init_list<small, void*>(), ""); + static_assert(!has_emplace_init_list<large, void*>(), ""); + } + { + // Test that the emplace SFINAE's away when the + // argument is non-copyable + struct NoCopy { + NoCopy() = default; + NoCopy(NoCopy const&) = delete; + NoCopy(int) {} + NoCopy(std::initializer_list<int>, int, int) {} + }; + static_assert(!has_emplace<NoCopy>(), ""); + static_assert(!has_emplace<NoCopy, int>(), ""); + static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), ""); + static_assert(!has_emplace<NoCopy&>(), ""); + static_assert(!has_emplace<NoCopy&, int>(), ""); + static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), ""); + static_assert(!has_emplace<NoCopy&&>(), ""); + static_assert(!has_emplace<NoCopy&&, int>(), ""); + static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), ""); + + } +} + +int main() { + test_emplace_type<small>(); + test_emplace_type<large>(); + test_emplace_type<small_throws_on_copy>(); + test_emplace_type<large_throws_on_copy>(); + test_emplace_type<throws_on_move>(); + test_emplace_type_tracked<small_tracked_t>(); + test_emplace_type_tracked<large_tracked_t>(); + test_emplace_sfinae_constraints(); +#ifndef TEST_HAS_NO_EXCEPTIONS + test_emplace_throws<SmallThrows>(); + test_emplace_throws<LargeThrows>(); +#endif +} diff --git a/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp b/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp new file mode 100644 index 000000000000..45bc70f7a795 --- /dev/null +++ b/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any::reset() noexcept + +#include <any> +#include <cassert> + +#include "any_helpers.h" + +int main() +{ + using std::any; + using std::any_cast; + // empty + { + any a; + + // noexcept check + static_assert( + noexcept(a.reset()) + , "any.reset() must be noexcept" + ); + + assertEmpty(a); + + a.reset(); + + assertEmpty(a); + } + // small object + { + any a((small(1))); + assert(small::count == 1); + assertContains<small>(a, 1); + + a.reset(); + + assertEmpty<small>(a); + assert(small::count == 0); + } + // large object + { + any a(large(1)); + assert(large::count == 1); + assertContains<large>(a, 1); + + a.reset(); + + assertEmpty<large>(a); + assert(large::count == 0); + } +} diff --git a/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp b/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp new file mode 100644 index 000000000000..6fc100943d0f --- /dev/null +++ b/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any::swap(any &) noexcept + +// Test swap(large, small) and swap(small, large) + +#include <any> +#include <cassert> + +#include "any_helpers.h" + +using std::any; +using std::any_cast; + +template <class LHS, class RHS> +void test_swap() { + assert(LHS::count == 0); + assert(RHS::count == 0); + { + any a1((LHS(1))); + any a2(RHS{2}); + assert(LHS::count == 1); + assert(RHS::count == 1); + + a1.swap(a2); + + assert(LHS::count == 1); + assert(RHS::count == 1); + + assertContains<RHS>(a1, 2); + assertContains<LHS>(a2, 1); + } + assert(LHS::count == 0); + assert(RHS::count == 0); + assert(LHS::copied == 0); + assert(RHS::copied == 0); +} + +template <class Tp> +void test_swap_empty() { + assert(Tp::count == 0); + { + any a1((Tp(1))); + any a2; + assert(Tp::count == 1); + + a1.swap(a2); + + assert(Tp::count == 1); + + assertContains<Tp>(a2, 1); + assertEmpty(a1); + } + assert(Tp::count == 0); + { + any a1((Tp(1))); + any a2; + assert(Tp::count == 1); + + a2.swap(a1); + + assert(Tp::count == 1); + + assertContains<Tp>(a2, 1); + assertEmpty(a1); + } + assert(Tp::count == 0); + assert(Tp::copied == 0); +} + +void test_noexcept() +{ + any a1; + any a2; + static_assert( + noexcept(a1.swap(a2)) + , "any::swap(any&) must be noexcept" + ); +} + +void test_self_swap() { + { + // empty + any a; + a.swap(a); + assertEmpty(a); + } + { // small + using T = small; + any a{T{42}}; + T::reset(); + a.swap(a); + assertContains<T>(a, 42); + assert(T::count == 1); + assert(T::copied == 0); + LIBCPP_ASSERT(T::moved == 0); + } + assert(small::count == 0); + { // large + using T = large; + any a{T{42}}; + T::reset(); + a.swap(a); + assertContains<T>(a, 42); + assert(T::count == 1); + assert(T::copied == 0); + LIBCPP_ASSERT(T::moved == 0); + } + assert(large::count == 0); +} + +int main() +{ + test_noexcept(); + test_swap_empty<small>(); + test_swap_empty<large>(); + test_swap<small1, small2>(); + test_swap<large1, large2>(); + test_swap<small, large>(); + test_swap<large, small>(); + test_self_swap(); +} diff --git a/test/std/utilities/any/any.class/any.observers/has_value.pass.cpp b/test/std/utilities/any/any.class/any.observers/has_value.pass.cpp new file mode 100644 index 000000000000..072ac06776c1 --- /dev/null +++ b/test/std/utilities/any/any.class/any.observers/has_value.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// any::has_value() noexcept + +#include <any> +#include <cassert> + +#include "any_helpers.h" + +int main() +{ + using std::any; + // noexcept test + { + any a; + static_assert(noexcept(a.has_value()), "any::has_value() must be noexcept"); + } + // empty + { + any a; + assert(!a.has_value()); + + a.reset(); + assert(!a.has_value()); + + a = 42; + assert(a.has_value()); + } + // small object + { + small const s(1); + any a(s); + assert(a.has_value()); + + a.reset(); + assert(!a.has_value()); + + a = s; + assert(a.has_value()); + } + // large object + { + large const l(1); + any a(l); + assert(a.has_value()); + + a.reset(); + assert(!a.has_value()); + + a = l; + assert(a.has_value()); + } +} diff --git a/test/std/utilities/any/any.class/any.observers/type.pass.cpp b/test/std/utilities/any/any.class/any.observers/type.pass.cpp new file mode 100644 index 000000000000..984c4137db09 --- /dev/null +++ b/test/std/utilities/any/any.class/any.observers/type.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// XFAIL: libcpp-no-rtti + +// <any> + +// any::type() noexcept + +#include <any> +#include <cassert> +#include "any_helpers.h" + +int main() +{ + using std::any; + { + any const a; + assert(a.type() == typeid(void)); + static_assert(noexcept(a.type()), "any::type() must be noexcept"); + } + { + small const s(1); + any const a(s); + assert(a.type() == typeid(small)); + + } + { + large const l(1); + any const a(l); + assert(a.type() == typeid(large)); + } +} diff --git a/test/std/utilities/any/any.class/not_literal_type.pass.cpp b/test/std/utilities/any/any.class/not_literal_type.pass.cpp new file mode 100644 index 000000000000..91ef5c970a22 --- /dev/null +++ b/test/std/utilities/any/any.class/not_literal_type.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// [Note any is a not a literal type --end note] + +#include <any> +#include <type_traits> + +int main () { + static_assert(!std::is_literal_type<std::any>::value, ""); +} diff --git a/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp b/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp new file mode 100644 index 000000000000..1a5a85482b8f --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp @@ -0,0 +1,171 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType const* any_cast(any const *) noexcept; +// +// template <class ValueType> +// ValueType * any_cast(any *) noexcept; + +#include <any> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" + +using std::any; +using std::any_cast; + +// Test that the operators are properly noexcept. +void test_cast_is_noexcept() { + any a; + static_assert(noexcept(any_cast<int>(&a)), ""); + + any const& ca = a; + static_assert(noexcept(any_cast<int>(&ca)), ""); +} + +// Test that the return type of any_cast is correct. +void test_cast_return_type() { + any a; + static_assert(std::is_same<decltype(any_cast<int>(&a)), int*>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(&a)), int const*>::value, ""); + + any const& ca = a; + static_assert(std::is_same<decltype(any_cast<int>(&ca)), int const*>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(&ca)), int const*>::value, ""); +} + +// Test that any_cast handles null pointers. +void test_cast_nullptr() { + any* a = nullptr; + assert(nullptr == any_cast<int>(a)); + assert(nullptr == any_cast<int const>(a)); + + any const* ca = nullptr; + assert(nullptr == any_cast<int>(ca)); + assert(nullptr == any_cast<int const>(ca)); +} + +// Test casting an empty object. +void test_cast_empty() { + { + any a; + assert(nullptr == any_cast<int>(&a)); + assert(nullptr == any_cast<int const>(&a)); + + any const& ca = a; + assert(nullptr == any_cast<int>(&ca)); + assert(nullptr == any_cast<int const>(&ca)); + } + // Create as non-empty, then make empty and run test. + { + any a(42); + a.reset(); + assert(nullptr == any_cast<int>(&a)); + assert(nullptr == any_cast<int const>(&a)); + + any const& ca = a; + assert(nullptr == any_cast<int>(&ca)); + assert(nullptr == any_cast<int const>(&ca)); + } +} + +template <class Type> +void test_cast() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + any const& ca = a; + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Try a cast to a bad type. + // NOTE: Type cannot be an int. + assert(any_cast<int>(&a) == nullptr); + assert(any_cast<int const>(&a) == nullptr); + assert(any_cast<int const volatile>(&a) == nullptr); + + // Try a cast to the right type, but as a pointer. + assert(any_cast<Type*>(&a) == nullptr); + assert(any_cast<Type const*>(&a) == nullptr); + + // Check getting a unqualified type from a non-const any. + Type* v = any_cast<Type>(&a); + assert(v != nullptr); + assert(v->value == 42); + + // change the stored value and later check for the new value. + v->value = 999; + + // Check getting a const qualified type from a non-const any. + Type const* cv = any_cast<Type const>(&a); + assert(cv != nullptr); + assert(cv == v); + assert(cv->value == 999); + + // Check getting a unqualified type from a const any. + cv = any_cast<Type>(&ca); + assert(cv != nullptr); + assert(cv == v); + assert(cv->value == 999); + + // Check getting a const-qualified type from a const any. + cv = any_cast<Type const>(&ca); + assert(cv != nullptr); + assert(cv == v); + assert(cv->value == 999); + + // Check that no more objects were created, copied or moved. + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + } + assert(Type::count == 0); +} + +void test_cast_non_copyable_type() +{ + // Even though 'any' never stores non-copyable types + // we still need to support any_cast<NoCopy>(ptr) + struct NoCopy { NoCopy(NoCopy const&) = delete; }; + std::any a(42); + std::any const& ca = a; + assert(std::any_cast<NoCopy>(&a) == nullptr); + assert(std::any_cast<NoCopy>(&ca) == nullptr); +} + +void test_fn() {} + +void test_cast_function_pointer() { + using T = void(*)(); + std::any a(test_fn); + // An any can never store a function type, but we should at least be able + // to ask. + assert(std::any_cast<void()>(&a) == nullptr); + T fn_ptr = std::any_cast<T>(a); + assert(fn_ptr == test_fn); +} + +int main() { + test_cast_is_noexcept(); + test_cast_return_type(); + test_cast_nullptr(); + test_cast_empty(); + test_cast<small>(); + test_cast<large>(); + test_cast_non_copyable_type(); + test_cast_function_pointer(); +} diff --git a/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp b/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp new file mode 100644 index 000000000000..af081ecceefd --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp @@ -0,0 +1,313 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType const any_cast(any const&); +// +// template <class ValueType> +// ValueType any_cast(any &); +// +// template <class ValueType> +// ValueType any_cast(any &&); + +#include <any> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; +using std::bad_any_cast; + + +// Test that the operators are NOT marked noexcept. +void test_cast_is_not_noexcept() { + any a; + static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), ""); + static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), ""); + static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), ""); +} + +// Test that the return type of any_cast is correct. +void test_cast_return_type() { + any a; + static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, ""); + + static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, ""); + + static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, ""); + + static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, ""); + + any const& ca = a; + static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, ""); + + static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, ""); +} + +template <class Type, class ConstT = Type> +void checkThrows(any& a) +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + try { + any_cast<Type>(a); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + + try { + any_cast<ConstT>(static_cast<any const&>(a)); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + + try { + using RefType = typename std::conditional< + std::is_lvalue_reference<Type>::value, + typename std::remove_reference<Type>::type&&, + Type + >::type; + any_cast<RefType>(static_cast<any&&>(a)); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } +#else + ((void)a); +#endif +} + +void test_cast_empty() { + // None of these operations should allocate. + DisableAllocationGuard g; ((void)g); + any a; + checkThrows<int>(a); +} + +template <class Type> +void test_cast_to_reference() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + any const& ca = a; + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Try a cast to a bad type. + // NOTE: Type cannot be an int. + checkThrows<int>(a); + checkThrows<int&, int const&>(a); + checkThrows<Type*, Type const*>(a); + checkThrows<Type const*>(a); + + // Check getting a type by reference from a non-const lvalue any. + { + Type& v = any_cast<Type&>(a); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(a); + assert(&cv == &v); + } + // Check getting a type by reference from a const lvalue any. + { + Type const& v = any_cast<Type const&>(ca); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(ca); + assert(&cv == &v); + } + // Check getting a type by reference from a const rvalue any. + { + Type const& v = any_cast<Type const&>(std::move(ca)); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(std::move(ca)); + assert(&cv == &v); + } + // Check getting a type by reference from a const rvalue any. + { + Type&& v = any_cast<Type&&>(std::move(a)); + assert(v.value == 42); + assert(any_cast<Type&>(a).value == 42); + + Type&& cv = any_cast<Type&&>(std::move(a)); + assert(&cv == &v); + assert(any_cast<Type&>(a).value == 42); + } + // Check getting a type by reference from a const rvalue any. + { + Type const&& v = any_cast<Type const&&>(std::move(a)); + assert(v.value == 42); + assert(any_cast<Type&>(a).value == 42); + + Type const&& cv = any_cast<Type const&&>(std::move(a)); + assert(&cv == &v); + assert(any_cast<Type&>(a).value == 42); + } + // Check that the original object hasn't been changed. + assertContains<Type>(a, 42); + + // Check that no objects have been created/copied/moved. + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + } + assert(Type::count == 0); +} + +template <class Type> +void test_cast_to_value() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Try a cast to a bad type. + // NOTE: Type cannot be an int. + checkThrows<int>(a); + checkThrows<int&, int const&>(a); + checkThrows<Type*, Type const*>(a); + checkThrows<Type const*>(a); + + Type::reset(); // NOTE: reset does not modify Type::count + // Check getting Type by value from a non-const lvalue any. + // This should cause the non-const copy constructor to be called. + { + Type t = any_cast<Type>(a); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 1); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting const Type by value from a non-const lvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type const>(a); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 1); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting Type by value from a non-const lvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type>(static_cast<any const&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 1); + assert(Type::non_const_copied == 0); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting Type by value from a non-const rvalue any. + // This should cause the non-const copy constructor to be called. + { + Type t = any_cast<Type>(static_cast<any &&>(a)); + + assert(Type::count == 2); + assert(Type::moved == 1); + assert(Type::copied == 0); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 0); + assert(t.value == 42); + assert(any_cast<Type&>(a).value == 0); + any_cast<Type&>(a).value = 42; // reset the value + } + assert(Type::count == 1); + Type::reset(); + // Check getting const Type by value from a non-const rvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type const>(static_cast<any &&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 0); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 0); + assert(Type::moved == 1); + assert(t.value == 42); + assert(any_cast<Type&>(a).value == 0); + any_cast<Type&>(a).value = 42; // reset the value + } + assert(Type::count == 1); + Type::reset(); + // Check getting Type by value from a const rvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type>(static_cast<any const&&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 1); + assert(Type::non_const_copied == 0); + assert(Type::moved == 0); + assert(t.value == 42); + assert(any_cast<Type&>(a).value == 42); + } + // Ensure we still only have 1 Type object alive. + assert(Type::count == 1); + + // Check that the original object hasn't been changed. + assertContains<Type>(a, 42); + } + assert(Type::count == 0); +} + +int main() { + test_cast_is_not_noexcept(); + test_cast_return_type(); + test_cast_empty(); + test_cast_to_reference<small>(); + test_cast_to_reference<large>(); + test_cast_to_value<small>(); + test_cast_to_value<large>(); +} diff --git a/test/std/utilities/any/any.nonmembers/any.cast/any_cast_request_invalid_value_category.fail.cpp b/test/std/utilities/any/any.nonmembers/any.cast/any_cast_request_invalid_value_category.fail.cpp new file mode 100644 index 000000000000..07578a28e82f --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/any.cast/any_cast_request_invalid_value_category.fail.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType any_cast(any &&); + +// Try and use the rvalue any_cast to cast to an lvalue reference + +#include <any> + +struct TestType {}; +using std::any; +using std::any_cast; + +void test_const_lvalue_cast_request_non_const_lvalue() +{ + const any a; + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{binding value of type 'const TestType' to reference to type 'TestType' drops 'const' qualifier}} + any_cast<TestType &>(a); // expected-note {{requested here}} + + const any a2(42); + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{binding value of type 'const int' to reference to type 'int' drops 'const' qualifier}} + any_cast<int&>(a2); // expected-note {{requested here}} +} + +void test_lvalue_any_cast_request_rvalue() +{ + any a; + // expected-error@any:* {{static_assert failed "ValueType is required to be an lvalue reference or a CopyConstructible type"}} + any_cast<TestType &&>(a); // expected-note {{requested here}} + + any a2(42); + // expected-error@any:* {{static_assert failed "ValueType is required to be an lvalue reference or a CopyConstructible type"}} + any_cast<int&&>(a2); // expected-note {{requested here}} +} + +void test_rvalue_any_cast_request_lvalue() +{ + any a; + // expected-error@any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{non-const lvalue reference to type 'TestType' cannot bind to a temporary}} + any_cast<TestType &>(std::move(a)); // expected-note {{requested here}} + + // expected-error@any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{non-const lvalue reference to type 'int' cannot bind to a temporary}} + any_cast<int&>(42); +} + +int main() +{ + test_const_lvalue_cast_request_non_const_lvalue(); + test_lvalue_any_cast_request_rvalue(); + test_rvalue_any_cast_request_lvalue(); +} diff --git a/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp b/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp new file mode 100644 index 000000000000..3f6955a8cbce --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType any_cast(any const &); + +// Try and cast away const. + +#include <any> + +struct TestType {}; +struct TestType2 {}; + +int main() +{ + using std::any; + using std::any_cast; + + any a; + + // expected-error@any:* {{binding value of type 'const TestType' to reference to type 'TestType' drops 'const' qualifier}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + any_cast<TestType &>(static_cast<any const&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{cannot cast from lvalue of type 'const TestType' to rvalue reference type 'TestType &&'; types are not compatible}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + any_cast<TestType &&>(static_cast<any const&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{binding value of type 'const TestType2' to reference to type 'TestType2' drops 'const' qualifier}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + any_cast<TestType2 &>(static_cast<any const&&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{cannot cast from lvalue of type 'const TestType2' to rvalue reference type 'TestType2 &&'; types are not compatible}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + any_cast<TestType2 &&>(static_cast<any const&&>(a)); // expected-note {{requested here}} +} diff --git a/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp b/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp new file mode 100644 index 000000000000..ed4b96d644d2 --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType const any_cast(any const&); +// +// template <class ValueType> +// ValueType any_cast(any &); +// +// template <class ValueType> +// ValueType any_cast(any &&); + +// Test instantiating the any_cast with a non-copyable type. + +#include <any> + +using std::any; +using std::any_cast; + +struct no_copy +{ + no_copy() {} + no_copy(no_copy &&) {} + no_copy(no_copy const &) = delete; +}; + +struct no_move { + no_move() {} + no_move(no_move&&) = delete; + no_move(no_move const&) {} +}; + +int main() { + any a; + // expected-error@any:* {{static_assert failed "ValueType is required to be an lvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{static_cast from 'no_copy' to 'no_copy' uses deleted function}} + any_cast<no_copy>(static_cast<any&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{static_assert failed "ValueType is required to be a const lvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{static_cast from 'const no_copy' to 'no_copy' uses deleted function}} + any_cast<no_copy>(static_cast<any const&>(a)); // expected-note {{requested here}} + + any_cast<no_copy>(static_cast<any &&>(a)); // OK + + // expected-error@any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{static_cast from 'typename remove_reference<no_move &>::type' (aka 'no_move') to 'no_move' uses deleted function}} + any_cast<no_move>(static_cast<any &&>(a)); +} diff --git a/test/std/utilities/any/any.nonmembers/any.cast/reference_types.fail.cpp b/test/std/utilities/any/any.nonmembers/any.cast/reference_types.fail.cpp new file mode 100644 index 000000000000..99cc029971a8 --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/any.cast/reference_types.fail.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType const* any_cast(any const *) noexcept; +// +// template <class ValueType> +// ValueType * any_cast(any *) noexcept; + +#include <any> + +using std::any; +using std::any_cast; + +int main() +{ + any a(1); + any_cast<int &>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int &&>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const &>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const&&>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any const& a2 = a; + any_cast<int &>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int &&>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const &>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const &&>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} +} diff --git a/test/std/utilities/any/any.nonmembers/make_any.pass.cpp b/test/std/utilities/any/any.nonmembers/make_any.pass.cpp new file mode 100644 index 000000000000..59c06be6aad3 --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/make_any.pass.cpp @@ -0,0 +1,140 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class T, class ...Args> any make_any(Args&&...); +// template <class T, class U, class ...Args> +// any make_any(initializer_list<U>, Args&&...); + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + + +template <class Type> +void test_make_any_type() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + any a = std::make_any<Type>(); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 0); + } + assert(Type::count == 0); + Type::reset(); + { + any a = std::make_any<Type>(101); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 101); + } + assert(Type::count == 0); + Type::reset(); + { + any a = std::make_any<Type>(-1, 42, -1); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); +} + +template <class Type> +void test_make_any_type_tracked() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + { + any a = std::make_any<Type>(); + assertArgsMatch<Type>(a); + } + { + any a = std::make_any<Type>(-1, 42, -1); + assertArgsMatch<Type, int, int, int>(a); + } + // initializer_list constructor tests + { + any a = std::make_any<Type>({-1, 42, -1}); + assertArgsMatch<Type, std::initializer_list<int>>(a); + } + { + int x = 42; + any a = std::make_any<Type>({-1, 42, -1}, x); + assertArgsMatch<Type, std::initializer_list<int>, int&>(a); + } +} + +#ifndef TEST_HAS_NO_EXCEPTIONS + +struct SmallThrows { + SmallThrows(int) { throw 42; } + SmallThrows(std::initializer_list<int>, int) { throw 42; } +}; +static_assert(IsSmallObject<SmallThrows>::value, ""); + +struct LargeThrows { + LargeThrows(int) { throw 42; } + LargeThrows(std::initializer_list<int>, int) { throw 42; } + int data[sizeof(std::any)]; +}; +static_assert(!IsSmallObject<LargeThrows>::value, ""); + +template <class Type> +void test_make_any_throws() +{ + { + try { + std::make_any<Type>(101); + assert(false); + } catch (int const&) { + } + } + { + try { + std::make_any<Type>({1, 2, 3}, 101); + assert(false); + } catch (int const&) { + } + } +} + +#endif + +int main() { + test_make_any_type<small>(); + test_make_any_type<large>(); + test_make_any_type<small_throws_on_copy>(); + test_make_any_type<large_throws_on_copy>(); + test_make_any_type<throws_on_move>(); + test_make_any_type_tracked<small_tracked_t>(); + test_make_any_type_tracked<large_tracked_t>(); +#ifndef TEST_HAS_NO_EXCEPTIONS + test_make_any_throws<SmallThrows>(); + test_make_any_throws<LargeThrows>(); + +#endif +} diff --git a/test/std/utilities/any/any.nonmembers/swap.pass.cpp b/test/std/utilities/any/any.nonmembers/swap.pass.cpp new file mode 100644 index 000000000000..1b3785bb1c66 --- /dev/null +++ b/test/std/utilities/any/any.nonmembers/swap.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// void swap(any &, any &) noexcept + +// swap(...) just wraps any::swap(...). That function is tested elsewhere. + +#include <any> +#include <cassert> + +using std::any; +using std::any_cast; + +int main() +{ + + { // test noexcept + any a; + static_assert(noexcept(swap(a, a)), "swap(any&, any&) must be noexcept"); + } + { + any a1(1); + any a2(2); + + swap(a1, a2); + + assert(any_cast<int>(a1) == 2); + assert(any_cast<int>(a2) == 1); + } +} diff --git a/test/std/utilities/function.objects/arithmetic.operations/divides.pass.cpp b/test/std/utilities/function.objects/arithmetic.operations/divides.pass.cpp index 490dc16b60e2..7419b70e0b8f 100644 --- a/test/std/utilities/function.objects/arithmetic.operations/divides.pass.cpp +++ b/test/std/utilities/function.objects/arithmetic.operations/divides.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::divides<int> F; @@ -23,7 +25,7 @@ int main() static_assert((std::is_same<int, F::second_argument_type>::value), "" ); static_assert((std::is_same<int, F::result_type>::value), "" ); assert(f(36, 4) == 9); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::divides<> F2; const F2 f2 = F2(); assert(f2(36, 4) == 9); @@ -33,7 +35,7 @@ int main() constexpr int foo = std::divides<int> () (3, 2); static_assert ( foo == 1, "" ); - constexpr int bar = std::divides<> () (3.0, 2); - static_assert ( bar == 1, "" ); + constexpr double bar = std::divides<> () (3.0, 2); + static_assert ( bar == 1.5, "" ); // exact in binary #endif } diff --git a/test/std/utilities/function.objects/arithmetic.operations/minus.pass.cpp b/test/std/utilities/function.objects/arithmetic.operations/minus.pass.cpp index 9bda541f896a..25df69d60e96 100644 --- a/test/std/utilities/function.objects/arithmetic.operations/minus.pass.cpp +++ b/test/std/utilities/function.objects/arithmetic.operations/minus.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::minus<int> F; @@ -23,7 +25,7 @@ int main() static_assert((std::is_same<int, F::second_argument_type>::value), "" ); static_assert((std::is_same<int, F::result_type>::value), "" ); assert(f(3, 2) == 1); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::minus<> F2; const F2 f2 = F2(); assert(f2(3,2) == 1); @@ -33,7 +35,7 @@ int main() constexpr int foo = std::minus<int> () (3, 2); static_assert ( foo == 1, "" ); - constexpr int bar = std::minus<> () (3.0, 2); - static_assert ( bar == 1, "" ); + constexpr double bar = std::minus<> () (3.0, 2); + static_assert ( bar == 1.0, "" ); #endif } diff --git a/test/std/utilities/function.objects/arithmetic.operations/modulus.pass.cpp b/test/std/utilities/function.objects/arithmetic.operations/modulus.pass.cpp index ca5bba6d5b8e..6f39792e925f 100644 --- a/test/std/utilities/function.objects/arithmetic.operations/modulus.pass.cpp +++ b/test/std/utilities/function.objects/arithmetic.operations/modulus.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::modulus<int> F; @@ -23,7 +25,7 @@ int main() static_assert((std::is_same<int, F::second_argument_type>::value), "" ); static_assert((std::is_same<int, F::result_type>::value), "" ); assert(f(36, 8) == 4); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::modulus<> F2; const F2 f2 = F2(); assert(f2(36, 8) == 4); diff --git a/test/std/utilities/function.objects/arithmetic.operations/multiplies.pass.cpp b/test/std/utilities/function.objects/arithmetic.operations/multiplies.pass.cpp index f132c8d4bd9b..2b354826960e 100644 --- a/test/std/utilities/function.objects/arithmetic.operations/multiplies.pass.cpp +++ b/test/std/utilities/function.objects/arithmetic.operations/multiplies.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::multiplies<int> F; @@ -23,7 +25,7 @@ int main() static_assert((std::is_same<int, F::second_argument_type>::value), "" ); static_assert((std::is_same<int, F::result_type>::value), "" ); assert(f(3, 2) == 6); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::multiplies<> F2; const F2 f2 = F2(); assert(f2(3,2) == 6); @@ -33,7 +35,7 @@ int main() constexpr int foo = std::multiplies<int> () (3, 2); static_assert ( foo == 6, "" ); - constexpr int bar = std::multiplies<> () (3.0, 2); - static_assert ( bar == 6, "" ); + constexpr double bar = std::multiplies<> () (3.0, 2); + static_assert ( bar == 6.0, "" ); #endif } diff --git a/test/std/utilities/function.objects/arithmetic.operations/negate.pass.cpp b/test/std/utilities/function.objects/arithmetic.operations/negate.pass.cpp index 0adac659123b..198894023cd7 100644 --- a/test/std/utilities/function.objects/arithmetic.operations/negate.pass.cpp +++ b/test/std/utilities/function.objects/arithmetic.operations/negate.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::negate<int> F; @@ -22,7 +24,7 @@ int main() static_assert((std::is_same<F::argument_type, int>::value), "" ); static_assert((std::is_same<F::result_type, int>::value), "" ); assert(f(36) == -36); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::negate<> F2; const F2 f2 = F2(); assert(f2(36) == -36); @@ -32,7 +34,7 @@ int main() constexpr int foo = std::negate<int> () (3); static_assert ( foo == -3, "" ); - constexpr int bar = std::negate<> () (3.0); - static_assert ( bar == -3, "" ); + constexpr double bar = std::negate<> () (3.0); + static_assert ( bar == -3.0, "" ); #endif } diff --git a/test/std/utilities/function.objects/arithmetic.operations/plus.pass.cpp b/test/std/utilities/function.objects/arithmetic.operations/plus.pass.cpp index ce544c78b676..b56d3ef2b346 100644 --- a/test/std/utilities/function.objects/arithmetic.operations/plus.pass.cpp +++ b/test/std/utilities/function.objects/arithmetic.operations/plus.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::plus<int> F; @@ -23,7 +25,7 @@ int main() static_assert((std::is_same<int, F::second_argument_type>::value), "" ); static_assert((std::is_same<int, F::result_type>::value), "" ); assert(f(3, 2) == 5); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::plus<> F2; const F2 f2 = F2(); assert(f2(3,2) == 5); @@ -33,7 +35,7 @@ int main() constexpr int foo = std::plus<int> () (3, 2); static_assert ( foo == 5, "" ); - constexpr int bar = std::plus<> () (3.0, 2); - static_assert ( bar == 5, "" ); + constexpr double bar = std::plus<> () (3.0, 2); + static_assert ( bar == 5.0, "" ); #endif } diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/bind_return_type.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/bind_return_type.pass.cpp index 63d3c9b0de92..a543fffedbb5 100644 --- a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/bind_return_type.pass.cpp +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/bind_return_type.pass.cpp @@ -24,6 +24,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int dummy = 42; int return_value(int) { return dummy; } @@ -81,10 +83,10 @@ void do_test(Fn* func) { // Check that the call operator SFINAE's away when too few arguments // are provided but is well-formed otherwise. { - static_assert(!CheckCall<Bind>(), ""); + LIBCPP_STATIC_ASSERT(!CheckCall<Bind>(), ""); static_assert(CheckCall<Bind, int>(), ""); static_assert(CheckCall<Bind, int, int>(), ""); - static_assert(!CheckCall<BindR>(), ""); + LIBCPP_STATIC_ASSERT(!CheckCall<BindR>(), ""); static_assert(CheckCall<BindR, int>(), ""); static_assert(CheckCall<BindR, int, int>(), ""); } @@ -108,7 +110,7 @@ void do_test_r(Fn* func) { // Check that the call operator SFINAE's away when too few arguments // are provided but is well-formed otherwise. { - static_assert(!CheckCall<Bind>(), ""); + LIBCPP_STATIC_ASSERT(!CheckCall<Bind>(), ""); static_assert(CheckCall<Bind, int>(), ""); static_assert(CheckCall<Bind, int, int>(), ""); } diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp index a0c686de77ba..180433109f26 100644 --- a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp @@ -29,7 +29,7 @@ struct DummyUnaryFunction struct BadUnaryFunction { template <typename S> - constexpr int operator()(S const & s) const + constexpr int operator()(S const &) const { // Trigger a compile error if this function is instantiated. // The constexpr is needed so that it is instantiated while checking diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp index f61d93aefd89..0d4244b4d860 100644 --- a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp @@ -28,7 +28,7 @@ struct power T operator()(T a, T b) { - return std::pow(a, b); + return static_cast<T>(std::pow(a, b)); } }; diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp index 83fa452fecb3..5d833e28830b 100644 --- a/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp @@ -14,12 +14,16 @@ // template<class T> struct is_bind_expression #include <functional> +#include "test_macros.h" template <bool Expected, class T> void test(const T&) { static_assert(std::is_bind_expression<T>::value == Expected, ""); +#if TEST_STD_VER > 14 + static_assert(std::is_bind_expression_v<T> == Expected, ""); +#endif } struct C {}; diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp index 6a52bd1848e9..1d7c649dfc0e 100644 --- a/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp @@ -12,12 +12,16 @@ // struct is_placeholder #include <functional> +#include "test_macros.h" template <int Expected, class T> void test(const T&) { static_assert(std::is_placeholder<T>::value == Expected, ""); +#if TEST_STD_VER > 14 + static_assert(std::is_placeholder_v<T> == Expected, ""); +#endif } struct C {}; diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.place/placeholders.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.place/placeholders.pass.cpp index 68986ac1aeb3..59709d0ed5b2 100644 --- a/test/std/utilities/function.objects/bind/func.bind/func.bind.place/placeholders.pass.cpp +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.place/placeholders.pass.cpp @@ -56,8 +56,34 @@ constexpr decltype(std::placeholders::_9) cp9 = std::placeholders::_9; constexpr decltype(std::placeholders::_10) cp10 = std::placeholders::_10; #endif // TEST_STD_VER >= 11 +void use_placeholders_to_prevent_unused_warning() { +#if TEST_STD_VER >= 11 + ((void)cp1); + ((void)cp2); + ((void)cp3); + ((void)cp4); + ((void)cp5); + ((void)cp6); + ((void)cp7); + ((void)cp8); + ((void)cp9); + ((void)cp10); + ((void)default1); + ((void)default2); + ((void)default3); + ((void)default4); + ((void)default5); + ((void)default6); + ((void)default7); + ((void)default8); + ((void)default9); + ((void)default10); +#endif +} + int main() { + use_placeholders_to_prevent_unused_warning(); test(std::placeholders::_1); test(std::placeholders::_2); test(std::placeholders::_3); diff --git a/test/std/utilities/function.objects/bitwise.operations/bit_and.pass.cpp b/test/std/utilities/function.objects/bitwise.operations/bit_and.pass.cpp index c0135fad1982..12d968f42c0a 100644 --- a/test/std/utilities/function.objects/bitwise.operations/bit_and.pass.cpp +++ b/test/std/utilities/function.objects/bitwise.operations/bit_and.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::bit_and<int> F; @@ -27,7 +29,7 @@ int main() assert(f(0x58D3, 0xEA95) == 0x4891); assert(f(0x58D3, 0) == 0); assert(f(0xFFFF, 0x58D3) == 0x58D3); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::bit_and<> F2; const F2 f2 = F2(); assert(f2(0xEA95, 0xEA95) == 0xEA95); diff --git a/test/std/utilities/function.objects/bitwise.operations/bit_or.pass.cpp b/test/std/utilities/function.objects/bitwise.operations/bit_or.pass.cpp index cb33df3d84b7..90dd9bc098bb 100644 --- a/test/std/utilities/function.objects/bitwise.operations/bit_or.pass.cpp +++ b/test/std/utilities/function.objects/bitwise.operations/bit_or.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::bit_or<int> F; @@ -27,7 +29,7 @@ int main() assert(f(0x58D3, 0xEA95) == 0xFAD7); assert(f(0x58D3, 0) == 0x58D3); assert(f(0xFFFF, 0x58D3) == 0xFFFF); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::bit_or<> F2; const F2 f2 = F2(); assert(f2(0xEA95, 0xEA95) == 0xEA95); diff --git a/test/std/utilities/function.objects/bitwise.operations/bit_xor.pass.cpp b/test/std/utilities/function.objects/bitwise.operations/bit_xor.pass.cpp index bbf2ce5baf1b..a5cbd17a0d0e 100644 --- a/test/std/utilities/function.objects/bitwise.operations/bit_xor.pass.cpp +++ b/test/std/utilities/function.objects/bitwise.operations/bit_xor.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { { @@ -29,7 +31,7 @@ int main() assert(f(0x58D3, 0) == 0x58D3); assert(f(0xFFFF, 0x58D3) == 0xA72C); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { typedef std::bit_xor<> F2; const F2 f = F2(); diff --git a/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.hpp b/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.hpp index 66d783a6e357..b23d4e8bb478 100644 --- a/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.hpp +++ b/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.hpp @@ -19,13 +19,13 @@ void do_pointer_comparison_test() { #endif std::vector<std::shared_ptr<T> > pointers; const std::size_t test_size = 100; - for (int i=0; i < test_size; ++i) + for (size_t i=0; i < test_size; ++i) pointers.push_back(std::shared_ptr<T>(new T())); Compare comp; UIntCompare ucomp; VoidCompare vcomp; - for (int i=0; i < test_size; ++i) { - for (int j=0; j < test_size; ++j) { + for (size_t i=0; i < test_size; ++i) { + for (size_t j=0; j < test_size; ++j) { T* lhs = pointers[i].get(); T* rhs = pointers[j].get(); std::uintptr_t lhs_uint = reinterpret_cast<std::uintptr_t>(lhs); diff --git a/test/std/utilities/function.objects/func.invoke/invoke_feature_test_macro.pass.cpp b/test/std/utilities/function.objects/func.invoke/invoke_feature_test_macro.pass.cpp new file mode 100644 index 000000000000..aaac98474fcb --- /dev/null +++ b/test/std/utilities/function.objects/func.invoke/invoke_feature_test_macro.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <functional> + +// template <class F, class ...Args> +// result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...); + +#include <functional> +#include <cassert> + +#include "test_macros.h" + +#if TEST_STD_VER <= 14 +# ifdef __cpp_lib_invoke +# error Feature test macro should be defined +# endif +#else +# ifndef __cpp_lib_invoke +# error Feature test macro not defined +# endif +# if __cpp_lib_invoke != 201411 +# error __cpp_lib_invoke has the wrong value +# endif +#endif + +int foo(int) { return 42; } + +int main() { +#if defined(__cpp_lib_invoke) + assert(std::invoke(foo, 101) == 42); +#endif +}
\ No newline at end of file diff --git a/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp b/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp index c12fa7920974..47a3e1cc5969 100644 --- a/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp +++ b/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp @@ -138,26 +138,26 @@ inline constexpr CallType operator|(CallType LHS, CallType RHS) { struct ForwardingCallObject { template <class ...Args> - bool operator()(Args&&... args) & { + bool operator()(Args&&...) & { set_call<Args&&...>(CT_NonConst | CT_LValue); return true; } template <class ...Args> - bool operator()(Args&&... args) const & { + bool operator()(Args&&...) const & { set_call<Args&&...>(CT_Const | CT_LValue); return true; } // Don't allow the call operator to be invoked as an rvalue. template <class ...Args> - bool operator()(Args&&... args) && { + bool operator()(Args&&...) && { set_call<Args&&...>(CT_NonConst | CT_RValue); return true; } template <class ...Args> - bool operator()(Args&&... args) const && { + bool operator()(Args&&...) const && { set_call<Args&&...>(CT_Const | CT_RValue); return true; } @@ -526,7 +526,6 @@ void call_operator_forwarding_test() assert(Fn::check_call<int&&>(CT_Const | CT_RValue)); } { // test multi arg - int x = 42; const double y = 3.14; std::string s = "abc"; obj(42, std::move(y), s, std::string{"foo"}); @@ -554,7 +553,10 @@ void call_operator_noexcept_test() using T = NoExceptCallable<bool>; T value(true); auto ret = std::not_fn(value); - static_assert(noexcept(!_VSTD::__invoke(value)), ""); + LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), ""); +#if TEST_STD_VER > 14 + static_assert(noexcept(!std::invoke(value)), ""); +#endif static_assert(noexcept(ret()), "call should be noexcept"); auto const& cret = ret; static_assert(noexcept(cret()), "call should be noexcept"); @@ -577,6 +579,19 @@ void call_operator_noexcept_test() } } +void test_lwg2767() { + // See http://wg21.link/LWG2767 + struct Abstract { virtual void f() const = 0; }; + struct Derived : public Abstract { void f() const {} }; + struct F { bool operator()(Abstract&&) { return false; } }; + { + Derived d; + Abstract &a = d; + bool b = std::not_fn(F{})(std::move(a)); + assert(b); + } +} + int main() { constructor_tests(); @@ -586,4 +601,5 @@ int main() call_operator_sfinae_test(); // somewhat of an extension call_operator_forwarding_test(); call_operator_noexcept_test(); + test_lwg2767(); } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/derive_from.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/derive_from.fail.cpp new file mode 100644 index 000000000000..e156fa966ac5 --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/derive_from.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// XFAIL: c++11, c++14 + +// <functional> + +#include <functional> +#include <type_traits> + +#include "test_macros.h" + +struct S : public std::function<void()> { using function::function; }; + +int main() { + S f1( [](){} ); + S f2(std::allocator_arg, std::allocator<int>{}, f1); +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/derive_from.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/derive_from.pass.cpp new file mode 100644 index 000000000000..5bdf9e98e897 --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/derive_from.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// REQUIRES-ANY: c++11, c++14 + +// <functional> + +// See https://llvm.org/bugs/show_bug.cgi?id=20002 + +#include <functional> +#include <type_traits> + +#include "test_macros.h" + +using Fn = std::function<void()>; +struct S : public std::function<void()> { using function::function; }; + +int main() { + S s( [](){} ); + S f1( s ); + S f2(std::allocator_arg, std::allocator<int>{}, s); +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp index 58192c928d58..1a9206e0e7f3 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp @@ -12,13 +12,14 @@ // class function<R(ArgTypes...)> // template <MoveConstructible R, MoveConstructible ... ArgTypes> -// void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&); +// void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept; #include <functional> #include <cstdlib> #include <cassert> +#include "test_macros.h" #include "count_new.hpp" class A @@ -63,6 +64,9 @@ int main() { std::function<int(int)> f1 = A(1); std::function<int(int)> f2 = A(2); +#if TEST_STD_VER >= 11 + static_assert(noexcept(swap(f1, f2)), "" ); +#endif assert(A::count == 2); assert(globalMemCounter.checkOutstandingNewEq(2)); assert(f1.target<A>()->id() == 1); @@ -78,6 +82,9 @@ int main() { std::function<int(int)> f1 = A(1); std::function<int(int)> f2 = g; +#if TEST_STD_VER >= 11 + static_assert(noexcept(swap(f1, f2)), "" ); +#endif assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f1.target<A>()->id() == 1); @@ -93,6 +100,9 @@ int main() { std::function<int(int)> f1 = g; std::function<int(int)> f2 = A(1); +#if TEST_STD_VER >= 11 + static_assert(noexcept(swap(f1, f2)), "" ); +#endif assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(*f1.target<int(*)(int)>() == g); @@ -108,6 +118,9 @@ int main() { std::function<int(int)> f1 = g; std::function<int(int)> f2 = h; +#if TEST_STD_VER >= 11 + static_assert(noexcept(swap(f1, f2)), "" ); +#endif assert(A::count == 0); assert(globalMemCounter.checkOutstandingNewEq(0)); assert(*f1.target<int(*)(int)>() == g); diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp index 82a6f6c5215e..fd296a7367b8 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp @@ -16,6 +16,7 @@ #include <functional> #include <cassert> +#include "test_macros.h" #include "count_new.hpp" class A @@ -49,6 +50,17 @@ int A::count = 0; int g(int) {return 0;} +#if TEST_STD_VER >= 11 +struct RValueCallable { + template <class ...Args> + void operator()(Args&&...) && {} +}; +struct LValueCallable { + template <class ...Args> + void operator()(Args&&...) & {} +}; +#endif + int main() { assert(globalMemCounter.checkOutstandingNewEq(0)); @@ -91,4 +103,13 @@ int main() std::function <void()> f(static_cast<void (*)()>(0)); assert(!f); } +#if TEST_STD_VER >= 11 + { + using Fn = std::function<void(int, int, int)>; + static_assert(std::is_constructible<Fn, LValueCallable&>::value, ""); + static_assert(std::is_constructible<Fn, LValueCallable>::value, ""); + static_assert(!std::is_constructible<Fn, RValueCallable&>::value, ""); + static_assert(!std::is_constructible<Fn, RValueCallable>::value, ""); + } +#endif } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp index 11716e7946b0..e927ad42c06b 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp @@ -19,6 +19,7 @@ #include <functional> #include <cassert> +#include "test_macros.h" #include "count_new.hpp" class A @@ -52,6 +53,17 @@ int A::count = 0; int g(int) {return 0;} +#if TEST_STD_VER >= 11 +struct RValueCallable { + template <class ...Args> + void operator()(Args&&...) && {} +}; +struct LValueCallable { + template <class ...Args> + void operator()(Args&&...) & {} +}; +#endif + int main() { assert(globalMemCounter.checkOutstandingNewEq(0)); @@ -95,4 +107,13 @@ int main() assert(f.target<int(*)(int)>() != 0); f(1); } +#if TEST_STD_VER >= 11 + { + using Fn = std::function<void(int, int, int)>; + static_assert(std::is_assignable<Fn&, LValueCallable&>::value, ""); + static_assert(std::is_assignable<Fn&, LValueCallable>::value, ""); + static_assert(!std::is_assignable<Fn&, RValueCallable&>::value, ""); + static_assert(!std::is_assignable<Fn&, RValueCallable>::value, ""); + } +#endif } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.fail.cpp new file mode 100644 index 000000000000..f455f0311847 --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <functional> +// XFAIL: c++98, c++03, c++11, c++14 + +// class function<R(ArgTypes...)> + +// template<class A> function(allocator_arg_t, const A&); + +#include <functional> +#include <cassert> + +#include "min_allocator.h" + +int main() +{ + std::function<int(int)> f(std::allocator_arg, std::allocator<int>()); +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp index f97e34d3f2cb..392dfc1993bc 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp @@ -8,10 +8,13 @@ //===----------------------------------------------------------------------===// // <functional> +// REQUIRES-ANY: c++98, c++03, c++11, c++14 // class function<R(ArgTypes...)> // template<class A> function(allocator_arg_t, const A&); +// +// This signature was removed in C++17 #include <functional> #include <cassert> diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.fail.cpp new file mode 100644 index 000000000000..24f7fceb877b --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.fail.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <functional> +// XFAIL: c++98, c++03, c++11, c++14 + +// class function<R(ArgTypes...)> + +// template<class F, class A> function(allocator_arg_t, const A&, F); +// +// This signature was removed in C++17 + +#include <functional> +#include <cassert> + +#include "test_macros.h" + +void foo(int) {} + +int main() +{ + std::function<void(int)> f(std::allocator_arg, std::allocator<int>(), foo); +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp index 352ecfc602be..8d454723320c 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // <functional> +// REQUIRES-ANY: c++98, c++03, c++11, c++14 // class function<R(ArgTypes...)> @@ -16,11 +17,24 @@ #include <functional> #include <cassert> +#include "test_macros.h" #include "min_allocator.h" #include "test_allocator.h" #include "count_new.hpp" #include "../function_types.h" + +#if TEST_STD_VER >= 11 +struct RValueCallable { + template <class ...Args> + void operator()(Args&&...) && {} +}; +struct LValueCallable { + template <class ...Args> + void operator()(Args&&...) & {} +}; +#endif + class DummyClass {}; template <class FuncType, class AllocType> @@ -103,4 +117,14 @@ int main() non_default_test_allocator<DummyClass> non_default_alloc(42); test_for_alloc(non_default_alloc); } +#if TEST_STD_VER >= 11 + { + using Fn = std::function<void(int, int, int)>; + static_assert(std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, LValueCallable&>::value, ""); + static_assert(std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, LValueCallable>::value, ""); + static_assert(!std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, RValueCallable&>::value, ""); + static_assert(!std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, RValueCallable>::value, ""); + } +#endif + } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.fail.cpp new file mode 100644 index 000000000000..9967457ff821 --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <functional> +// XFAIL: c++98, c++03, c++11, c++14 + +// class function<R(ArgTypes...)> + +// template<class A> function(allocator_arg_t, const A&, const function&); +// +// This signature was removed in C++17 + + +#include <functional> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + typedef std::function<void(int)> F; + F f1; + F f2(std::allocator_arg, std::allocator<int>(), f1); +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp index 371eb98de1a9..718aa49341d2 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // <functional> +// REQUIRES-ANY: c++98, c++03, c++11, c++14 // class function<R(ArgTypes...)> diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.fail.cpp new file mode 100644 index 000000000000..cc4ecce75138 --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.fail.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <functional> +// XFAIL: c++98, c++03, c++11, c++14 + +// class function<R(ArgTypes...)> + +// template<class A> function(allocator_arg_t, const A&, nullptr_t); +// +// This signature was removed in C++17 + +#include <functional> +#include <cassert> + +#include "min_allocator.h" + +int main() +{ + std::function<int(int)> f(std::allocator_arg, std::allocator<int>(), nullptr); +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp index 2350f92f0f89..354ad955f207 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp @@ -8,10 +8,13 @@ //===----------------------------------------------------------------------===// // <functional> +// REQUIRES-ANY: c++98, c++03, c++11, c++14 // class function<R(ArgTypes...)> // template<class A> function(allocator_arg_t, const A&, nullptr_t); +// +// This signature was removed in C++17 #include <functional> #include <cassert> diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.fail.cpp new file mode 100644 index 000000000000..cb9fb9afad2b --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.fail.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <functional> +// XFAIL: c++98, c++03, c++11, c++14 + +// class function<R(ArgTypes...)> + +// template<class A> function(allocator_arg_t, const A&, function&&); +// +// This signature was removed in C++17 + +#include <functional> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +class A +{ + int data_[10]; +public: + static int count; + + A() + { + ++count; + for (int i = 0; i < 10; ++i) + data_[i] = i; + } + + A(const A&) {++count;} + + ~A() {--count;} + + int operator()(int i) const + { + for (int j = 0; j < 10; ++j) + i += data_[j]; + return i; + } +}; + +int A::count = 0; + +int g(int) { return 0; } + +int main() +{ + { + std::function<int(int)> f = A(); + std::function<int(int)> f2(std::allocator_arg, std::allocator<A>(), std::move(f)); + } +} diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp index 403d646f4216..e328481b274d 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp @@ -8,12 +8,15 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03 +// REQUIRES-ANY: c++11, c++14 // <functional> // class function<R(ArgTypes...)> // template<class A> function(allocator_arg_t, const A&, function&&); +// +// This signature was removed in C++17 #include <functional> #include <memory> diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp index c91eaa2d5674..9b83ddecb974 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp @@ -16,94 +16,123 @@ #include <functional> #include <cassert> +#include "test_macros.h" #include "count_new.hpp" -class A -{ - int data_[10]; +class A { + int data_[10]; + public: - static int count; + static int count; - A() - { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = i; - } + A() { + ++count; + for (int i = 0; i < 10; ++i) + data_[i] = i; + } - A(const A&) {++count;} + A(const A &) { ++count; } - ~A() {--count;} + ~A() { --count; } - int operator()(int i) const - { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; - } + int operator()(int i) const { + for (int j = 0; j < 10; ++j) + i += data_[j]; + return i; + } }; int A::count = 0; -int g(int) {return 0;} +int g0() { return 0; } +int g(int) { return 0; } +int g2(int, int) { return 2; } +int g3(int, int, int) { return 3; } -int main() -{ - assert(globalMemCounter.checkOutstandingNewEq(0)); - { +int main() { + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f = A(); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f.target<A>()); - assert(f.target<int(*)(int)>() == 0); + assert(f.target<int (*)(int)>() == 0); std::function<int(int)> f2; f2 = f; assert(A::count == 2); assert(globalMemCounter.checkOutstandingNewEq(2)); assert(f2.target<A>()); - assert(f2.target<int(*)(int)>() == 0); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + assert(f2.target<int (*)(int)>() == 0); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f = g; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target<int(*)(int)>()); + assert(f.target<int (*)(int)>()); assert(f.target<A>() == 0); std::function<int(int)> f2; f2 = f; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>()); + assert(f2.target<int (*)(int)>()); assert(f2.target<A>() == 0); - } - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target<int(*)(int)>() == 0); + assert(f.target<int (*)(int)>() == 0); assert(f.target<A>() == 0); std::function<int(int)> f2; f2 = f; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>() == 0); + assert(f2.target<int (*)(int)>() == 0); assert(f2.target<A>() == 0); - } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + { + typedef std::function<int()> Func; + Func f = g0; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)()>() == g0); + } + { + typedef std::function<int(int)> Func; + Func f = g; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)(int)>() == g); + } + { + typedef std::function<int(int, int)> Func; + Func f = g2; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)(int, int)>() == g2); + } + { + typedef std::function<int(int, int, int)> Func; + Func f = g3; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)(int, int, int)>() == g3); + } +#if TEST_STD_VER >= 11 + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f = A(); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f.target<A>()); - assert(f.target<int(*)(int)>() == 0); + assert(f.target<int (*)(int)>() == 0); std::function<int(int)> f2; f2 = std::move(f); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f2.target<A>()); - assert(f2.target<int(*)(int)>() == 0); + assert(f2.target<int (*)(int)>() == 0); assert(f.target<A>() == 0); - assert(f.target<int(*)(int)>() == 0); - } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + assert(f.target<int (*)(int)>() == 0); + } +#endif } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp index 387b371a9331..9d5681a3db76 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp @@ -132,7 +132,7 @@ int main() assert(A::count == 1); assert(f2.target<A>() == nullptr); assert(f2.target<Ref>()); - assert(f.target<Ref>()); // f is unchanged because the target is small + LIBCPP_ASSERT(f.target<Ref>()); // f is unchanged because the target is small } { // Test that moving a function constructed from a function pointer @@ -146,7 +146,7 @@ int main() std::function<int(int)> f2(std::move(f)); assert(f2.target<A>() == nullptr); assert(f2.target<Ptr>()); - assert(f.target<Ptr>()); // f is unchanged because the target is small + LIBCPP_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small } #endif // TEST_STD_VER >= 11 } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp index f94e689b2a6b..214c3f7c5d83 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp @@ -18,46 +18,49 @@ #include "count_new.hpp" -class A -{ - int data_[10]; +class A { + int data_[10]; + public: - static int count; + static int count; - explicit A(int j) - { - ++count; - data_[0] = j; - } + explicit A(int j) { + ++count; + data_[0] = j; + } - A(const A& a) - { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = a.data_[i]; - } + A(const A &a) { + ++count; + for (int i = 0; i < 10; ++i) + data_[i] = a.data_[i]; + } - ~A() {--count;} + ~A() { --count; } - int operator()(int i) const - { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; - } + int operator()(int i) const { + for (int j = 0; j < 10; ++j) + i += data_[j]; + return i; + } + + int operator()() const { return -1; } + int operator()(int, int) const { return -2; } + int operator()(int, int, int) const { return -3; } - int id() const {return data_[0];} + int id() const { return data_[0]; } }; int A::count = 0; -int g(int) {return 0;} -int h(int) {return 1;} +int g0() { return 0; } +int g(int) { return 0; } +int h(int) { return 1; } +int g2(int, int) { return 2; } +int g3(int, int, int) { return 3; } -int main() -{ - assert(globalMemCounter.checkOutstandingNewEq(0)); - { +int main() { + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = A(1); std::function<int(int)> f2 = A(2); assert(A::count == 2); @@ -69,52 +72,122 @@ int main() assert(globalMemCounter.checkOutstandingNewEq(2)); assert(f1.target<A>()->id() == 2); assert(f2.target<A>()->id() == 1); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = A(1); std::function<int(int)> f2 = g; assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f1.target<A>()->id() == 1); - assert(*f2.target<int(*)(int)>() == g); + assert(*f2.target<int (*)(int)>() == g); f1.swap(f2); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); - assert(*f1.target<int(*)(int)>() == g); + assert(*f1.target<int (*)(int)>() == g); assert(f2.target<A>()->id() == 1); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = g; std::function<int(int)> f2 = A(1); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); - assert(*f1.target<int(*)(int)>() == g); + assert(*f1.target<int (*)(int)>() == g); assert(f2.target<A>()->id() == 1); f1.swap(f2); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f1.target<A>()->id() == 1); - assert(*f2.target<int(*)(int)>() == g); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + assert(*f2.target<int (*)(int)>() == g); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = g; std::function<int(int)> f2 = h; assert(A::count == 0); assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(*f1.target<int(*)(int)>() == g); - assert(*f2.target<int(*)(int)>() == h); + assert(*f1.target<int (*)(int)>() == g); + assert(*f2.target<int (*)(int)>() == h); f1.swap(f2); assert(A::count == 0); assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(*f1.target<int(*)(int)>() == h); - assert(*f2.target<int(*)(int)>() == g); + assert(*f1.target<int (*)(int)>() == h); + assert(*f2.target<int (*)(int)>() == g); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int(int)> f1 = A(1); + assert(A::count == 1); + { + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 1); + assert(f1.target<A>()->id() == 1); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int()> f1 = g0; + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(*f1.target<int (*)()>() == g0); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int(int, int)> f1 = g2; + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(*f1.target<int (*)(int, int)>() == g2); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int(int, int, int)> f1 = g3; + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(*f1.target<int (*)(int, int, int)>() == g3); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int()> f1 = A(1); + assert(A::count == 1); + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(A::count == 1); + assert(f1.target<A>()->id() == 1); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 0); + { + std::function<int(int, int)> f1 = A(2); + assert(A::count == 1); + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(A::count == 1); + assert(f1.target<A>()->id() == 2); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 0); + { + std::function<int(int, int, int)> f1 = A(3); + assert(A::count == 1); + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(A::count == 1); + assert(f1.target<A>()->id() == 3); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 0); } diff --git a/test/std/utilities/function.objects/logical.operations/logical_and.pass.cpp b/test/std/utilities/function.objects/logical.operations/logical_and.pass.cpp index 72f9dc20144d..ac94fa5362e8 100644 --- a/test/std/utilities/function.objects/logical.operations/logical_and.pass.cpp +++ b/test/std/utilities/function.objects/logical.operations/logical_and.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::logical_and<int> F; @@ -26,7 +28,7 @@ int main() assert(!f(36, 0)); assert(!f(0, 36)); assert(!f(0, 0)); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::logical_and<> F2; const F2 f2 = F2(); assert( f2(36, 36)); diff --git a/test/std/utilities/function.objects/logical.operations/logical_not.pass.cpp b/test/std/utilities/function.objects/logical.operations/logical_not.pass.cpp index 8484625a727c..4f783dd0f23a 100644 --- a/test/std/utilities/function.objects/logical.operations/logical_not.pass.cpp +++ b/test/std/utilities/function.objects/logical.operations/logical_not.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::logical_not<int> F; @@ -23,7 +25,7 @@ int main() static_assert((std::is_same<F::result_type, bool>::value), "" ); assert(!f(36)); assert(f(0)); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::logical_not<> F2; const F2 f2 = F2(); assert(!f2(36)); diff --git a/test/std/utilities/function.objects/logical.operations/logical_or.pass.cpp b/test/std/utilities/function.objects/logical.operations/logical_or.pass.cpp index 7280504403f4..3c450a05de19 100644 --- a/test/std/utilities/function.objects/logical.operations/logical_or.pass.cpp +++ b/test/std/utilities/function.objects/logical.operations/logical_or.pass.cpp @@ -15,6 +15,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::logical_or<int> F; @@ -26,7 +28,7 @@ int main() assert(f(36, 0)); assert(f(0, 36)); assert(!f(0, 0)); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 typedef std::logical_or<> F2; const F2 f2 = F2(); assert( f2(36, 36)); diff --git a/test/std/utilities/function.objects/refwrap/type_properties.pass.cpp b/test/std/utilities/function.objects/refwrap/type_properties.pass.cpp index 3c00bd20ac64..261a306ca156 100644 --- a/test/std/utilities/function.objects/refwrap/type_properties.pass.cpp +++ b/test/std/utilities/function.objects/refwrap/type_properties.pass.cpp @@ -21,7 +21,9 @@ #include <type_traits> #include <string> -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#include "test_macros.h" + +#if TEST_STD_VER >= 11 class MoveOnly { MoveOnly(const MoveOnly&); @@ -55,7 +57,7 @@ int main() test<int>(); test<double>(); test<std::string>(); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 test<MoveOnly>(); #endif } diff --git a/test/std/utilities/function.objects/unord.hash/enum.pass.cpp b/test/std/utilities/function.objects/unord.hash/enum.pass.cpp index 8aa2c1df8935..af367789a105 100644 --- a/test/std/utilities/function.objects/unord.hash/enum.pass.cpp +++ b/test/std/utilities/function.objects/unord.hash/enum.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11 + // <functional> // make sure that we can hash enumeration values @@ -14,8 +16,6 @@ #include "test_macros.h" -#if TEST_STD_VER >= 14 - #include <functional> #include <cassert> #include <type_traits> @@ -59,6 +59,3 @@ int main() test<Fruits>(); } -#else -int main () {} -#endif diff --git a/test/std/utilities/function.objects/unord.hash/integral.pass.cpp b/test/std/utilities/function.objects/unord.hash/integral.pass.cpp index 8954f4f3664b..2f3f9bee4bc3 100644 --- a/test/std/utilities/function.objects/unord.hash/integral.pass.cpp +++ b/test/std/utilities/function.objects/unord.hash/integral.pass.cpp @@ -35,11 +35,11 @@ test() for (int i = 0; i <= 5; ++i) { - T t(i); + T t(static_cast<T>(i)); if (sizeof(T) <= sizeof(std::size_t)) { const std::size_t result = h(t); - LIBCPP_ASSERT(result == t); + LIBCPP_ASSERT(result == static_cast<size_t>(t)); ((void)result); // Prevent unused warning } } diff --git a/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp b/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp new file mode 100644 index 000000000000..ed173f280d05 --- /dev/null +++ b/test/std/utilities/function.objects/unord.hash/non_enum.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <functional> + +// Hashing a struct w/o a defined hash should *not* fail, but it should +// create a type that is not constructible and not callable. +// See also: http://cplusplus.github.io/LWG/lwg-active.html#2543 + +#include <functional> +#include <cassert> +#include <type_traits> + +#include "test_macros.h" + +struct X {}; + +int main() +{ + using H = std::hash<X>; + static_assert(!std::is_default_constructible<H>::value, ""); + static_assert(!std::is_copy_constructible<H>::value, ""); + static_assert(!std::is_move_constructible<H>::value, ""); + static_assert(!std::is_copy_assignable<H>::value, ""); + static_assert(!std::is_move_assignable<H>::value, ""); +#if TEST_STD_VER > 14 + static_assert(!std::is_callable<H(X&)>::value, ""); + static_assert(!std::is_callable<H(X const&)>::value, ""); +#endif +} diff --git a/test/std/utilities/intseq/intseq.intseq/integer_seq.fail.cpp b/test/std/utilities/intseq/intseq.intseq/integer_seq.fail.cpp index b689160babaa..ed899e7ca268 100644 --- a/test/std/utilities/intseq/intseq.intseq/integer_seq.fail.cpp +++ b/test/std/utilities/intseq/intseq.intseq/integer_seq.fail.cpp @@ -22,9 +22,11 @@ #include <utility> +#include "test_macros.h" + int main() { -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 // Should fail to compile, since float is not an integral type using floatmix = std::integer_sequence<float>; @@ -34,5 +36,5 @@ int main() X -#endif // _LIBCPP_STD_VER > 11 +#endif // TEST_STD_VER > 11 } diff --git a/test/std/utilities/intseq/intseq.make/make_integer_seq.fail.cpp b/test/std/utilities/intseq/intseq.make/make_integer_seq.fail.cpp index af4a3c4dfe7f..192626935f00 100644 --- a/test/std/utilities/intseq/intseq.make/make_integer_seq.fail.cpp +++ b/test/std/utilities/intseq/intseq.make/make_integer_seq.fail.cpp @@ -14,6 +14,9 @@ // UNSUPPORTED: c++98, c++03, c++11 +// This test hangs during recursive template instantiation with libstdc++ +// UNSUPPORTED: libstdc++ + #include <utility> #include <type_traits> #include <cassert> diff --git a/test/std/utilities/intseq/intseq.make/make_integer_seq_fallback.fail.cpp b/test/std/utilities/intseq/intseq.make/make_integer_seq_fallback.fail.cpp index b6431b56d5f0..c3efe72fe7db 100644 --- a/test/std/utilities/intseq/intseq.make/make_integer_seq_fallback.fail.cpp +++ b/test/std/utilities/intseq/intseq.make/make_integer_seq_fallback.fail.cpp @@ -14,5 +14,8 @@ // UNSUPPORTED: c++98, c++03, c++11 +// This test hangs during recursive template instantiation with libstdc++ +// UNSUPPORTED: libstdc++ + #define _LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE #include "make_integer_seq.fail.cpp" diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp index 490fdf5d332b..ab8179c5ab4d 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp @@ -17,6 +17,7 @@ // }; #include <memory> +#include <cstdint> #include <cassert> template <class T> @@ -27,12 +28,12 @@ struct A value_type* allocate(std::size_t n) { assert(n == 10); - return (value_type*)0xDEADBEEF; + return reinterpret_cast<value_type*>(static_cast<std::uintptr_t>(0xDEADBEEF)); } }; int main() { A<int> a; - assert(std::allocator_traits<A<int> >::allocate(a, 10) == (int*)0xDEADBEEF); + assert(std::allocator_traits<A<int> >::allocate(a, 10) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF))); } diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp index 079db3526ac7..808284261f7d 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp @@ -17,8 +17,11 @@ // }; #include <memory> +#include <cstdint> #include <cassert> +#include "test_macros.h" + template <class T> struct A { @@ -27,7 +30,7 @@ struct A value_type* allocate(std::size_t n) { assert(n == 10); - return (value_type*)0xDEADBEEF; + return reinterpret_cast<value_type*>(static_cast<std::uintptr_t>(0xDEADBEEF)); } }; @@ -39,22 +42,22 @@ struct B value_type* allocate(std::size_t n) { assert(n == 12); - return (value_type*)0xEEADBEEF; + return reinterpret_cast<value_type*>(static_cast<std::uintptr_t>(0xEEADBEEF)); } value_type* allocate(std::size_t n, const void* p) { assert(n == 11); assert(p == 0); - return (value_type*)0xFEADBEEF; + return reinterpret_cast<value_type*>(static_cast<std::uintptr_t>(0xFEADBEEF)); } }; int main() { -#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE +#if TEST_STD_VER >= 11 A<int> a; - assert(std::allocator_traits<A<int> >::allocate(a, 10, nullptr) == (int*)0xDEADBEEF); -#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE + assert(std::allocator_traits<A<int> >::allocate(a, 10, nullptr) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF))); +#endif B<int> b; - assert(std::allocator_traits<B<int> >::allocate(b, 11, nullptr) == (int*)0xFEADBEEF); + assert(std::allocator_traits<B<int> >::allocate(b, 11, nullptr) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xFEADBEEF))); } diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp index 634019758e70..46075f62c6c1 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp @@ -22,6 +22,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + template <class T> struct A { @@ -36,14 +38,14 @@ struct B { typedef T value_type; -#ifndef _LIBCPP_HAS_NO_VARIADICS +#if TEST_STD_VER >= 11 template <class U, class ...Args> void construct(U* p, Args&& ...args) { ++b_construct; ::new ((void*)p) U(std::forward<Args>(args)...); } -#endif // _LIBCPP_HAS_NO_VARIADICS +#endif }; struct A0 @@ -105,7 +107,7 @@ int main() std::allocator_traits<A<int> >::construct(a, (A2*)&a2, 'd', 5); assert(A2::count == 1); } -#ifndef _LIBCPP_HAS_NO_VARIADICS +#if TEST_STD_VER >= 11 { A0::count = 0; b_construct = 0; @@ -139,5 +141,5 @@ int main() assert(A2::count == 1); assert(b_construct == 1); } -#endif // _LIBCPP_HAS_NO_VARIADICS +#endif } diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp index b137dc6d36c3..8176d8b3767a 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp @@ -17,6 +17,7 @@ // }; #include <memory> +#include <cstdint> #include <cassert> int called = 0; @@ -28,7 +29,7 @@ struct A void deallocate(value_type* p, std::size_t n) { - assert(p == (value_type*)0xDEADBEEF); + assert(p == reinterpret_cast<value_type*>(static_cast<std::uintptr_t>(0xDEADBEEF))); assert(n == 10); ++called; } @@ -37,6 +38,6 @@ struct A int main() { A<int> a; - std::allocator_traits<A<int> >::deallocate(a, (int*)0xDEADBEEF, 10); + std::allocator_traits<A<int> >::deallocate(a, reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)), 10); assert(called == 1); } diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp index 54726c929efe..2ee64b8b4a07 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp @@ -22,6 +22,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + template <class T> struct A { @@ -63,7 +65,7 @@ int main() std::allocator_traits<A<int> >::destroy(a, (A0*)&a0); assert(A0::count == 1); } -#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE +#if TEST_STD_VER >= 11 { A0::count = 0; b_destroy = 0; @@ -76,5 +78,5 @@ int main() assert(A0::count == 1); assert(b_destroy == 1); } -#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE +#endif } diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp index bbc6b470174d..d2c9a9826e14 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp @@ -43,7 +43,15 @@ struct B int main() { -#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE + { + B<int> b; + assert(std::allocator_traits<B<int> >::max_size(b) == 100); + } + { + const B<int> b = {}; + assert(std::allocator_traits<B<int> >::max_size(b) == 100); + } +#if TEST_STD_VER >= 11 { A<int> a; assert(std::allocator_traits<A<int> >::max_size(a) == @@ -54,16 +62,6 @@ int main() assert(std::allocator_traits<A<int> >::max_size(a) == std::numeric_limits<std::size_t>::max() / sizeof(int)); } -#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE - { - B<int> b; - assert(std::allocator_traits<B<int> >::max_size(b) == 100); - } - { - const B<int> b = {}; - assert(std::allocator_traits<B<int> >::max_size(b) == 100); - } -#if TEST_STD_VER >= 11 { std::allocator<int> a; static_assert(noexcept(std::allocator_traits<std::allocator<int>>::max_size(a)) == true, ""); diff --git a/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp b/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp index 29fe2be126f3..2e9703037894 100644 --- a/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp @@ -22,6 +22,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + template <class T> struct A { @@ -55,7 +57,7 @@ int main() const A<int> a(0); assert(std::allocator_traits<A<int> >::select_on_container_copy_construction(a).id == 0); } -#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE +#if TEST_STD_VER >= 11 { B<int> b; assert(std::allocator_traits<B<int> >::select_on_container_copy_construction(b).id == 100); @@ -64,5 +66,5 @@ int main() const B<int> b(0); assert(std::allocator_traits<B<int> >::select_on_container_copy_construction(b).id == 100); } -#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE +#endif } diff --git a/test/std/utilities/memory/allocator.traits/rebind_traits.pass.cpp b/test/std/utilities/memory/allocator.traits/rebind_traits.pass.cpp index 87da9a0a85da..af4f5bc3fb46 100644 --- a/test/std/utilities/memory/allocator.traits/rebind_traits.pass.cpp +++ b/test/std/utilities/memory/allocator.traits/rebind_traits.pass.cpp @@ -19,6 +19,8 @@ #include <memory> #include <type_traits> +#include "test_macros.h" + template <class T> struct ReboundA {}; @@ -63,17 +65,17 @@ struct E int main() { -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#if TEST_STD_VER >= 11 static_assert((std::is_same<std::allocator_traits<A<char> >::rebind_traits<double>, std::allocator_traits<ReboundA<double> > >::value), ""); static_assert((std::is_same<std::allocator_traits<B<int, char> >::rebind_traits<double>, std::allocator_traits<ReboundB<double, char> > >::value), ""); static_assert((std::is_same<std::allocator_traits<C<char> >::rebind_traits<double>, std::allocator_traits<C<double> > >::value), ""); static_assert((std::is_same<std::allocator_traits<D<int, char> >::rebind_traits<double>, std::allocator_traits<D<double, char> > >::value), ""); static_assert((std::is_same<std::allocator_traits<E<char> >::rebind_traits<double>, std::allocator_traits<E<double> > >::value), ""); -#else // _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#else static_assert((std::is_same<std::allocator_traits<A<char> >::rebind_traits<double>::other, std::allocator_traits<ReboundA<double> > >::value), ""); static_assert((std::is_same<std::allocator_traits<B<int, char> >::rebind_traits<double>::other, std::allocator_traits<ReboundB<double, char> > >::value), ""); static_assert((std::is_same<std::allocator_traits<C<char> >::rebind_traits<double>::other, std::allocator_traits<C<double> > >::value), ""); static_assert((std::is_same<std::allocator_traits<D<int, char> >::rebind_traits<double>::other, std::allocator_traits<D<double, char> > >::value), ""); static_assert((std::is_same<std::allocator_traits<E<char> >::rebind_traits<double>::other, std::allocator_traits<E<double> > >::value), ""); -#endif // _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#endif } diff --git a/test/std/utilities/memory/allocator.uses/allocator.uses.trait/uses_allocator.pass.cpp b/test/std/utilities/memory/allocator.uses/allocator.uses.trait/uses_allocator.pass.cpp index bd32bc34e7a0..2831399c3047 100644 --- a/test/std/utilities/memory/allocator.uses/allocator.uses.trait/uses_allocator.pass.cpp +++ b/test/std/utilities/memory/allocator.uses/allocator.uses.trait/uses_allocator.pass.cpp @@ -38,16 +38,38 @@ private: typedef int allocator_type; }; +template <bool Expected, class T, class A> +void +test() +{ + static_assert((std::uses_allocator<T, A>::value == Expected), ""); +#if TEST_STD_VER > 14 + static_assert((std::uses_allocator_v<T, A> == Expected), ""); +#endif +} + int main() { - static_assert((!std::uses_allocator<int, std::allocator<int> >::value), ""); - static_assert(( std::uses_allocator<std::vector<int>, std::allocator<int> >::value), ""); - static_assert((!std::uses_allocator<A, std::allocator<int> >::value), ""); - static_assert((!std::uses_allocator<B, std::allocator<int> >::value), ""); - static_assert(( std::uses_allocator<B, double>::value), ""); - static_assert((!std::uses_allocator<C, decltype(C::allocator_type)>::value), ""); - static_assert((!std::uses_allocator<D, decltype(D::allocator_type)>::value), ""); + test<false, int, std::allocator<int> >(); + test<true, std::vector<int>, std::allocator<int> >(); + test<false, A, std::allocator<int> >(); + test<false, B, std::allocator<int> >(); + test<true, B, double>(); + test<false, C, decltype(C::allocator_type)>(); + test<false, D, decltype(D::allocator_type)>(); #if TEST_STD_VER >= 11 - static_assert((!std::uses_allocator<E, int>::value), ""); + test<false, E, int>(); #endif + + +// static_assert((!std::uses_allocator<int, std::allocator<int> >::value), ""); +// static_assert(( std::uses_allocator<std::vector<int>, std::allocator<int> >::value), ""); +// static_assert((!std::uses_allocator<A, std::allocator<int> >::value), ""); +// static_assert((!std::uses_allocator<B, std::allocator<int> >::value), ""); +// static_assert(( std::uses_allocator<B, double>::value), ""); +// static_assert((!std::uses_allocator<C, decltype(C::allocator_type)>::value), ""); +// static_assert((!std::uses_allocator<D, decltype(D::allocator_type)>::value), ""); +// #if TEST_STD_VER >= 11 +// static_assert((!std::uses_allocator<E, int>::value), ""); +// #endif } diff --git a/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp b/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp index dc0bdd047c61..768d41878437 100644 --- a/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp +++ b/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // <memory> // allocator: @@ -16,6 +16,8 @@ #include <memory> #include <cassert> +#include "test_macros.h" + template <typename T> void test_max(size_t count) { @@ -27,23 +29,19 @@ void test_max(size_t count) } } -int main() +template <typename T> +void test() { - { // Bug 26812 -- allocating too large - typedef double T; - std::allocator<T> a; - test_max<T> (a.max_size() + 1); // just barely too large - test_max<T> (a.max_size() * 2); // significantly too large - test_max<T> (((size_t) -1) / sizeof(T) + 1); // multiply will overflow - test_max<T> ((size_t) -1); // way too large - } + // Bug 26812 -- allocating too large + std::allocator<T> a; + test_max<T> (a.max_size() + 1); // just barely too large + test_max<T> (a.max_size() * 2); // significantly too large + test_max<T> (((size_t) -1) / sizeof(T) + 1); // multiply will overflow + test_max<T> ((size_t) -1); // way too large +} - { - typedef const double T; - std::allocator<T> a; - test_max<T> (a.max_size() + 1); // just barely too large - test_max<T> (a.max_size() * 2); // significantly too large - test_max<T> (((size_t) -1) / sizeof(T) + 1); // multiply will overflow - test_max<T> ((size_t) -1); // way too large - } +int main() +{ + test<double>(); + LIBCPP_ONLY(test<const double>()); } diff --git a/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp b/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp index cba32103dcd4..7f25e57765d4 100644 --- a/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp +++ b/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp @@ -32,6 +32,8 @@ #include <type_traits> #include <cstddef> +#include "test_macros.h" + int main() { static_assert((std::is_same<std::allocator<char>::size_type, std::size_t>::value), ""); @@ -45,7 +47,7 @@ int main() std::allocator<int> >::value), ""); static_assert((std::is_same<std::allocator< char>::is_always_equal, std::true_type>::value), ""); - static_assert((std::is_same<std::allocator<const char>::is_always_equal, std::true_type>::value), ""); + LIBCPP_STATIC_ASSERT((std::is_same<std::allocator<const char>::is_always_equal, std::true_type>::value), ""); std::allocator<char> a; std::allocator<char> a2 = a; diff --git a/test/std/utilities/memory/pointer.traits/rebind.pass.cpp b/test/std/utilities/memory/pointer.traits/rebind.pass.cpp index 8716c05f3335..4caf4f650297 100644 --- a/test/std/utilities/memory/pointer.traits/rebind.pass.cpp +++ b/test/std/utilities/memory/pointer.traits/rebind.pass.cpp @@ -19,9 +19,11 @@ #include <memory> #include <type_traits> +#include "test_macros.h" + int main() { -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#if TEST_STD_VER >= 11 static_assert((std::is_same<std::pointer_traits<int*>::rebind<double>, double*>::value), ""); #else static_assert((std::is_same<std::pointer_traits<int*>::rebind<double>::other, double*>::value), ""); diff --git a/test/std/utilities/utility/forward/forward3.fail.cpp b/test/std/utilities/memory/specialized.algorithms/specialized.addressof/addressof.temp.fail.cpp index 7e1e9b38fdc2..81f49eaac39b 100644 --- a/test/std/utilities/utility/forward/forward3.fail.cpp +++ b/test/std/utilities/memory/specialized.algorithms/specialized.addressof/addressof.temp.fail.cpp @@ -7,18 +7,20 @@ // //===----------------------------------------------------------------------===// -// test forward +// <memory> -#include <utility> +// template <ObjectType T> T* addressof(T&& r) = delete; -struct A -{ -}; +#include <memory> +#include <cassert> -A source() {return A();} -const A csource() {return A();} +#include "test_macros.h" int main() { - std::forward<A&>(csource()); // error +#if TEST_STD_VER > 14 + const int *p = std::addressof<const int>(0); +#else +#error +#endif } diff --git a/test/std/utilities/memory/specialized.algorithms/specialized.addressof/constexpr_addressof.pass.cpp b/test/std/utilities/memory/specialized.algorithms/specialized.addressof/constexpr_addressof.pass.cpp index a371f8eda1a8..41f06c519609 100644 --- a/test/std/utilities/memory/specialized.algorithms/specialized.addressof/constexpr_addressof.pass.cpp +++ b/test/std/utilities/memory/specialized.algorithms/specialized.addressof/constexpr_addressof.pass.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 -// XFAIL: gcc +// XFAIL: gcc-4, gcc-5, gcc-6 // <memory> diff --git a/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp b/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp new file mode 100644 index 000000000000..2ad9d04e59b7 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class ForwardIt> +// void destroy(ForwardIt, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static void reset() { count = 0; } + Counted() { ++count; } + Counted(Counted const&) { ++count; } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; + +int main() +{ + using It = forward_iterator<Counted*>; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_fill(p, p+N, Counted()); + assert(Counted::count == 5); + std::destroy(p, p+1); + p += 1; + assert(Counted::count == 4); + std::destroy(It(p), It(p + 4)); + assert(Counted::count == 0); +} diff --git a/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp b/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp new file mode 100644 index 000000000000..4e67b1eceb57 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class _Tp> +// void destroy_at(_Tp*); + +#include <memory> +#include <cstdlib> +#include <cassert> + +struct Counted { + static int count; + static void reset() { count = 0; } + Counted() { ++count; } + Counted(Counted const&) { ++count; } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; + +struct VCounted { + static int count; + static void reset() { count = 0; } + VCounted() { ++count; } + VCounted(VCounted const&) { ++count; } + virtual ~VCounted() { --count; } + friend void operator&(VCounted) = delete; +}; +int VCounted::count = 0; + +struct DCounted : VCounted { + friend void operator&(DCounted) = delete; +}; + +int main() +{ + { + void* mem1 = std::malloc(sizeof(Counted)); + void* mem2 = std::malloc(sizeof(Counted)); + assert(mem1 && mem2); + assert(Counted::count == 0); + Counted* ptr1 = ::new(mem1) Counted(); + Counted* ptr2 = ::new(mem2) Counted(); + assert(Counted::count == 2); + std::destroy_at(ptr1); + assert(Counted::count == 1); + std::destroy_at(ptr2); + assert(Counted::count == 0); + std::free(mem1); + std::free(mem2); + } + { + void* mem1 = std::malloc(sizeof(DCounted)); + void* mem2 = std::malloc(sizeof(DCounted)); + assert(mem1 && mem2); + assert(DCounted::count == 0); + DCounted* ptr1 = ::new(mem1) DCounted(); + DCounted* ptr2 = ::new(mem2) DCounted(); + assert(DCounted::count == 2); + assert(VCounted::count == 2); + std::destroy_at(ptr1); + assert(VCounted::count == 1); + std::destroy_at(ptr2); + assert(VCounted::count == 0); + std::free(mem1); + std::free(mem2); + } +} diff --git a/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp b/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp new file mode 100644 index 000000000000..d1eaca558a73 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class ForwardIt, class Size> +// ForwardIt destroy_n(ForwardIt, Size s); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static void reset() { count = 0; } + Counted() { ++count; } + Counted(Counted const&) { ++count; } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; + +int main() +{ + using It = forward_iterator<Counted*>; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_fill(p, p+N, Counted()); + assert(Counted::count == 5); + Counted* np = std::destroy_n(p, 1); + assert(np == p+1); + assert(Counted::count == 4); + p += 1; + It it = std::destroy_n(It(p), 4); + assert(it == It(p+4)); + assert(Counted::count == 0); +} diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp new file mode 100644 index 000000000000..533d516707e1 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class ForwardIt> +// void uninitialized_default_construct(ForwardIt, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + TEST_THROW(1); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { assert(count > 0); --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator<ThrowsCounted*>; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_default_construct(It(p), It(p+N)); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws +#endif +} + +void test_counted() +{ + using It = forward_iterator<Counted*>; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_default_construct(It(p), It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + std::uninitialized_default_construct(It(p+1), It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator<int*>; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + std::uninitialized_default_construct(It(p), It(p+1)); + assert(pool[0] == -1); + assert(pool[1] == -1); + std::uninitialized_default_construct(It(p+1), It(p+N)); + assert(pool[1] == -1); + assert(pool[2] == -1); + assert(pool[3] == -1); + assert(pool[4] == -1); +} + +int main() +{ + test_counted(); + test_value_initialized(); + test_ctor_throws(); +} diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp new file mode 100644 index 000000000000..f22a74f1f832 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class ForwardIt> +// void uninitialized_default_construct(ForwardIt, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { assert(count > 0); --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + TEST_THROW(1); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { assert(count > 0); --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator<ThrowsCounted*>; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_default_construct_n(It(p), N); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws +#endif +} + +void test_counted() +{ + using It = forward_iterator<Counted*>; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + It e = std::uninitialized_default_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + e = std::uninitialized_default_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator<int*>; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + auto e = std::uninitialized_default_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(pool[0] == -1); + assert(pool[1] == -1); + e = std::uninitialized_default_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(pool[1] == -1); + assert(pool[2] == -1); + assert(pool[3] == -1); + assert(pool[4] == -1); +} + + +int main() +{ + test_counted(); + test_value_initialized(); + test_ctor_throws(); +} diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp new file mode 100644 index 000000000000..c2d860694a75 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp @@ -0,0 +1,111 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class ForwardIt> +// void uninitialized_value_construct(ForwardIt, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { assert(count > 0); --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + TEST_THROW(1); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { assert(count > 0); --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator<ThrowsCounted*>; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_value_construct(It(p), It(p+N)); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws +#endif +} + +void test_counted() +{ + using It = forward_iterator<Counted*>; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_value_construct(It(p), It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + std::uninitialized_value_construct(It(p+1), It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator<int*>; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + std::uninitialized_value_construct(It(p), It(p+1)); + assert(pool[0] == 0); + assert(pool[1] == -1); + std::uninitialized_value_construct(It(p+1), It(p+N)); + assert(pool[1] == 0); + assert(pool[2] == 0); + assert(pool[3] == 0); + assert(pool[4] == 0); +} + +int main() +{ + test_counted(); + test_value_initialized(); + test_ctor_throws(); +} diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp new file mode 100644 index 000000000000..323d00f7c9c4 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class ForwardIt> +// void uninitialized_value_construct(ForwardIt, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + TEST_THROW(1); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator<ThrowsCounted*>; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_value_construct_n(It(p), N); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 3); + assert(ThrowsCounted::constructed == 4); // forth construction throws + std::destroy(p, p+3); + assert(ThrowsCounted::count == 0); +#endif +} + +void test_counted() +{ + using It = forward_iterator<Counted*>; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + It e = std::uninitialized_value_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + e = std::uninitialized_value_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator<int*>; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + It e = std::uninitialized_value_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(pool[0] == 0); + assert(pool[1] == -1); + e = std::uninitialized_value_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(pool[1] == 0); + assert(pool[2] == 0); + assert(pool[3] == 0); + assert(pool[4] == 0); +} + +int main() +{ + test_counted(); + test_value_initialized(); +}
\ No newline at end of file diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp index 1debd6d75ff0..1829dff354d3 100644 --- a/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // <memory> // template <class InputIterator, class ForwardIterator> @@ -18,13 +17,21 @@ #include <memory> #include <cassert> +#include "test_macros.h" + struct B { static int count_; static int population_; int data_; explicit B() : data_(1) { ++population_; } - B(const B& b) {if (++count_ == 3) throw 1; data_ = b.data_; ++population_; } + B(const B &b) { + ++count_; + if (count_ == 3) + TEST_THROW(1); + data_ = b.data_; + ++population_; + } ~B() {data_ = 0; --population_; } }; @@ -49,6 +56,7 @@ int main() B* bp = (B*)pool; B b[N]; assert(B::population_ == N); +#ifndef TEST_HAS_NO_EXCEPTIONS try { std::uninitialized_copy(b, b+N, bp); @@ -58,6 +66,7 @@ int main() { assert(B::population_ == N); } +#endif B::count_ = 0; std::uninitialized_copy(b, b+2, bp); for (int i = 0; i < 2; ++i) diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp index 83aa19471ada..af20cd220291 100644 --- a/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // <memory> // template <class InputIterator, class Size, class ForwardIterator> @@ -18,13 +17,21 @@ #include <memory> #include <cassert> +#include "test_macros.h" + struct B { static int count_; static int population_; int data_; explicit B() : data_(1) { ++population_; } - B(const B& b) {if (++count_ == 3) throw 1; data_ = b.data_; ++population_; } + B(const B &b) { + ++count_; + if (count_ == 3) + TEST_THROW(1); + data_ = b.data_; + ++population_; + } ~B() {data_ = 0; --population_; } }; @@ -49,6 +56,7 @@ int main() B* bp = (B*)pool; B b[N]; assert(B::population_ == N); +#ifndef TEST_HAS_NO_EXCEPTIONS try { std::uninitialized_copy_n(b, 5, bp); @@ -58,6 +66,7 @@ int main() { assert(B::population_ == N); } +#endif B::count_ = 0; std::uninitialized_copy_n(b, 2, bp); for (int i = 0; i < 2; ++i) diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp index 5f90a3792064..862e5be8e363 100644 --- a/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // <memory> // template <class ForwardIterator, class Size, class T> @@ -17,13 +16,21 @@ #include <memory> #include <cassert> +#include "test_macros.h" + struct B { static int count_; static int population_; int data_; explicit B() : data_(1) { ++population_; } - B(const B& b) {if (++count_ == 3) throw 1; data_ = b.data_; ++population_; } + B(const B &b) { + ++count_; + if (count_ == 3) + TEST_THROW(1); + data_ = b.data_; + ++population_; + } ~B() {data_ = 0; --population_; } }; @@ -47,6 +54,7 @@ int main() char pool[sizeof(B)*N] = {0}; B* bp = (B*)pool; assert(B::population_ == 0); +#ifndef TEST_HAS_NO_EXCEPTIONS try { std::uninitialized_fill_n(bp, 5, B()); @@ -56,6 +64,7 @@ int main() { assert(B::population_ == 0); } +#endif B::count_ = 0; B* r = std::uninitialized_fill_n(bp, 2, B()); assert(r == bp + 2); diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp index 3816a2528688..57438e9cb0d5 100644 --- a/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // <memory> // template <class ForwardIterator, class T> @@ -18,13 +17,21 @@ #include <memory> #include <cassert> +#include "test_macros.h" + struct B { static int count_; static int population_; int data_; explicit B() : data_(1) { ++population_; } - B(const B& b) {if (++count_ == 3) throw 1; data_ = b.data_; ++population_; } + B(const B &b) { + ++count_; + if (count_ == 3) + TEST_THROW(1); + data_ = b.data_; + ++population_; + } ~B() {data_ = 0; --population_; } }; @@ -48,6 +55,7 @@ int main() char pool[sizeof(B)*N] = {0}; B* bp = (B*)pool; assert(B::population_ == 0); +#ifndef TEST_HAS_NO_EXCEPTIONS try { std::uninitialized_fill(bp, bp+N, B()); @@ -57,6 +65,7 @@ int main() { assert(B::population_ == 0); } +#endif B::count_ = 0; std::uninitialized_fill(bp, bp+2, B()); for (int i = 0; i < 2; ++i) diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp new file mode 100644 index 000000000000..d7a9542b4c27 --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class InputIt, class ForwardIt> +// ForwardIt uninitialized_move(InputIt, InputIt, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { assert(count > 0); --count; } + friend void operator&(Counted) = delete; + int value; +}; +int Counted::count = 0; +int Counted::constructed = 0; + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted(int&& x) { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + TEST_THROW(1); + } + ++count; + x = 0; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { assert(count > 0); --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator<ThrowsCounted*>; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_move(values, values + N, It(p)); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws + assert(values[0] == 0); + assert(values[1] == 0); + assert(values[2] == 0); + assert(values[3] == 4); + assert(values[4] == 5); +#endif +} + +void test_counted() +{ + using It = input_iterator<int*>; + using FIt = forward_iterator<Counted*>; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + auto ret = std::uninitialized_move(It(values), It(values + 1), FIt(p)); + assert(ret == FIt(p +1)); + assert(Counted::constructed = 1); + assert(Counted::count == 1); + assert(p[0].value == 1); + assert(values[0] == 0); + ret = std::uninitialized_move(It(values+1), It(values+N), FIt(p+1)); + assert(ret == FIt(p + N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + assert(p[1].value == 2); + assert(p[2].value == 3); + assert(p[3].value == 4); + assert(p[4].value == 5); + assert(values[1] == 0); + assert(values[2] == 0); + assert(values[3] == 0); + assert(values[4] == 0); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +int main() { + test_counted(); + test_ctor_throws(); +}
\ No newline at end of file diff --git a/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp b/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp new file mode 100644 index 000000000000..f27e5726135f --- /dev/null +++ b/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <memory> + +// template <class InputIt, class Size, class ForwardIt> +// pair<InputIt, ForwardIt> uninitialized_move_n(InputIt, Size, ForwardIt); + +#include <memory> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { assert(count > 0); --count; } + friend void operator&(Counted) = delete; + int value; +}; +int Counted::count = 0; +int Counted::constructed = 0; + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted(int&& x) { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + TEST_THROW(1); + } + ++count; + x = 0; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { assert(count > 0); --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator<ThrowsCounted*>; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_move_n(values, N, It(p)); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws + assert(values[0] == 0); + assert(values[1] == 0); + assert(values[2] == 0); + assert(values[3] == 4); + assert(values[4] == 5); +#endif +} + +void test_counted() +{ + using It = input_iterator<int*>; + using FIt = forward_iterator<Counted*>; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + auto ret = std::uninitialized_move_n(It(values), 1, FIt(p)); + assert(ret.first == It(values +1)); + assert(ret.second == FIt(p +1)); + assert(Counted::constructed = 1); + assert(Counted::count == 1); + assert(p[0].value == 1); + assert(values[0] == 0); + ret = std::uninitialized_move_n(It(values+1), N-1, FIt(p+1)); + assert(ret.first == It(values+N)); + assert(ret.second == FIt(p + N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + assert(p[1].value == 2); + assert(p[2].value == 3); + assert(p[3].value == 4); + assert(p[4].value == 5); + assert(values[1] == 0); + assert(values[2] == 0); + assert(values[3] == 0); + assert(values[4] == 0); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +int main() +{ + test_counted(); + test_ctor_throws(); +}
\ No newline at end of file diff --git a/test/std/utilities/memory/storage.iterator/raw_storage_iterator.pass.cpp b/test/std/utilities/memory/storage.iterator/raw_storage_iterator.pass.cpp index 914802423ce7..3df8dd0eded0 100644 --- a/test/std/utilities/memory/storage.iterator/raw_storage_iterator.pass.cpp +++ b/test/std/utilities/memory/storage.iterator/raw_storage_iterator.pass.cpp @@ -13,6 +13,7 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" #include <MoveOnly.h> int A_constructed = 0; @@ -46,7 +47,7 @@ int main() assert(A_constructed == i+1); } } -#if _LIBCPP_STD_VER >= 14 +#if TEST_STD_VER >= 14 { typedef MoveOnly S; typedef std::aligned_storage<3*sizeof(S), std::alignment_of<S>::value>::type diff --git a/test/std/utilities/memory/unique.ptr/unique.ptr.dltr/unique.ptr.dltr.dflt1/convert_ctor.pass.cpp b/test/std/utilities/memory/unique.ptr/unique.ptr.dltr/unique.ptr.dltr.dflt1/convert_ctor.pass.cpp index a611b1a12f05..2949d6310c59 100644 --- a/test/std/utilities/memory/unique.ptr/unique.ptr.dltr/unique.ptr.dltr.dflt1/convert_ctor.pass.cpp +++ b/test/std/utilities/memory/unique.ptr/unique.ptr.dltr/unique.ptr.dltr.dflt1/convert_ctor.pass.cpp @@ -24,4 +24,5 @@ int main() { std::default_delete<int[]> d1; std::default_delete<const int[]> d2 = d1; + ((void)d2); } diff --git a/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/null_ctor.pass.cpp b/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/null_ctor.pass.cpp index 6d752b9951a5..50389978e8ab 100644 --- a/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/null_ctor.pass.cpp +++ b/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/null_ctor.pass.cpp @@ -16,6 +16,8 @@ #include <memory> #include <cassert> +#include "test_macros.h" + class Deleter { int state_; @@ -36,9 +38,18 @@ int main() Deleter d; assert(d.state() == 0); { + std::unique_ptr<int[], Deleter&> p(nullptr, d); + assert(p.get() == 0); + assert(&p.get_deleter() == &d); + } +#if defined(_LIBCPP_VERSION) + { + // The standard only requires the constructor accept nullptr, but libc++ + // also supports the literal 0. std::unique_ptr<int[], Deleter&> p(0, d); assert(p.get() == 0); assert(&p.get_deleter() == &d); } +#endif assert(d.state() == 0); } diff --git a/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/move02.pass.cpp b/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/move02.pass.cpp index 5720d3bd288f..89b6fa248845 100644 --- a/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/move02.pass.cpp +++ b/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/move02.pass.cpp @@ -38,7 +38,7 @@ source1() return std::unique_ptr<A[]>(new A[3]); } -void sink1(std::unique_ptr<A[]> p) +void sink1(std::unique_ptr<A[]>) { } @@ -48,7 +48,7 @@ source2() return std::unique_ptr<A[], Deleter<A[]> >(new A[3]); } -void sink2(std::unique_ptr<A[], Deleter<A[]> > p) +void sink2(std::unique_ptr<A[], Deleter<A[]> >) { } @@ -59,7 +59,7 @@ source3() return std::unique_ptr<A[], NCDeleter<A[]>&>(new A[3], d); } -void sink3(std::unique_ptr<A[], NCDeleter<A[]>&> p) +void sink3(std::unique_ptr<A[], NCDeleter<A[]>&>) { } diff --git a/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/pointer_deleter01.pass.cpp b/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/pointer_deleter01.pass.cpp index 2b0b5f0d945d..3de556563f97 100644 --- a/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/pointer_deleter01.pass.cpp +++ b/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/pointer_deleter01.pass.cpp @@ -42,7 +42,9 @@ int main() assert(A::count == 0); { // LWG#2520 says that nullptr is a valid input as well as null +#ifdef _LIBCPP_VERSION std::unique_ptr<A[], Deleter<A[]> > s1(NULL, Deleter<A[]>()); +#endif std::unique_ptr<A[], Deleter<A[]> > s2(nullptr, Deleter<A[]>()); } assert(A::count == 0); diff --git a/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert08.fail.cpp b/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert08.fail.cpp index e14bba0763c5..016eadcb2460 100644 --- a/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert08.fail.cpp +++ b/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert08.fail.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // unique_ptr @@ -46,17 +48,10 @@ template <class T> class Deleter { int state_; - -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES Deleter(const Deleter&); Deleter& operator=(const Deleter&); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - Deleter(Deleter&); - Deleter& operator=(Deleter&); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES public: -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;} Deleter& operator=(Deleter&& r) { @@ -64,20 +59,9 @@ public: r.state_ = 0; return *this; } -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);} - Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;} - Deleter& operator=(std::__rv<Deleter> r) - { - state_ = r->state_; - r->state_ = 0; - return *this; - } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES Deleter() : state_(5) {} -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template <class U> Deleter(Deleter<U>&& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) @@ -87,12 +71,7 @@ private: template <class U> Deleter(const Deleter<U>& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - template <class U> - Deleter(Deleter<U> d, - typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) - : state_(d.state()) {} -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + public: int state() const {return state_;} void set_state(int i) {state_ = i;} @@ -102,17 +81,6 @@ public: int main() { - { - const std::unique_ptr<B, Deleter<B> > s(new B); - A* p = s.get(); - std::unique_ptr<A, Deleter<A> > s2(s); - assert(s2.get() == p); - assert(s.get() == 0); - assert(A::count == 1); - assert(B::count == 1); - assert(s2.get_deleter().state() == 5); - assert(s.get_deleter().state() == 0); - } - assert(A::count == 0); - assert(B::count == 0); + const std::unique_ptr<B, Deleter<B> > s; + std::unique_ptr<A, Deleter<A> > s2(s); // expected-error {{no matching constructor}} } diff --git a/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert11.fail.cpp b/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert11.fail.cpp index bcf94a978144..1b8bb736df20 100644 --- a/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert11.fail.cpp +++ b/test/std/utilities/memory/unique.ptr/unique.ptr.single/unique.ptr.single.ctor/move_convert11.fail.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // unique_ptr @@ -47,16 +49,9 @@ class Deleter { int state_; -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES Deleter(const Deleter&); Deleter& operator=(const Deleter&); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - Deleter(Deleter&); - Deleter& operator=(Deleter&); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - public: -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;} Deleter& operator=(Deleter&& r) { @@ -64,20 +59,9 @@ public: r.state_ = 0; return *this; } -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);} - Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;} - Deleter& operator=(std::__rv<Deleter> r) - { - state_ = r->state_; - r->state_ = 0; - return *this; - } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES Deleter() : state_(5) {} -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template <class U> Deleter(Deleter<U>&& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) @@ -87,12 +71,7 @@ private: template <class U> Deleter(const Deleter<U>& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - template <class U> - Deleter(Deleter<U> d, - typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) - : state_(d.state()) {} -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + public: int state() const {return state_;} void set_state(int i) {state_ = i;} @@ -102,17 +81,6 @@ public: int main() { - { - const std::unique_ptr<B, Deleter<B> > s(new B); - A* p = s.get(); - std::unique_ptr<A, Deleter<A> > s2 = s; - assert(s2.get() == p); - assert(s.get() == 0); - assert(A::count == 1); - assert(B::count == 1); - assert(s2.get_deleter().state() == 5); - assert(s.get_deleter().state() == 0); - } - assert(A::count == 0); - assert(B::count == 0); + const std::unique_ptr<B, Deleter<B> > s; + std::unique_ptr<A, Deleter<A> > s2 = s; // expected-error {{no viable conversion}} } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_Y_rv.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_Y_rv.pass.cpp index 93956bcae663..20275de603e2 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_Y_rv.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_Y_rv.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // shared_ptr @@ -42,7 +44,6 @@ int A::count = 0; int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { std::shared_ptr<A> pA(new A); A* ptrA = pA.get(); @@ -119,5 +120,4 @@ int main() } assert(B::count == 0); assert(A::count == 0); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_rv.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_rv.pass.cpp index 4194890dda2d..4a85633a89ad 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_rv.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/shared_ptr_rv.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // shared_ptr @@ -42,7 +44,6 @@ int A::count = 0; int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { std::shared_ptr<A> pA(new A); A* ptrA = pA.get(); @@ -119,5 +120,4 @@ int main() } assert(B::count == 0); assert(A::count == 0); -#endif // _LIBCXX_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp index 41aeb04a5feb..2e6441d66316 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // <memory> // template<class D, class A> shared_ptr(nullptr_t, D d, A a); diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_throw.pass.cpp index 85fc5e930544..009b4cfc00f9 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_throw.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_throw.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // UNSUPPORTED: sanitizer-new-delete // <memory> diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp index c72847791778..388599bd7015 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // <memory> // template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp index 70af2964113d..7b40d6df2164 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_throw.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // UNSUPPORTED: sanitizer-new-delete // <memory> diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp index 2fa975eca833..182d5f4a4937 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_throw.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // UNSUPPORTED: sanitizer-new-delete // <memory> diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp index f041d9451a6d..ea0720404b48 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // shared_ptr @@ -17,6 +19,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + struct B { static int count; @@ -66,24 +70,24 @@ int main() std::shared_ptr<B> pB(std::move(pA)); assert(B::count == 1); assert(A::count == 1); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 assert(pB.use_count() == 1); assert(pA.use_count() == 0); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#else assert(pB.use_count() == 2); assert(pA.use_count() == 2); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif assert(p == pB.get()); } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 assert(pA.use_count() == 0); assert(B::count == 0); assert(A::count == 0); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#else assert(pA.use_count() == 1); assert(B::count == 1); assert(A::count == 1); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif } assert(B::count == 0); assert(A::count == 0); diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_rv.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_rv.pass.cpp index b89178e201cf..257d3ce19be3 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_rv.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_rv.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <memory> // shared_ptr @@ -16,6 +18,8 @@ #include <memory> #include <cassert> +#include "test_macros.h" + struct A { static int count; @@ -37,22 +41,22 @@ int main() A* p = pA.get(); std::shared_ptr<A> pA2(std::move(pA)); assert(A::count == 1); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 assert(pA.use_count() == 0); assert(pA2.use_count() == 1); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#else assert(pA.use_count() == 2); assert(pA2.use_count() == 2); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif assert(pA2.get() == p); } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 assert(pA.use_count() == 0); assert(A::count == 0); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#else assert(pA.use_count() == 1); assert(A::count == 1); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif } assert(A::count == 0); { diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp index 5c424f5c7428..877577c9ce58 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // UNSUPPORTED: sanitizer-new-delete // <memory> @@ -63,6 +62,7 @@ int main() assert(p.get() == raw_ptr); assert(ptr.get() == 0); } +#ifndef TEST_HAS_NO_EXCEPTIONS assert(A::count == 0); { std::unique_ptr<A> ptr(new A); @@ -86,6 +86,7 @@ int main() #endif } } +#endif assert(A::count == 0); { // LWG 2399 fn(std::unique_ptr<int>(new int)); diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp index 35a7d077b424..830aa5bbca4c 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // <memory> // shared_ptr @@ -17,6 +16,8 @@ #include <memory> #include <cassert> +#include "test_macros.h" + struct B { static int count; @@ -42,6 +43,7 @@ int A::count = 0; int main() { +#ifndef TEST_HAS_NO_EXCEPTIONS { std::weak_ptr<A> wp; try @@ -54,6 +56,7 @@ int main() } assert(A::count == 0); } +#endif { std::shared_ptr<A> sp0(new A); std::weak_ptr<A> wp(sp0); @@ -63,6 +66,7 @@ int main() assert(A::count == 1); } assert(A::count == 0); +#ifndef TEST_HAS_NO_EXCEPTIONS { std::shared_ptr<A> sp0(new A); std::weak_ptr<A> wp(sp0); @@ -77,4 +81,5 @@ int main() } } assert(A::count == 0); +#endif } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp index 8cb972b0c1a1..8d782716b94f 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp @@ -16,6 +16,7 @@ #include <memory> #include <cassert> +#include "test_macros.h" #include "count_new.hpp" struct A @@ -65,7 +66,7 @@ int main() assert(p2.get()); } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 nc = globalMemCounter.outstanding_new; { char c = 'e'; diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr.pass.cpp index 75bf3df90aa3..90f958e26852 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr.pass.cpp @@ -18,6 +18,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + struct B { static int count; @@ -55,7 +57,7 @@ int C::count = 0; template <class T> std::weak_ptr<T> source (std::shared_ptr<T> p) { return std::weak_ptr<T>(p); } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 template <class T> void sink (std::weak_ptr<T> &&) {} #endif @@ -100,7 +102,7 @@ int main() assert(B::count == 0); assert(A::count == 0); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 { std::shared_ptr<A> ps(new A); std::weak_ptr<A> pA = source(ps); diff --git a/test/std/utilities/meta/meta.help/integral_constant.pass.cpp b/test/std/utilities/meta/meta.help/integral_constant.pass.cpp index 335305a28236..51a837e4e032 100644 --- a/test/std/utilities/meta/meta.help/integral_constant.pass.cpp +++ b/test/std/utilities/meta/meta.help/integral_constant.pass.cpp @@ -14,6 +14,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + int main() { typedef std::integral_constant<int, 5> _5; @@ -26,7 +28,7 @@ int main() assert(_5() == 5); #endif -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert ( _5{}() == 5, "" ); static_assert ( std::true_type{}(), "" ); #endif diff --git a/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_all_extents.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_all_extents.pass.cpp index 28bbedee1749..f7902a2be775 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_all_extents.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_all_extents.pass.cpp @@ -13,13 +13,15 @@ #include <type_traits> +#include "test_macros.h" + enum Enum {zero, one_}; template <class T, class U> void test_remove_all_extents() { static_assert((std::is_same<typename std::remove_all_extents<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::remove_all_extents_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_extent.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_extent.pass.cpp index c688c26b9a5b..aa175d9ebc8c 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_extent.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.arr/remove_extent.pass.cpp @@ -13,13 +13,15 @@ #include <type_traits> +#include "test_macros.h" + enum Enum {zero, one_}; template <class T, class U> void test_remove_extent() { static_assert((std::is_same<typename std::remove_extent<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::remove_extent_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.cv/add_const.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.cv/add_const.pass.cpp index 19b1fb4d01b3..ef1aa8acbc68 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.cv/add_const.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.cv/add_const.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_add_const_imp() { static_assert((std::is_same<typename std::add_const<T>::type, const U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::add_const_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.cv/add_cv.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.cv/add_cv.pass.cpp index 4905e518e12a..c0c2483e4c40 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.cv/add_cv.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.cv/add_cv.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_add_cv_imp() { static_assert((std::is_same<typename std::add_cv<T>::type, const volatile U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::add_cv_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.cv/add_volatile.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.cv/add_volatile.pass.cpp index 7a12c44a2c6e..f29fb06cd807 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.cv/add_volatile.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.cv/add_volatile.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_add_volatile_imp() { static_assert((std::is_same<typename std::add_volatile<T>::type, volatile U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::add_volatile_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_const.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_const.pass.cpp index cd2faf786d80..426d22d29f67 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_const.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_const.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_remove_const_imp() { static_assert((std::is_same<typename std::remove_const<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::remove_const_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_cv.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_cv.pass.cpp index 3f6405c8280c..a6ce05756ef6 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_cv.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_cv.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_remove_cv_imp() { static_assert((std::is_same<typename std::remove_cv<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::remove_cv_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_volatile.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_volatile.pass.cpp index 6258a9039b40..90b8d4bcbea2 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_volatile.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.cv/remove_volatile.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_remove_volatile_imp() { static_assert((std::is_same<typename std::remove_volatile<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::remove_volatile_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_union.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_union.pass.cpp index ae849ca54558..43f23f5ccc80 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_union.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_union.pass.cpp @@ -13,12 +13,14 @@ #include <type_traits> +#include "test_macros.h" + int main() { #ifndef _LIBCPP_HAS_NO_VARIADICS { typedef std::aligned_union<10, char >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<10, char>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 1, ""); @@ -26,7 +28,7 @@ int main() } { typedef std::aligned_union<10, short >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<10, short>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 2, ""); @@ -34,7 +36,7 @@ int main() } { typedef std::aligned_union<10, int >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<10, int>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 4, ""); @@ -42,7 +44,7 @@ int main() } { typedef std::aligned_union<10, double >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<10, double>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 8, ""); @@ -50,7 +52,7 @@ int main() } { typedef std::aligned_union<10, short, char >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<10, short, char>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 2, ""); @@ -58,7 +60,7 @@ int main() } { typedef std::aligned_union<10, char, short >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<10, char, short>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 2, ""); @@ -66,7 +68,7 @@ int main() } { typedef std::aligned_union<2, int, char, short >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<2, int, char, short>, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 4, ""); @@ -74,7 +76,7 @@ int main() } { typedef std::aligned_union<2, char, int, short >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<2, char, int, short >, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 4, ""); @@ -82,7 +84,7 @@ int main() } { typedef std::aligned_union<2, char, short, int >::type T1; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(std::is_same<std::aligned_union_t<2, char, short, int >, T1>::value, "" ); #endif static_assert(std::alignment_of<T1>::value == 4, ""); diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp index e8611253c5d4..61523e4872d4 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp @@ -12,6 +12,7 @@ // common_type #include <type_traits> +#include <memory> #include "test_macros.h" @@ -30,15 +31,198 @@ namespace std { typedef S<T> type; }; + + template <class T> + struct common_type< ::S<T>, T> { + typedef S<T> type; + }; + + template <> struct common_type< ::S<long>, long> {}; + template <> struct common_type<long, ::S<long> > {}; } #if TEST_STD_VER >= 11 -template <class T, class U, class = void> -struct no_common_type : std::true_type {}; +template <class Tp> +struct always_bool_imp { using type = bool; }; +template <class Tp> using always_bool = typename always_bool_imp<Tp>::type; + +template <class ...Args> +constexpr auto no_common_type_imp(int) + -> always_bool<typename std::common_type<Args...>::type> + { return false; } + +template <class ...Args> +constexpr bool no_common_type_imp(long) { return true; } + +template <class ...Args> +using no_common_type = std::integral_constant<bool, no_common_type_imp<Args...>(0)>; + +template <class Tp> +using Decay = typename std::decay<Tp>::type; + +template <class ...Args> +using CommonType = typename std::common_type<Args...>::type; + +template <class T1, class T2> +struct TernaryOpImp { + static_assert(std::is_same<Decay<T1>, T1>::value, "must be same"); + static_assert(std::is_same<Decay<T2>, T2>::value, "must be same"); + using type = typename std::decay< + decltype(false ? std::declval<T1>() : std::declval<T2>()) + >::type; +}; + +template <class T1, class T2> +using TernaryOp = typename TernaryOpImp<T1, T2>::type; + +// -- If sizeof...(T) is zero, there shall be no member type. +void test_bullet_one() { + static_assert(no_common_type<>::value, ""); +} + +// If sizeof...(T) is one, let T0 denote the sole type constituting the pack T. +// The member typedef-name type shall denote the same type as decay_t<T0>. +void test_bullet_two() { + static_assert(std::is_same<CommonType<void>, void>::value, ""); + static_assert(std::is_same<CommonType<int>, int>::value, ""); + static_assert(std::is_same<CommonType<int const>, int>::value, ""); + static_assert(std::is_same<CommonType<int volatile[]>, int volatile*>::value, ""); + static_assert(std::is_same<CommonType<void(&)()>, void(*)()>::value, ""); +} + +template <class T, class U, class Expect> +void test_bullet_three_one_imp() { + using DT = Decay<T>; + using DU = Decay<U>; + static_assert(!std::is_same<T, DT>::value || !std::is_same<U, DU>::value, ""); + static_assert(std::is_same<CommonType<T, U>, Expect>::value, ""); + static_assert(std::is_same<CommonType<U, T>, Expect>::value, ""); + static_assert(std::is_same<CommonType<T, U>, CommonType<DT, DU>>::value, ""); +} + +// (3.3) +// -- If sizeof...(T) is two, let the first and second types constituting T be +// denoted by T1 and T2, respectively, and let D1 and D2 denote the same types +// as decay_t<T1> and decay_t<T2>, respectively. +// (3.3.1) +// -- If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, let C +// denote the same type, if any, as common_type_t<D1, D2>. +void test_bullet_three_one() { + // Test that the user provided specialization of common_type is used after + // decaying T1. + { + using T1 = S<int> const; + using T2 = int; + test_bullet_three_one_imp<T1, T2, S<int> >(); + } + // Test a user provided specialization that does not provide a typedef. + { + using T1 = ::S<long> const; + using T2 = long; + static_assert(no_common_type<T1, T2>::value, ""); + static_assert(no_common_type<T2, T1>::value, ""); + } + // Test that the ternary operator is not applied when the types are the + // same. + { + using T1 = const void; + using Expect = void; + static_assert(std::is_same<CommonType<T1, T1>, Expect>::value, ""); + static_assert(std::is_same<CommonType<T1, T1>, CommonType<T1>>::value, ""); + } + { + using T1 = int const[]; + using Expect = int const*; + static_assert(std::is_same<CommonType<T1, T1>, Expect>::value, ""); + static_assert(std::is_same<CommonType<T1, T1>, CommonType<T1>>::value, ""); + } +} -template <class T, class U> -struct no_common_type<T, U, typename std::conditional<false, - typename std::common_type<T, U>::type, void>::type> : std::false_type {}; +// (3.3) +// -- If sizeof...(T) is two, let the first and second types constituting T be +// denoted by T1 and T2, respectively, and let D1 and D2 denote the same types +// as decay_t<T1> and decay_t<T2>, respectively. +// (3.3.1) +// -- If [...] +// (3.3.2) +// -- Otherwise, let C denote the same type, if any, as +// decay_t<decltype(false ? declval<D1>() : declval<D2>())> +void test_bullet_three_two() { + { + using T1 = int const*; + using T2 = int*; + using Expect = TernaryOp<T1, T2>; + static_assert(std::is_same<CommonType<T1, T2>, Expect>::value, ""); + static_assert(std::is_same<CommonType<T2, T1>, Expect>::value, ""); + } + // Test that there is no ::type member when the ternary op is ill-formed + { + using T1 = int; + using T2 = void; + static_assert(no_common_type<T1, T2>::value, ""); + static_assert(no_common_type<T2, T1>::value, ""); + } + { + using T1 = int; + using T2 = X<int>; + static_assert(no_common_type<T1, T2>::value, ""); + static_assert(no_common_type<T2, T1>::value, ""); + } + // Test that the ternary operator is not applied when the types are the + // same. + { + using T1 = void; + using Expect = void; + static_assert(std::is_same<CommonType<T1, T1>, Expect>::value, ""); + static_assert(std::is_same<CommonType<T1, T1>, CommonType<T1>>::value, ""); + } +} + +// (3.4) +// -- If sizeof...(T) is greater than two, let T1, T2, and R, respectively, +// denote the first, second, and (pack of) remaining types constituting T. +// Let C denote the same type, if any, as common_type_t<T1, T2>. If there is +// such a type C, the member typedef-name type shall denote the +// same type, if any, as common_type_t<C, R...>. Otherwise, there shall be +// no member type. +void test_bullet_four() { + { // test that there is no ::type member + static_assert(no_common_type<int, E>::value, ""); + static_assert(no_common_type<int, int, E>::value, ""); + static_assert(no_common_type<int, int, E, int>::value, ""); + static_assert(no_common_type<int, int, int, E>::value, ""); + } +} + + +// The example code specified in Note B for common_type +namespace note_b_example { + +using PF1 = bool (&)(); +using PF2 = short (*)(long); + +struct S { + operator PF2() const; + double operator()(char, int&); + void fn(long) const; + char data; +}; + +using PMF = void (S::*)(long) const; +using PMD = char S::*; + +using std::is_same; +using std::result_of; +using std::unique_ptr; + +static_assert(is_same<typename result_of<S(int)>::type, short>::value, "Error!"); +static_assert(is_same<typename result_of<S&(unsigned char, int&)>::type, double>::value, "Error!"); +static_assert(is_same<typename result_of<PF1()>::type, bool>::value, "Error!"); +static_assert(is_same<typename result_of<PMF(unique_ptr<S>, int)>::type, void>::value, "Error!"); +static_assert(is_same<typename result_of<PMD(S)>::type, char&&>::value, "Error!"); +static_assert(is_same<typename result_of<PMD(const S*)>::type, const char&>::value, "Error!"); + +} // namespace note_b_example #endif // TEST_STD_VER >= 11 int main() @@ -89,14 +273,15 @@ int main() static_assert((std::is_same<std::common_type<volatile void, void>::type, void>::value), ""); static_assert((std::is_same<std::common_type<const void, const void>::type, void>::value), ""); -#if TEST_STD_VER >= 11 - static_assert((no_common_type<void, int>::value), ""); - static_assert((no_common_type<int, void>::value), ""); - static_assert((no_common_type<int, E>::value), ""); - static_assert((no_common_type<int, X<int> >::value), ""); -#endif // TEST_STD_VER >= 11 - static_assert((std::is_same<std::common_type<int, S<int> >::type, S<int> >::value), ""); static_assert((std::is_same<std::common_type<int, S<int>, S<int> >::type, S<int> >::value), ""); static_assert((std::is_same<std::common_type<int, int, S<int> >::type, S<int> >::value), ""); + +#if TEST_STD_VER >= 11 + test_bullet_one(); + test_bullet_two(); + test_bullet_three_one(); + test_bullet_three_two(); + test_bullet_four(); +#endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/conditional.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/conditional.pass.cpp index ac11e3a4ce86..7de0a0737905 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/conditional.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/conditional.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + int main() { static_assert((std::is_same<std::conditional<true, char, int>::type, char>::value), ""); static_assert((std::is_same<std::conditional<false, char, int>::type, int>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::conditional_t<true, char, int>, char>::value), ""); static_assert((std::is_same<std::conditional_t<false, char, int>, int>::value), ""); #endif diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/decay.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/decay.pass.cpp index bd8ae0e297bc..bcd839849453 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/decay.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/decay.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T, class U> void test_decay() { static_assert((std::is_same<typename std::decay<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::decay_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/enable_if.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/enable_if.pass.cpp index eb72b0f393b3..a9b1e1be1274 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/enable_if.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/enable_if.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + int main() { static_assert((std::is_same<std::enable_if<true>::type, void>::value), ""); static_assert((std::is_same<std::enable_if<true, int>::type, int>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::enable_if_t<true>, void>::value), ""); static_assert((std::is_same<std::enable_if_t<true, int>, int>::value), ""); #endif diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp index 1d7b23c19222..410e47e03bcc 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp @@ -21,14 +21,19 @@ enum F { W = UINT_MAX }; int main() { +#if !defined(_WIN32) || defined(__MINGW32__) + typedef unsigned ExpectUnsigned; +#else + typedef int ExpectUnsigned; // MSVC's ABI doesn't follow the Standard +#endif static_assert((std::is_same<std::underlying_type<E>::type, int>::value), "E has the wrong underlying type"); - static_assert((std::is_same<std::underlying_type<F>::type, unsigned>::value), + static_assert((std::is_same<std::underlying_type<F>::type, ExpectUnsigned>::value), "F has the wrong underlying type"); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::underlying_type_t<E>, int>::value), ""); - static_assert((std::is_same<std::underlying_type_t<F>, unsigned>::value), ""); + static_assert((std::is_same<std::underlying_type_t<F>, ExpectUnsigned>::value), ""); #endif #if TEST_STD_VER >= 11 @@ -36,7 +41,7 @@ int main() static_assert((std::is_same<std::underlying_type<G>::type, char>::value), "G has the wrong underlying type"); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::underlying_type_t<G>, char>::value), ""); #endif #endif // TEST_STD_VER >= 11 diff --git a/test/std/utilities/meta/meta.trans/meta.trans.ref/add_rvalue_ref.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.ref/add_rvalue_ref.pass.cpp index fc147c37b1ac..373bad7d6e3c 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.ref/add_rvalue_ref.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.ref/add_rvalue_ref.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // type_traits // add_rvalue_reference @@ -16,8 +18,6 @@ #include <type_traits> #include "test_macros.h" -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - template <class T, class U> void test_add_rvalue_reference() { @@ -44,13 +44,11 @@ void test_function1() static_assert((std::is_same<std::add_rvalue_reference_t<F>, F>::value), ""); #endif } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES struct Foo {}; int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES test_add_rvalue_reference<void, void>(); test_add_rvalue_reference<int, int&&>(); test_add_rvalue_reference<int[3], int(&&)[3]>(); @@ -63,22 +61,17 @@ int main() // LWG 2101 specifically talks about add_rvalue_reference and functions. // The term of art is "a referenceable type", which a cv- or ref-qualified function is not. test_function0<void()>(); -#if TEST_STD_VER >= 11 test_function1<void() const>(); test_function1<void() &>(); test_function1<void() &&>(); test_function1<void() const &>(); test_function1<void() const &&>(); -#endif // But a cv- or ref-qualified member function *is* "a referenceable type" test_function0<void (Foo::*)()>(); -#if TEST_STD_VER >= 11 test_function0<void (Foo::*)() const>(); test_function0<void (Foo::*)() &>(); test_function0<void (Foo::*)() &&>(); test_function0<void (Foo::*)() const &>(); test_function0<void (Foo::*)() const &&>(); -#endif -#endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.ref/remove_ref.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.ref/remove_ref.pass.cpp index e335bd19ef2d..1f9ec2476b50 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.ref/remove_ref.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.ref/remove_ref.pass.cpp @@ -37,11 +37,11 @@ int main() test_remove_reference<int*&, int*>(); test_remove_reference<const int*&, const int*>(); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 test_remove_reference<int&&, int>(); test_remove_reference<const int&&, const int>(); test_remove_reference<int(&&)[3], int[3]>(); test_remove_reference<int*&&, int*>(); test_remove_reference<const int*&&, const int*>(); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.sign/make_signed.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.sign/make_signed.pass.cpp index eb8e31c76e10..06f6e6152aec 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.sign/make_signed.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.sign/make_signed.pass.cpp @@ -13,9 +13,15 @@ #include <type_traits> +#include "test_macros.h" + enum Enum {zero, one_}; +#if TEST_STD_VER >= 11 +enum BigEnum : unsigned long long // MSVC's ABI doesn't follow the Standard +#else enum BigEnum +#endif { bigzero, big = 0xFFFFFFFFFFFFFFFFULL @@ -32,7 +38,7 @@ template <class T, class U> void test_make_signed() { static_assert((std::is_same<typename std::make_signed<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::make_signed_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.trans/meta.trans.sign/make_unsigned.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.sign/make_unsigned.pass.cpp index 984440193fa6..3d152f6049e9 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.sign/make_unsigned.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.sign/make_unsigned.pass.cpp @@ -13,9 +13,15 @@ #include <type_traits> +#include "test_macros.h" + enum Enum {zero, one_}; +#if TEST_STD_VER >= 11 +enum BigEnum : unsigned long long // MSVC's ABI doesn't follow the Standard +#else enum BigEnum +#endif { bigzero, big = 0xFFFFFFFFFFFFFFFFULL @@ -32,7 +38,7 @@ template <class T, class U> void test_make_unsigned() { static_assert((std::is_same<typename std::make_unsigned<T>::type, U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<std::make_unsigned_t<T>, U>::value), ""); #endif } diff --git a/test/std/utilities/meta/meta.unary.prop.query/void_t_feature_test_macro.pass.cpp b/test/std/utilities/meta/meta.unary.prop.query/void_t_feature_test_macro.pass.cpp new file mode 100644 index 000000000000..f188c098c034 --- /dev/null +++ b/test/std/utilities/meta/meta.unary.prop.query/void_t_feature_test_macro.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// type_traits + +// void_t + +#include <type_traits> + +#include "test_macros.h" + +#if TEST_STD_VER <= 14 +# ifdef __cpp_lib_void_t +# error Feature test macro should not be defined! +# endif +#else +# ifndef __cpp_lib_void_t +# error Feature test macro is not defined +# endif +# if __cpp_lib_void_t != 201411 +# error Feature test macro has the wrong value +# endif +#endif + +int main() +{ +#if defined(__cpp_lib_void_t) + static_assert(std::is_same_v<std::void_t<int>, void>, ""); +#endif +} diff --git a/test/std/utilities/meta/meta.unary/meta.unary.cat/lvalue_ref.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.cat/lvalue_ref.pass.cpp index 13cad58c0ef3..5154a1d12936 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.cat/lvalue_ref.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.cat/lvalue_ref.pass.cpp @@ -13,11 +13,13 @@ #include <type_traits> +#include "test_macros.h" + template <class T> void test_lvalue_ref() { static_assert(!std::is_void<T>::value, ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(!std::is_null_pointer<T>::value, ""); #endif static_assert(!std::is_integral<T>::value, ""); diff --git a/test/std/utilities/meta/meta.unary/meta.unary.cat/member_function_pointer_no_variadics.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.cat/member_function_pointer_no_variadics.pass.cpp index b0edea37e8e8..cdaf713ac928 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.cat/member_function_pointer_no_variadics.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.cat/member_function_pointer_no_variadics.pass.cpp @@ -14,11 +14,13 @@ #define _LIBCPP_HAS_NO_VARIADICS #include <type_traits> +#include "test_macros.h" + template <class T> void test_member_function_pointer_imp() { static_assert(!std::is_void<T>::value, ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert(!std::is_null_pointer<T>::value, ""); #endif static_assert(!std::is_integral<T>::value, ""); diff --git a/test/std/utilities/meta/meta.unary/meta.unary.cat/rvalue_ref.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.cat/rvalue_ref.pass.cpp index 99fd2887981f..23d391b490e5 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.cat/rvalue_ref.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.cat/rvalue_ref.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // type_traits // rvalue_ref @@ -39,11 +41,9 @@ struct incomplete_type; int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES test_rvalue_ref<int&&>(); test_rvalue_ref<const int&&>(); // LWG#2582 static_assert(!std::is_rvalue_reference<incomplete_type>::value, ""); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.comp/rvalue_ref.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.comp/rvalue_ref.pass.cpp index 7563c2fd5850..b9b28fd8c3f1 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.comp/rvalue_ref.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.comp/rvalue_ref.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // type_traits // rvalue_ref @@ -27,8 +29,6 @@ void test_rvalue_ref() int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES test_rvalue_ref<int&&>(); test_rvalue_ref<const int&&>(); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp index b734a1aa60d8..f4736e713422 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp @@ -43,7 +43,7 @@ void test_is_not_assignable() struct D; -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 struct C { template <class U> @@ -59,6 +59,8 @@ struct E template <typename T> struct X { T t; }; +struct Incomplete; + int main() { test_is_assignable<int&, int&> (); @@ -67,7 +69,7 @@ int main() test_is_assignable<B, A> (); test_is_assignable<void*&, void*> (); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 test_is_assignable<E, int> (); test_is_not_assignable<int, int&> (); @@ -80,4 +82,5 @@ int main() // pointer to incomplete template type test_is_assignable<X<D>*&, X<D>*> (); + test_is_not_assignable<Incomplete&, Incomplete const&>(); } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp index 9f8fdc7fc635..f6ae401533a9 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp @@ -14,9 +14,18 @@ // template <class T, class... Args> // struct is_constructible; +// MODULES_DEFINES: _LIBCPP_TESTING_FALLBACK_IS_CONSTRUCTIBLE +#define _LIBCPP_TESTING_FALLBACK_IS_CONSTRUCTIBLE #include <type_traits> #include "test_macros.h" +#if TEST_STD_VER >= 11 && defined(_LIBCPP_VERSION) +#define LIBCPP11_STATIC_ASSERT(...) static_assert(__VA_ARGS__) +#else +#define LIBCPP11_STATIC_ASSERT(...) ((void)0) +#endif + + struct A { explicit A(int); @@ -27,6 +36,9 @@ private: A(char); }; +struct Base {}; +struct Derived : public Base {}; + class Abstract { virtual void foo() = 0; @@ -37,10 +49,38 @@ class AbstractDestructor virtual ~AbstractDestructor() = 0; }; +struct PrivateDtor { + PrivateDtor(int) {} +private: + ~PrivateDtor() {} +}; + +struct S { + template <class T> +#if TEST_STD_VER >= 11 + explicit +#endif + operator T () const; +}; + +template <class To> +struct ImplicitTo { + operator To(); +}; + +#if TEST_STD_VER >= 11 +template <class To> +struct ExplicitTo { + explicit operator To (); +}; +#endif + + template <class T> void test_is_constructible() { static_assert( (std::is_constructible<T>::value), ""); + LIBCPP11_STATIC_ASSERT((std::__libcpp_is_constructible<T>::type::value), ""); #if TEST_STD_VER > 14 static_assert( std::is_constructible_v<T>, ""); #endif @@ -50,6 +90,7 @@ template <class T, class A0> void test_is_constructible() { static_assert(( std::is_constructible<T, A0>::value), ""); + LIBCPP11_STATIC_ASSERT((std::__libcpp_is_constructible<T, A0>::type::value), ""); #if TEST_STD_VER > 14 static_assert(( std::is_constructible_v<T, A0>), ""); #endif @@ -59,6 +100,7 @@ template <class T, class A0, class A1> void test_is_constructible() { static_assert(( std::is_constructible<T, A0, A1>::value), ""); + LIBCPP11_STATIC_ASSERT((std::__libcpp_is_constructible<T, A0, A1>::type::value), ""); #if TEST_STD_VER > 14 static_assert(( std::is_constructible_v<T, A0, A1>), ""); #endif @@ -68,6 +110,7 @@ template <class T> void test_is_not_constructible() { static_assert((!std::is_constructible<T>::value), ""); + LIBCPP11_STATIC_ASSERT((!std::__libcpp_is_constructible<T>::type::value), ""); #if TEST_STD_VER > 14 static_assert((!std::is_constructible_v<T>), ""); #endif @@ -77,13 +120,28 @@ template <class T, class A0> void test_is_not_constructible() { static_assert((!std::is_constructible<T, A0>::value), ""); + LIBCPP11_STATIC_ASSERT((!std::__libcpp_is_constructible<T, A0>::type::value), ""); #if TEST_STD_VER > 14 static_assert((!std::is_constructible_v<T, A0>), ""); #endif } +#if TEST_STD_VER >= 11 +template <class T = int, class = decltype(static_cast<T&&>(std::declval<double&>()))> +constexpr bool clang_disallows_valid_static_cast_test(int) { return false; }; + +constexpr bool clang_disallows_valid_static_cast_test(long) { return true; } + +static constexpr bool clang_disallows_valid_static_cast_bug = + clang_disallows_valid_static_cast_test(0); +#endif + + int main() { + typedef Base B; + typedef Derived D; + test_is_constructible<int> (); test_is_constructible<int, const int> (); test_is_constructible<A, int> (); @@ -97,17 +155,138 @@ int main() test_is_constructible<A, char> (); #endif test_is_not_constructible<A, void> (); + test_is_not_constructible<int, void()>(); + test_is_not_constructible<int, void(&)()>(); + test_is_not_constructible<int, void() const>(); + test_is_not_constructible<int&, void>(); + test_is_not_constructible<int&, void()>(); + test_is_not_constructible<int&, void() const>(); + test_is_not_constructible<int&, void(&)()>(); + test_is_not_constructible<void> (); + test_is_not_constructible<const void> (); // LWG 2738 + test_is_not_constructible<volatile void> (); + test_is_not_constructible<const volatile void> (); test_is_not_constructible<int&> (); test_is_not_constructible<Abstract> (); test_is_not_constructible<AbstractDestructor> (); + test_is_constructible<int, S>(); + test_is_not_constructible<int&, S>(); -// LWG 2560 -- postpone this test until bots updated -// test_is_not_constructible<void()> (); -#if TEST_STD_VER > 11 -// test_is_not_constructible<void() const> (); -// test_is_not_constructible<void() volatile> (); -// test_is_not_constructible<void() &> (); -// test_is_not_constructible<void() &&> (); + test_is_constructible<void(&)(), void(&)()>(); + test_is_constructible<void(&)(), void()>(); +#if TEST_STD_VER >= 11 + test_is_constructible<void(&&)(), void(&&)()>(); + test_is_constructible<void(&&)(), void()>(); + test_is_constructible<void(&&)(), void(&)()>(); +#endif + +#if TEST_STD_VER >= 11 + test_is_constructible<int const&, int>(); + test_is_constructible<int const&, int&&>(); + + test_is_constructible<int&&, double&>(); + test_is_constructible<void(&)(), void(&&)()>(); + + test_is_not_constructible<int&, int>(); + test_is_not_constructible<int&, int const&>(); + test_is_not_constructible<int&, int&&>(); + + test_is_constructible<int&&, int>(); + test_is_constructible<int&&, int&&>(); + test_is_not_constructible<int&&, int&>(); + test_is_not_constructible<int&&, int const&&>(); + + test_is_constructible<Base, Derived>(); + test_is_constructible<Base&, Derived&>(); + test_is_not_constructible<Derived&, Base&>(); + test_is_constructible<Base const&, Derived const&>(); + test_is_not_constructible<Derived const&, Base const&>(); + test_is_not_constructible<Derived const&, Base>(); + + test_is_constructible<Base&&, Derived>(); + test_is_constructible<Base&&, Derived&&>(); + test_is_not_constructible<Derived&&, Base&&>(); + test_is_not_constructible<Derived&&, Base>(); + + // test that T must also be destructible + test_is_constructible<PrivateDtor&, PrivateDtor&>(); + test_is_not_constructible<PrivateDtor, int>(); + + test_is_not_constructible<void() const, void() const>(); + test_is_not_constructible<void() const, void*>(); + + test_is_constructible<int&, ImplicitTo<int&>>(); + test_is_constructible<const int&, ImplicitTo<int&&>>(); + test_is_constructible<int&&, ImplicitTo<int&&>>(); + test_is_constructible<const int&, ImplicitTo<int>>(); + + test_is_not_constructible<B&&, B&>(); + test_is_not_constructible<B&&, D&>(); + test_is_constructible<B&&, ImplicitTo<D&&>>(); + test_is_constructible<B&&, ImplicitTo<D&&>&>(); + test_is_constructible<int&&, double&>(); + test_is_constructible<const int&, ImplicitTo<int&>&>(); + test_is_constructible<const int&, ImplicitTo<int&>>(); + test_is_constructible<const int&, ExplicitTo<int&>&>(); + test_is_constructible<const int&, ExplicitTo<int&>>(); + + test_is_constructible<const int&, ExplicitTo<int&>&>(); + test_is_constructible<const int&, ExplicitTo<int&>>(); + test_is_constructible<int&, ExplicitTo<int&>>(); + test_is_constructible<const int&, ExplicitTo<int&&>>(); + + // Binding through reference-compatible type is required to perform + // direct-initialization as described in [over.match.ref] p. 1 b. 1: + test_is_constructible<int&, ExplicitTo<int&>>(); + test_is_constructible<const int&, ExplicitTo<int&&>>(); + + static_assert(std::is_constructible<int&&, ExplicitTo<int&&>>::value, ""); +#ifdef __clang__ +#if defined(CLANG_TEST_VER) && CLANG_TEST_VER < 400 + static_assert(clang_disallows_valid_static_cast_bug, "bug still exists"); +#endif + // FIXME Clang disallows this construction because it thinks that + // 'static_cast<int&&>(declval<ExplicitTo<int&&>>())' is ill-formed. + LIBCPP_STATIC_ASSERT( + clang_disallows_valid_static_cast_bug != + std::__libcpp_is_constructible<int&&, ExplicitTo<int&&>>::value, ""); +#else + static_assert(clang_disallows_valid_static_cast_bug == false, ""); + LIBCPP_STATIC_ASSERT(std::__libcpp_is_constructible<int&&, ExplicitTo<int&&>>::value, ""); +#endif + +#ifdef __clang__ + // FIXME Clang and GCC disagree on the validity of this expression. + test_is_constructible<const int&, ExplicitTo<int>>(); + static_assert(std::is_constructible<int&&, ExplicitTo<int>>::value, ""); + LIBCPP_STATIC_ASSERT( + clang_disallows_valid_static_cast_bug != + std::__libcpp_is_constructible<int&&, ExplicitTo<int>>::value, ""); +#else + test_is_not_constructible<const int&, ExplicitTo<int>>(); + test_is_not_constructible<int&&, ExplicitTo<int>>(); +#endif + + // Binding through temporary behaves like copy-initialization, + // see [dcl.init.ref] p. 5, very last sub-bullet: + test_is_not_constructible<const int&, ExplicitTo<double&&>>(); + test_is_not_constructible<int&&, ExplicitTo<double&&>>(); + + +// TODO: Remove this workaround once Clang <= 3.7 are no longer used regularly. +// In those compiler versions the __is_constructible builtin gives the wrong +// results for abominable function types. +#if (defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER < 703) \ + || (defined(TEST_CLANG_VER) && TEST_CLANG_VER < 308) +#define WORKAROUND_CLANG_BUG +#endif +#if !defined(WORKAROUND_CLANG_BUG) + test_is_not_constructible<void()>(); + test_is_not_constructible<void() const> (); + test_is_not_constructible<void() volatile> (); + test_is_not_constructible<void() &> (); + test_is_not_constructible<void() &&> (); #endif +#endif // TEST_STD_VER >= 11 } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_copy_assignable.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_copy_assignable.pass.cpp index ac8b80bbd3a4..06cf8007889d 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_copy_assignable.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_copy_assignable.pass.cpp @@ -74,12 +74,10 @@ int main() test_is_copy_assignable<NotEmpty> (); test_is_copy_assignable<Empty> (); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 test_is_not_copy_assignable<const int> (); test_is_not_copy_assignable<int[]> (); test_is_not_copy_assignable<int[3]> (); -#endif -#if TEST_STD_VER >= 11 test_is_not_copy_assignable<B> (); #endif test_is_not_copy_assignable<void> (); diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp index 318147e5d4a3..22755dc33dc3 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp @@ -92,15 +92,35 @@ int main() test_is_default_constructible<int*>(); test_is_default_constructible<const int*>(); test_is_default_constructible<char[3]>(); + test_is_default_constructible<char[5][3]>(); + test_is_default_constructible<NotEmpty>(); test_is_default_constructible<bit_zero>(); test_is_not_default_constructible<void>(); test_is_not_default_constructible<int&>(); test_is_not_default_constructible<char[]>(); + test_is_not_default_constructible<char[][3]>(); + test_is_not_default_constructible<Abstract>(); test_is_not_default_constructible<NoDefaultConstructor>(); #if TEST_STD_VER >= 11 test_is_not_default_constructible<B>(); + test_is_not_default_constructible<int&&>(); + +// TODO: Remove this workaround once Clang <= 3.7 are no longer used regularly. +// In those compiler versions the __is_constructible builtin gives the wrong +// results for abominable function types. +#if (defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER < 703) \ + || (defined(TEST_CLANG_VER) && TEST_CLANG_VER < 308) +#define WORKAROUND_CLANG_BUG +#endif +#if !defined(WORKAROUND_CLANG_BUG) + test_is_not_default_constructible<void()>(); + test_is_not_default_constructible<void() const> (); + test_is_not_default_constructible<void() volatile> (); + test_is_not_default_constructible<void() &> (); + test_is_not_default_constructible<void() &&> (); +#endif #endif } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_empty.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_empty.pass.cpp index 410c1db7244d..7be76f4fa96a 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_empty.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_empty.pass.cpp @@ -11,6 +11,14 @@ // is_empty +// T is a non-union class type with: +// no non-static data members, +// no unnamed bit-fields of non-zero length, +// no virtual member functions, +// no virtual base classes, +// and no base class B for which is_empty_v<B> is false. + + #include <type_traits> #include "test_macros.h" @@ -44,22 +52,33 @@ void test_is_not_empty() #endif } -class Empty -{ -}; +class Empty {}; +struct NotEmpty { int foo; }; -class NotEmpty +class VirtualFn { - virtual ~NotEmpty(); + virtual ~VirtualFn(); }; union Union {}; +struct EmptyBase : public Empty {}; +struct VirtualBase : virtual Empty {}; +struct NotEmptyBase : public NotEmpty {}; + +struct StaticMember { static int foo; }; +struct NonStaticMember { int foo; }; + struct bit_zero { int : 0; }; +struct bit_one +{ + int : 1; +}; + int main() { test_is_not_empty<void>(); @@ -72,7 +91,14 @@ int main() test_is_not_empty<char[]>(); test_is_not_empty<Union>(); test_is_not_empty<NotEmpty>(); + test_is_not_empty<VirtualFn>(); + test_is_not_empty<VirtualBase>(); + test_is_not_empty<NotEmptyBase>(); + test_is_not_empty<NonStaticMember>(); +// test_is_not_empty<bit_one>(); test_is_empty<Empty>(); + test_is_empty<EmptyBase>(); + test_is_empty<StaticMember>(); test_is_empty<bit_zero>(); } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_assignable.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_assignable.pass.cpp index 613c1123e3fa..6209bc7b1483 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_assignable.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_assignable.pass.cpp @@ -63,7 +63,7 @@ int main() test_is_move_assignable<NotEmpty> (); test_is_move_assignable<Empty> (); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 test_is_not_move_assignable<const int> (); test_is_not_move_assignable<int[]> (); test_is_not_move_assignable<int[3]> (); diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_constructible.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_constructible.pass.cpp index 07c283bf8890..e81f8d4f43c4 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_constructible.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_move_constructible.pass.cpp @@ -62,7 +62,7 @@ struct A struct B { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 B(B&&); #endif }; diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_assignable.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_assignable.pass.cpp index 9d629dc7ef46..3349a9d3a968 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_assignable.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_assignable.pass.cpp @@ -50,7 +50,7 @@ int main() { test_is_nothrow_assignable<int&, int&> (); test_is_nothrow_assignable<int&, int> (); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 test_is_nothrow_assignable<int&, double> (); #endif diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_constructible.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_constructible.pass.cpp index 8200b468fe3a..f36b80cac17c 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_constructible.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_constructible.pass.cpp @@ -92,7 +92,7 @@ struct C void operator=(C&); // not const }; -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 struct Tuple { Tuple(Empty&&) noexcept {} }; @@ -104,15 +104,14 @@ int main() test_is_nothrow_constructible<int, const int&> (); test_is_nothrow_constructible<Empty> (); test_is_nothrow_constructible<Empty, const Empty&> (); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - test_is_nothrow_constructible<Tuple &&, Empty> (); // See bug #19616. -#endif test_is_not_nothrow_constructible<A, int> (); test_is_not_nothrow_constructible<A, int, double> (); test_is_not_nothrow_constructible<A> (); test_is_not_nothrow_constructible<C> (); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 + test_is_nothrow_constructible<Tuple &&, Empty> (); // See bug #19616. + static_assert(!std::is_constructible<Tuple&, Empty>::value, ""); test_is_not_nothrow_constructible<Tuple &, Empty> (); // See bug #19616. #endif diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp index 408231f6057f..b23a5e45f287 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp @@ -59,7 +59,7 @@ int main() !std::is_nothrow_swappable_with<A&, A&>::value, ""); } { - // test that hetrogenius swap is allowed only if both 'swap(A, B)' and + // test that heterogeneous swap is allowed only if both 'swap(A, B)' and // 'swap(B, A)' are valid. static_assert(std::is_nothrow_swappable_with<A&, B&>::value, ""); static_assert(!std::is_nothrow_swappable_with<A&, C&>::value && diff --git a/test/std/utilities/utility/forward/forward2.fail.cpp b/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp index 9ff07233fee8..e3c7bb5ad27b 100644 --- a/test/std/utilities/utility/forward/forward2.fail.cpp +++ b/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp @@ -7,19 +7,17 @@ // //===----------------------------------------------------------------------===// -// test forward +// UNSUPPORTED: c++98, c++03, c++11, c++14 -#include <utility> +// <optional> -struct A -{ -}; +// class bad_optional_access is default constructible -A source() {return A();} -const A csource() {return A();} +#include <optional> +#include <type_traits> int main() { - const A ca = A(); - std::forward<A&>(ca); // error + using std::bad_optional_access; + bad_optional_access ex; } diff --git a/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp b/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp new file mode 100644 index 000000000000..85e36d2c107d --- /dev/null +++ b/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// class bad_optional_access : public logic_error + +#include <optional> +#include <type_traits> + +int main() +{ + using std::bad_optional_access; + + static_assert(std::is_base_of<std::logic_error, bad_optional_access>::value, ""); + static_assert(std::is_convertible<bad_optional_access*, std::logic_error*>::value, ""); +} diff --git a/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp b/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp new file mode 100644 index 000000000000..b54a08f5575b --- /dev/null +++ b/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator==(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator==(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator == ( const X &lhs, const X &rhs ) + { return lhs.i_ == rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 == T(1)), "" ); + static_assert ( (o2 == T(1)), "" ); + static_assert ( !(o3 == T(1)), "" ); + static_assert ( (o3 == T(2)), "" ); + static_assert ( (o3 == val), "" ); + + static_assert ( !(T(1) == o1), "" ); + static_assert ( (T(1) == o2), "" ); + static_assert ( !(T(1) == o3), "" ); + static_assert ( (T(2) == o3), "" ); + static_assert ( (val == o3), "" ); + } +} diff --git a/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp b/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp new file mode 100644 index 000000000000..064114fb9db2 --- /dev/null +++ b/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator>(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator > ( const X &lhs, const X &rhs ) + { return lhs.i_ > rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 > T(1)), "" ); + static_assert ( !(o2 > T(1)), "" ); // equal + static_assert ( (o3 > T(1)), "" ); + static_assert ( !(o2 > val), "" ); + static_assert ( !(o3 > val), "" ); // equal + static_assert ( !(o3 > T(3)), "" ); + + static_assert ( (T(1) > o1), "" ); + static_assert ( !(T(1) > o2), "" ); // equal + static_assert ( !(T(1) > o3), "" ); + static_assert ( (val > o2), "" ); + static_assert ( !(val > o3), "" ); // equal + static_assert ( (T(3) > o3), "" ); + } +} diff --git a/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp b/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp new file mode 100644 index 000000000000..663686cdf347 --- /dev/null +++ b/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator>=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator >= ( const X &lhs, const X &rhs ) + { return lhs.i_ >= rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 >= T(1)), "" ); + static_assert ( (o2 >= T(1)), "" ); // equal + static_assert ( (o3 >= T(1)), "" ); + static_assert ( !(o2 >= val), "" ); + static_assert ( (o3 >= val), "" ); // equal + static_assert ( !(o3 >= T(3)), "" ); + + static_assert ( (T(1) >= o1), "" ); + static_assert ( (T(1) >= o2), "" ); // equal + static_assert ( !(T(1) >= o3), "" ); + static_assert ( (val >= o2), "" ); + static_assert ( (val >= o3), "" ); // equal + static_assert ( (T(3) >= o3), "" ); + } +} diff --git a/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp b/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp new file mode 100644 index 000000000000..05ac5eb12b48 --- /dev/null +++ b/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator<=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator <= ( const X &lhs, const X &rhs ) + { return lhs.i_ <= rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 <= T(1)), "" ); + static_assert ( (o2 <= T(1)), "" ); // equal + static_assert ( !(o3 <= T(1)), "" ); + static_assert ( (o2 <= val), "" ); + static_assert ( (o3 <= val), "" ); // equal + static_assert ( (o3 <= T(3)), "" ); + + static_assert ( !(T(1) <= o1), "" ); + static_assert ( (T(1) <= o2), "" ); // equal + static_assert ( (T(1) <= o3), "" ); + static_assert ( !(val <= o2), "" ); + static_assert ( (val <= o3), "" ); // equal + static_assert ( !(T(3) <= o3), "" ); + } +} diff --git a/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp b/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp new file mode 100644 index 000000000000..d1891a286d7b --- /dev/null +++ b/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator<(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator < ( const X &lhs, const X &rhs ) + { return lhs.i_ < rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 < T(1)), "" ); + static_assert ( !(o2 < T(1)), "" ); // equal + static_assert ( !(o3 < T(1)), "" ); + static_assert ( (o2 < val), "" ); + static_assert ( !(o3 < val), "" ); // equal + static_assert ( (o3 < T(3)), "" ); + + static_assert ( !(T(1) < o1), "" ); + static_assert ( !(T(1) < o2), "" ); // equal + static_assert ( (T(1) < o3), "" ); + static_assert ( !(val < o2), "" ); + static_assert ( !(val < o3), "" ); // equal + static_assert ( !(T(3) < o3), "" ); + } +} diff --git a/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp b/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp new file mode 100644 index 000000000000..ae2ff808fb25 --- /dev/null +++ b/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator!=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator!=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator != ( const X &lhs, const X &rhs ) + { return lhs.i_ != rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 != T(1)), "" ); + static_assert ( !(o2 != T(1)), "" ); + static_assert ( (o3 != T(1)), "" ); + static_assert ( !(o3 != T(2)), "" ); + static_assert ( !(o3 != val), "" ); + + static_assert ( (T(1) != o1), "" ); + static_assert ( !(T(1) != o2), "" ); + static_assert ( (T(1) != o3), "" ); + static_assert ( !(T(2) != o3), "" ); + static_assert ( !(val != o3), "" ); + } +} diff --git a/test/std/utilities/optional/optional.hash/hash.pass.cpp b/test/std/utilities/optional/optional.hash/hash.pass.cpp new file mode 100644 index 000000000000..dfdd07ddf452 --- /dev/null +++ b/test/std/utilities/optional/optional.hash/hash.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> struct hash<optional<T>>; + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + + +int main() +{ + using std::optional; + const std::size_t nullopt_hash = + std::hash<optional<double>>{}(optional<double>{}); + + { + typedef int T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = 2; + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } + { + typedef std::string T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = std::string("123"); + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } + { + typedef std::unique_ptr<int> T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = std::unique_ptr<int>(new int(3)); + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } +} diff --git a/test/std/utilities/optional/optional.nullops/equal.pass.cpp b/test/std/utilities/optional/optional.nullops/equal.pass.cpp new file mode 100644 index 000000000000..a87a87f877fc --- /dev/null +++ b/test/std/utilities/optional/optional.nullops/equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt == o1), "" ); + static_assert ( !(nullopt == o2), "" ); + static_assert ( (o1 == nullopt), "" ); + static_assert ( !(o2 == nullopt), "" ); + + static_assert (noexcept(nullopt == o1), ""); + static_assert (noexcept(o1 == nullopt), ""); + } +} diff --git a/test/std/utilities/optional/optional.nullops/greater.pass.cpp b/test/std/utilities/optional/optional.nullops/greater.pass.cpp new file mode 100644 index 000000000000..3986a0a92658 --- /dev/null +++ b/test/std/utilities/optional/optional.nullops/greater.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt > o1), "" ); + static_assert ( !(nullopt > o2), "" ); + static_assert ( !(o1 > nullopt), "" ); + static_assert ( (o2 > nullopt), "" ); + + static_assert (noexcept(nullopt > o1), ""); + static_assert (noexcept(o1 > nullopt), ""); + } +} diff --git a/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp b/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp new file mode 100644 index 000000000000..9f2427273476 --- /dev/null +++ b/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt >= o1), "" ); + static_assert ( !(nullopt >= o2), "" ); + static_assert ( (o1 >= nullopt), "" ); + static_assert ( (o2 >= nullopt), "" ); + + static_assert (noexcept(nullopt >= o1), ""); + static_assert (noexcept(o1 >= nullopt), ""); + } +} diff --git a/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp b/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp new file mode 100644 index 000000000000..8e73247b9d6e --- /dev/null +++ b/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt <= o1), "" ); + static_assert ( (nullopt <= o2), "" ); + static_assert ( (o1 <= nullopt), "" ); + static_assert ( !(o2 <= nullopt), "" ); + + static_assert (noexcept(nullopt <= o1), ""); + static_assert (noexcept(o1 <= nullopt), ""); + } +} diff --git a/test/std/utilities/optional/optional.nullops/less_than.pass.cpp b/test/std/utilities/optional/optional.nullops/less_than.pass.cpp new file mode 100644 index 000000000000..39a8e4a39363 --- /dev/null +++ b/test/std/utilities/optional/optional.nullops/less_than.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt < o1), "" ); + static_assert ( (nullopt < o2), "" ); + static_assert ( !(o1 < nullopt), "" ); + static_assert ( !(o2 < nullopt), "" ); + + static_assert (noexcept(nullopt < o1), ""); + static_assert (noexcept(o1 < nullopt), ""); + } +} diff --git a/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp b/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp new file mode 100644 index 000000000000..1c96dd42e808 --- /dev/null +++ b/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt != o1), "" ); + static_assert ( (nullopt != o2), "" ); + static_assert ( !(o1 != nullopt), "" ); + static_assert ( (o2 != nullopt), "" ); + + static_assert (noexcept(nullopt != o1), ""); + static_assert (noexcept(o1 != nullopt), ""); + } +} diff --git a/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp b/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp new file mode 100644 index 000000000000..86da5054a708 --- /dev/null +++ b/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// struct nullopt_t{see below}; + +#include <optional> + +using std::optional; +using std::nullopt_t; + +int main() +{ + // I roughly interpret LWG2736 as "it shall not be possible to copy-list-initialize nullopt_t with an + // empty braced-init-list." + nullopt_t foo = {}; +} diff --git a/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp new file mode 100644 index 000000000000..84bb29fabac8 --- /dev/null +++ b/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// struct nullopt_t{see below}; +// constexpr nullopt_t nullopt(unspecified); + +#include <optional> +#include <type_traits> + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +constexpr +int +test(const nullopt_t&) +{ + return 3; +} + +int main() +{ + static_assert((std::is_class<nullopt_t>::value), ""); + static_assert((std::is_empty<nullopt_t>::value), ""); + static_assert((std::is_literal_type<nullopt_t>::value), ""); + static_assert((!std::is_default_constructible<nullopt_t>::value), ""); + + static_assert(test(nullopt) == 3, ""); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp new file mode 100644 index 000000000000..1207e24150ff --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp @@ -0,0 +1,273 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> optional<T>& operator=(U&& v); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct ThrowAssign { + static int dtor_called; + ThrowAssign() = default; + ThrowAssign(int) { TEST_THROW(42); } + ThrowAssign& operator=(int) { + TEST_THROW(42); + } + ~ThrowAssign() { ++dtor_called; } +}; +int ThrowAssign::dtor_called = 0; + +template <class T, class Arg = T, bool Expect = true> +void assert_assignable() { + static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, ""); + static_assert(!std::is_assignable<const optional<T>&, Arg>::value, ""); +} + +struct MismatchType { + explicit MismatchType(int) {} + explicit MismatchType(char*) {} + explicit MismatchType(int*) = delete; + MismatchType& operator=(int) { return *this; } + MismatchType& operator=(int*) { return *this; } + MismatchType& operator=(char*) = delete; +}; + +struct FromOptionalType { + using Opt = std::optional<FromOptionalType>; + FromOptionalType() = default; + FromOptionalType(FromOptionalType const&) = delete; + template <class Dummy = void> + constexpr FromOptionalType(Opt&) { Dummy::BARK; } + template <class Dummy = void> + constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; } +}; + +void test_sfinae() { + using I = TestTypes::TestType; + using E = ExplicitTestTypes::TestType; + assert_assignable<int>(); + assert_assignable<int, int&>(); + assert_assignable<int, int const&>(); + // Implicit test type + assert_assignable<I, I const&>(); + assert_assignable<I, I&&>(); + assert_assignable<I, int>(); + assert_assignable<I, void*, false>(); + // Explicit test type + assert_assignable<E, E const&>(); + assert_assignable<E, E &&>(); + assert_assignable<E, int>(); + assert_assignable<E, void*, false>(); + // Mismatch type + assert_assignable<MismatchType, int>(); + assert_assignable<MismatchType, int*, false>(); + assert_assignable<MismatchType, char*, false>(); + // Type constructible from optional + assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>(); +} + +void test_with_test_type() +{ + using T = TestTypes::TestType; + T::reset(); + { // to empty + optional<T> opt; + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(42); + T::reset_constructors(); + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 1); + assert(T::move_assigned == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {}; + assert(static_cast<bool>(opt) == false); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + } +} + +template <class T, class Value = int> +void test_with_type() { + { // to empty + optional<T> opt; + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(Value(42)); + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test const + optional<T> opt(Value(42)); + const T t(Value(3)); + opt = t; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + opt = {Value(1)}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(Value(42)); + opt = {}; + assert(static_cast<bool>(opt) == false); + } +} + +template <class T> +void test_with_type_multi() { + test_with_type<T>(); + { // test default argument + optional<T> opt; + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } +} + +void test_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using T = ThrowAssign; + { + using T = ThrowAssign; + optional<T> opt; + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == false); + } + assert(T::dtor_called == 0); + { + T::dtor_called = 0; + optional<T> opt(std::in_place); + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == true); + assert(T::dtor_called == 0); + } + assert(T::dtor_called == 1); +#endif +} + +enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 }; + +using Fn = void(*)(); + +int main() +{ + test_sfinae(); + // Test with instrumented type + test_with_test_type(); + // Test with various scalar types + test_with_type<int>(); + test_with_type<MyEnum, MyEnum>(); + test_with_type<int, MyEnum>(); + test_with_type<Fn, Fn>(); + // Test types with multi argument constructors + test_with_type_multi<ConstexprTestTypes::TestType>(); + test_with_type_multi<TrivialTestTypes::TestType>(); + // Test move only types + { + optional<std::unique_ptr<int>> opt; + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + { + optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2))); + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + test_throws(); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp new file mode 100644 index 000000000000..d471c053c907 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp @@ -0,0 +1,254 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// From LWG2451: +// template<class U> +// optional<T>& operator=(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(int) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +struct Y1 +{ + Y1() = default; + Y1(const int&) {} + Y1& operator=(const Y1&) = delete; +}; + +struct Y2 +{ + Y2() = default; + Y2(const int&) = delete; + Y2& operator=(const int&) { return *this; } +}; + +template <class T> +struct AssignableFrom { + static int type_constructed; + static int type_assigned; +static int int_constructed; + static int int_assigned; + + static void reset() { + type_constructed = int_constructed = 0; + type_assigned = int_assigned = 0; + } + + AssignableFrom() = default; + + explicit AssignableFrom(T) { ++type_constructed; } + AssignableFrom& operator=(T) { ++type_assigned; return *this; } + + AssignableFrom(int) { ++int_constructed; } + AssignableFrom& operator=(int) { ++int_assigned; return *this; } +private: + AssignableFrom(AssignableFrom const&) = delete; + AssignableFrom& operator=(AssignableFrom const&) = delete; +}; + +template <class T> int AssignableFrom<T>::type_constructed = 0; +template <class T> int AssignableFrom<T>::type_assigned = 0; +template <class T> int AssignableFrom<T>::int_constructed = 0; +template <class T> int AssignableFrom<T>::int_assigned = 0; + + +void test_with_test_type() { + using T = TestTypes::TestType; + T::reset(); + { // non-empty to empty + T::reset_constructors(); + optional<T> opt; + const optional<int> other(42); + opt = other; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // non-empty to non-empty + optional<T> opt(101); + const optional<int> other(42); + T::reset_constructors(); + opt = other; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // empty to non-empty + optional<T> opt(101); + const optional<int> other; + T::reset_constructors(); + opt = other; + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); + { // empty to empty + optional<T> opt; + const optional<int> other; + T::reset_constructors(); + opt = other; + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); +} + +void test_ambigious_assign() { + using OptInt = std::optional<int>; + { + using T = AssignableFrom<OptInt const&>; + const OptInt a(42); + T::reset(); + { + std::optional<T> t; + t = a; + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + T::reset(); + { + std::optional<T> t(42); + t = a; + assert(T::type_constructed == 0); + assert(T::type_assigned == 1); + assert(T::int_constructed == 1); + assert(T::int_assigned == 0); + } + T::reset(); + { + std::optional<T> t(42); + t = std::move(a); + assert(T::type_constructed == 0); + assert(T::type_assigned == 1); + assert(T::int_constructed == 1); + assert(T::int_assigned == 0); + } + } + { + using T = AssignableFrom<OptInt&>; + OptInt a(42); + T::reset(); + { + std::optional<T> t; + t = a; + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(!std::is_assignable_v<Opt&, OptInt const&>, ""); + } + } +} + + +int main() +{ + test_with_test_type(); + test_ambigious_assign(); + { + optional<int> opt; + constexpr optional<short> opt2; + opt = opt2; + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + constexpr optional<short> opt2(short{2}); + opt = opt2; + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + constexpr optional<short> opt2; + opt = opt2; + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + constexpr optional<short> opt2(short{2}); + opt = opt2; + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<int> opt2(42); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = opt2; + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp new file mode 100644 index 000000000000..98c90aa1d4fb --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(const optional<T>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(const X&) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +template <class Tp> +constexpr bool assign_empty(optional<Tp>&& lhs) { + const optional<Tp> rhs; + lhs = rhs; + return !lhs.has_value() && !rhs.has_value(); +} + +template <class Tp> +constexpr bool assign_value(optional<Tp>&& lhs) { + const optional<Tp> rhs(101); + lhs = rhs; + return lhs.has_value() && rhs.has_value() && *lhs == *rhs; +} + +int main() +{ + { + using O = optional<int>; + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TrivialTestTypes::TestType>; + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TestTypes::TestType>; + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> opt(3); + const optional<T> opt2; + assert(T::alive == 1); + opt = opt2; + assert(T::alive == 0); + assert(!opt2.has_value()); + assert(!opt.has_value()); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<X> opt2(X{}); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = opt2; + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp new file mode 100644 index 000000000000..b5362589963c --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class... Args> void optional<T>::emplace(Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ +public: + static bool dtor_called; + Y() = default; + Y(int) { TEST_THROW(6);} + ~Y() {dtor_called = true;} +}; + +bool Y::dtor_called = false; + +template <class T> +void test_one_arg() { + using Opt = std::optional<T>; + { + Opt opt; + opt.emplace(); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(0)); + } + { + Opt opt; + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { + Opt opt(2); + opt.emplace(); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(0)); + } + { + Opt opt(2); + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } +} + + +template <class T> +void test_multi_arg() +{ + test_one_arg<T>(); + using Opt = std::optional<T>; + { + Opt opt; + opt.emplace(101, 41); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(101, 41)); + } + { + Opt opt; + opt.emplace({1, 2, 3, 4}); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // T sets its value to the size of the init list + } + { + Opt opt; + opt.emplace({1, 2, 3, 4, 5}, 6); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(5)); // T sets its value to the size of the init list + } +} + +template <class T> +void test_on_test_type() { + + T::reset(); + optional<T> opt; + assert(T::alive == 0); + { + T::reset_constructors(); + opt.emplace(); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::default_constructed == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T()); + } + { + T::reset_constructors(); + opt.emplace(); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::default_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T()); + } + { + T::reset_constructors(); + opt.emplace(101); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(101)); + } + { + T::reset_constructors(); + opt.emplace(-10, 99); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(-10, 99)); + } + { + T::reset_constructors(); + opt.emplace(-10, 99); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(-10, 99)); + } + { + T::reset_constructors(); + opt.emplace({-10, 99, 42, 1}); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // size of the initializer list + } + { + T::reset_constructors(); + opt.emplace({-10, 99, 42, 1}, 42); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // size of the initializer list + } +} + + + +int main() +{ + { + test_on_test_type<TestTypes::TestType>(); + test_on_test_type<ExplicitTestTypes::TestType>(); + } + { + using T = int; + test_one_arg<T>(); + test_one_arg<const T>(); + } + { + using T = ConstexprTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = ExplicitConstexprTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = TrivialTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = ExplicitTrivialTestTypes::TestType; + test_multi_arg<T>(); + } + { + optional<const int> opt; + opt.emplace(42); + assert(*opt == 42); + opt.emplace(); + assert(*opt == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + Y::dtor_called = false; + { + Y y; + optional<Y> opt(y); + try + { + assert(static_cast<bool>(opt) == true); + assert(Y::dtor_called == false); + opt.emplace(1); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + assert(Y::dtor_called == true); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp new file mode 100644 index 000000000000..1c3c69a70303 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U, class... Args> +// void optional<T>::emplace(initializer_list<U> il, Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <vector> + +#include "test_macros.h" + +using std::optional; + +class X +{ + int i_; + int j_ = 0; +public: + static bool dtor_called; + constexpr X() : i_(0) {} + constexpr X(int i) : i_(i) {} + constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + ~X() {dtor_called = true;} + + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +bool X::dtor_called = false; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ + int i_; + int j_ = 0; +public: + static bool dtor_called; + Z() : i_(0) {} + Z(int i) : i_(i) {} + Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) + { TEST_THROW(6);} + ~Z() {dtor_called = true;} + + friend bool operator==(const Z& x, const Z& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +bool Z::dtor_called = false; + +int main() +{ + { + X x; + optional<X> opt(x); + assert(X::dtor_called == false); + opt.emplace({1, 2}); + assert(X::dtor_called == true); + assert(*opt == X({1, 2})); + } + { + optional<std::vector<int>> opt; + opt.emplace({1, 2, 3}, std::allocator<int>()); + assert(static_cast<bool>(opt) == true); + assert(*opt == std::vector<int>({1, 2, 3})); + } + { + optional<Y> opt; + opt.emplace({1, 2}); + assert(static_cast<bool>(opt) == true); + assert(*opt == Y({1, 2})); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + Z z; + optional<Z> opt(z); + try + { + assert(static_cast<bool>(opt) == true); + assert(Z::dtor_called == false); + opt.emplace({1, 2}); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + assert(Z::dtor_called == true); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp new file mode 100644 index 000000000000..3ba261b52464 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(optional<T>&& rhs) +// noexcept(is_nothrow_move_assignable<T>::value && +// is_nothrow_move_constructible<T>::value); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + static int alive; + + X() { ++alive; } + X(X&&) + { + if (throw_now) + TEST_THROW(6); + ++alive; + } + + X& operator=(X&&) + { + if (throw_now) + TEST_THROW(42); + return *this; + } + + ~X() { assert(alive > 0); --alive; } +}; + +struct Y {}; + +bool X::throw_now = false; +int X::alive = 0; + +int main() +{ + { + static_assert(std::is_nothrow_move_assignable<optional<int>>::value, ""); + optional<int> opt; + constexpr optional<int> opt2; + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + constexpr optional<int> opt2(2); + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + constexpr optional<int> opt2; + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> opt(3); + optional<T> opt2; + assert(T::alive == 1); + opt = std::move(opt2); + assert(T::alive == 0); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + constexpr optional<int> opt2(2); + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); + X::alive = 0; + X::throw_now = false; + optional<X> opt; + optional<X> opt2(X{}); + assert(X::alive == 1); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + assert(X::alive == 1); + } + assert(X::alive == 0); + { + static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); + X::throw_now = false; + optional<X> opt(X{}); + optional<X> opt2(X{}); + assert(X::alive == 2); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 42); + assert(static_cast<bool>(opt) == true); + } + assert(X::alive == 2); + } + assert(X::alive == 0); +#endif // TEST_HAS_NO_EXCEPTIONS + { + static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, ""); + } + { + struct ThrowsMove { + ThrowsMove() noexcept {} + ThrowsMove(ThrowsMove const&) noexcept {} + ThrowsMove(ThrowsMove &&) noexcept(false) {} + ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; } + ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; } + }; + static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, ""); + struct ThrowsMoveAssign { + ThrowsMoveAssign() noexcept {} + ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {} + ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {} + ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; } + ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; } + }; + static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, ""); + struct NoThrowMove { + NoThrowMove() noexcept(false) {} + NoThrowMove(NoThrowMove const&) noexcept(false) {} + NoThrowMove(NoThrowMove &&) noexcept {} + NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; } + NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; } + }; + static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, ""); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp new file mode 100644 index 000000000000..991f4334304c --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(nullopt_t) noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +int main() +{ + { + optional<int> opt; + static_assert(noexcept(opt = nullopt) == true, ""); + opt = nullopt; + assert(static_cast<bool>(opt) == false); + } + { + optional<int> opt(3); + opt = nullopt; + assert(static_cast<bool>(opt) == false); + } + using TT = TestTypes::TestType; + TT::reset(); + { + optional<TT> opt; + static_assert(noexcept(opt = nullopt) == true, ""); + assert(TT::destroyed == 0); + opt = nullopt; + assert(TT::constructed == 0); + assert(TT::alive == 0); + assert(TT::destroyed == 0); + assert(static_cast<bool>(opt) == false); + } + assert(TT::alive == 0); + assert(TT::destroyed == 0); + TT::reset(); + { + optional<TT> opt(42); + assert(TT::destroyed == 0); + TT::reset_constructors(); + opt = nullopt; + assert(TT::constructed == 0); + assert(TT::alive == 0); + assert(TT::destroyed == 1); + assert(static_cast<bool>(opt) == false); + } + assert(TT::alive == 0); + assert(TT::destroyed == 1); + TT::reset(); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp new file mode 100644 index 000000000000..db7fc19bfb10 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// From LWG2451: +// template <class U> +// optional<T>& operator=(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <memory> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(int &&) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +struct Y1 +{ + Y1() = default; + Y1(const int&) {} + Y1& operator=(const Y1&) = delete; +}; + +struct Y2 +{ + Y2() = default; + Y2(const int&) = delete; + Y2& operator=(const int&) { return *this; } +}; + +class B {}; +class D : public B {}; + + +template <class T> +struct AssignableFrom { + static int type_constructed; + static int type_assigned; +static int int_constructed; + static int int_assigned; + + static void reset() { + type_constructed = int_constructed = 0; + type_assigned = int_assigned = 0; + } + + AssignableFrom() = default; + + explicit AssignableFrom(T) { ++type_constructed; } + AssignableFrom& operator=(T) { ++type_assigned; return *this; } + + AssignableFrom(int) { ++int_constructed; } + AssignableFrom& operator=(int) { ++int_assigned; return *this; } +private: + AssignableFrom(AssignableFrom const&) = delete; + AssignableFrom& operator=(AssignableFrom const&) = delete; +}; + +template <class T> int AssignableFrom<T>::type_constructed = 0; +template <class T> int AssignableFrom<T>::type_assigned = 0; +template <class T> int AssignableFrom<T>::int_constructed = 0; +template <class T> int AssignableFrom<T>::int_assigned = 0; + +void test_with_test_type() { + using T = TestTypes::TestType; + T::reset(); + { // non-empty to empty + T::reset_constructors(); + optional<T> opt; + optional<int> other(42); + opt = std::move(other); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // non-empty to non-empty + optional<T> opt(101); + optional<int> other(42); + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // empty to non-empty + optional<T> opt(101); + optional<int> other; + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); + { // empty to empty + optional<T> opt; + optional<int> other; + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); +} + + +void test_ambigious_assign() { + using OptInt = std::optional<int>; + { + using T = AssignableFrom<OptInt&&>; + T::reset(); + { + OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, ""); + static_assert(!std::is_assignable<Opt&, const OptInt&>::value, ""); + static_assert(!std::is_assignable<Opt&, OptInt&>::value, ""); + } + } + { + using T = AssignableFrom<OptInt const&&>; + T::reset(); + { + const OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + T::reset(); + { + OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(std::is_assignable<Opt&, OptInt&&>::value, ""); + static_assert(!std::is_assignable<Opt&, const OptInt&>::value, ""); + static_assert(!std::is_assignable<Opt&, OptInt&>::value, ""); + } + } +} + + +int main() +{ + test_with_test_type(); + test_ambigious_assign(); + { + optional<int> opt; + optional<short> opt2; + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + optional<short> opt2(short{2}); + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + optional<short> opt2; + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + optional<short> opt2(short{2}); + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<std::unique_ptr<B>> opt; + optional<std::unique_ptr<D>> other(new D()); + opt = std::move(other); + assert(static_cast<bool>(opt) == true); + assert(static_cast<bool>(other) == true); + assert(opt->get() != nullptr); + assert(other->get() == nullptr); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<int> opt2(42); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp new file mode 100644 index 000000000000..c4d4763a6f0a --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// template <class U> +// constexpr EXPLICIT optional(U&& u); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" +#include "test_convertible.hpp" + + +using std::optional; + +struct ImplicitThrow +{ + constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);} +}; + +struct ExplicitThrow +{ + constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);} +}; + + +template <class To, class From> +constexpr bool implicit_conversion(optional<To>&& opt, const From& v) +{ + using O = optional<To>; + static_assert(test_convertible<O, From>(), ""); + static_assert(!test_convertible<O, void*>(), ""); + static_assert(!test_convertible<O, From, int>(), ""); + return opt && *opt == static_cast<To>(v); +} + +template <class To, class Input, class Expect> +constexpr bool explicit_conversion(Input&& in, const Expect& v) +{ + using O = optional<To>; + static_assert(std::is_constructible<O, Input>::value, ""); + static_assert(!std::is_convertible<Input, O>::value, ""); + static_assert(!std::is_constructible<O, void*>::value, ""); + static_assert(!std::is_constructible<O, Input, int>::value, ""); + optional<To> opt(std::forward<Input>(in)); + return opt && *opt == static_cast<To>(v); +} + +void test_implicit() +{ + { + using T = long long; + static_assert(implicit_conversion<long long>(42, 42), ""); + } + { + using T = long double; + static_assert(implicit_conversion<long double>(3.14, 3.14), ""); + } + { + int x = 42; + optional<void* const> o(&x); + assert(*o == &x); + } + { + using T = TrivialTestTypes::TestType; + static_assert(implicit_conversion<T>(42, 42), ""); + } + { + using T = TestTypes::TestType; + assert(implicit_conversion<T>(3, T(3))); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + using T = ImplicitThrow; + optional<T> t = 42; + assert(false); + ((void)t); + } catch (int) { + } + } +#endif +} + +void test_explicit() { + { + using T = ExplicitTrivialTestTypes::TestType; + using O = optional<T>; + static_assert(explicit_conversion<T>(42, 42), ""); + } + { + using T = ExplicitConstexprTestTypes::TestType; + using O = optional<T>; + static_assert(explicit_conversion<T>(42, 42), ""); + static_assert(!std::is_convertible<int, T>::value, ""); + } + { + using T = ExplicitTestTypes::TestType; + using O = optional<T>; + T::reset(); + { + assert(explicit_conversion<T>(42, 42)); + assert(T::alive == 0); + } + T::reset(); + { + optional<T> t(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::move_constructed == 0); + assert(T::copy_constructed == 0); + assert(t.value().value == 42); + } + assert(T::alive == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + using T = ExplicitThrow; + optional<T> t(42); + assert(false); + } catch (int) { + } + } +#endif +} + +int main() { + test_implicit(); + test_explicit(); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp new file mode 100644 index 000000000000..34a12b8ad1c3 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp @@ -0,0 +1,128 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// constexpr optional(const T& v); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +int main() +{ + { + typedef int T; + constexpr T t(5); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } + { + typedef double T; + constexpr T t(3); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } + { + const int x = 42; + optional<const int> o(x); + assert(*o == x); + } + { + typedef TestTypes::TestType T; + T::reset(); + const T t(3); + optional<T> opt = t; + assert(T::alive == 2); + assert(T::copy_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ExplicitTestTypes::TestType T; + static_assert(!std::is_convertible<T const&, optional<T>>::value, ""); + T::reset(); + const T t(3); + optional<T> opt(t); + assert(T::alive == 2); + assert(T::copy_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ConstexprTestTypes::TestType T; + constexpr T t(3); + constexpr optional<T> opt = {t}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ExplicitConstexprTestTypes::TestType T; + static_assert(!std::is_convertible<const T&, optional<T>>::value, ""); + constexpr T t(3); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + struct Z { + Z(int) {} + Z(const Z&) {throw 6;} + }; + typedef Z T; + try + { + const T t(3); + optional<T> opt(t); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp new file mode 100644 index 000000000000..e12f6cb28f5a --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// optional(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(const optional<U>& rhs, bool is_going_to_throw = false) +{ + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs = rhs; + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); +#endif +} + +class X +{ + int i_; +public: + X(int i) : i_(i) {} + X(const X& x) : i_(x.i_) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +class Y +{ + int i_; +public: + Y(int i) : i_(i) {} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {TEST_THROW(6);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} +}; + + +int main() +{ + { + typedef short U; + typedef int T; + optional<U> rhs; + test<T>(rhs); + } + { + typedef short U; + typedef int T; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs, true); + } + + static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), ""); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp new file mode 100644 index 000000000000..5906d4edd119 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional(const optional<T>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class T, class ...InitArgs> +void test(InitArgs&&... args) +{ + const optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); +} + +void test_throwing_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Z { + Z() : count(0) {} + Z(Z const& o) : count(o.count + 1) + { if (count == 2) throw 6; } + int count; + }; + const Z z; + const optional<Z> rhs(z); + try + { + optional<Z> lhs(rhs); + assert(false); + } + catch (int i) + { + assert(i == 6); + } +#endif +} + +template <class T, class ...InitArgs> +void test_ref(InitArgs&&... args) +{ + const optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(&(*lhs) == &(*rhs)); +} + + +void test_reference_extension() +{ +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + using T = TestTypes::TestType; + T::reset(); + { + T t; + T::reset_constructors(); + test_ref<T&>(); + test_ref<T&>(t); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::destroyed == 1); + assert(T::alive == 0); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&>(); + test_ref<T const&>(t); + test_ref<T const&>(ct); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); + static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); + } +#endif +} + +int main() +{ + test<int>(); + test<int>(3); + { + const optional<const int> o(42); + optional<const int> o2(o); + assert(*o2 == 42); + } + { + using T = TestTypes::TestType; + T::reset(); + const optional<T> rhs; + assert(T::alive == 0); + const optional<T> lhs(rhs); + assert(lhs.has_value() == false); + assert(T::alive == 0); + } + TestTypes::TestType::reset(); + { + using T = TestTypes::TestType; + T::reset(); + const optional<T> rhs(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::copy_constructed == 0); + const optional<T> lhs(rhs); + assert(lhs.has_value()); + assert(T::copy_constructed == 1); + assert(T::alive == 2); + } + TestTypes::TestType::reset(); + { + using namespace ConstexprTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + using namespace TrivialTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + test_throwing_ctor(); + } + { + test_reference_extension(); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp new file mode 100644 index 000000000000..62795b91f9fd --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr optional() noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class Opt> +void +test_constexpr() +{ + static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, ""); + + constexpr Opt opt; + static_assert(static_cast<bool>(opt) == false, ""); + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +template <class Opt> +void +test() +{ + static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, ""); + { + Opt opt; + assert(static_cast<bool>(opt) == false); + } + { + const Opt opt; + assert(static_cast<bool>(opt) == false); + } + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +int main() +{ + test_constexpr<optional<int>>(); + test_constexpr<optional<int*>>(); + test_constexpr<optional<ImplicitTypes::NoCtors>>(); + test_constexpr<optional<NonTrivialTypes::NoCtors>>(); + test_constexpr<optional<NonConstexprTypes::NoCtors>>(); + test<optional<NonLiteralTypes::NoCtors>>(); + // EXTENSIONS +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + test_constexpr<optional<int&>>(); + test_constexpr<optional<const int&>>(); + test_constexpr<optional<int&>>(); + test_constexpr<optional<NonLiteralTypes::NoCtors&>>(); + test_constexpr<optional<NonLiteralTypes::NoCtors&&>>(); +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp new file mode 100644 index 000000000000..64ac05316c2a --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// explicit optional(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(const optional<U>& rhs, bool is_going_to_throw = false) +{ + static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), ""); + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs(rhs); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == T(*rhs)); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == T(*rhs)); +#endif +} + +class X +{ + int i_; +public: + explicit X(int i) : i_(i) {} + X(const X& x) : i_(x.i_) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +class Y +{ + int i_; +public: + explicit Y(int i) : i_(i) {} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ + int i_; +public: + explicit Z(int i) : i_(i) { TEST_THROW(6);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} +}; + + +int main() +{ + { + typedef X T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs, true); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp new file mode 100644 index 000000000000..2c6757a95825 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// explicit optional(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(optional<U>&& rhs, bool is_going_to_throw = false) +{ + static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), ""); + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs(std::move(rhs)); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs(std::move(rhs)); + assert(static_cast<bool>(lhs) == rhs_engaged); +#endif +} + +class X +{ + int i_; +public: + explicit X(int i) : i_(i) {} + X(X&& x) : i_(std::exchange(x.i_, 0)) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ +public: + explicit Z(int) { TEST_THROW(6); } +}; + +int main() +{ + { + optional<int> rhs; + test<X>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<X>(std::move(rhs)); + } + { + optional<int> rhs; + test<Z>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<Z>(std::move(rhs), true); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp new file mode 100644 index 000000000000..d0823d2c8c82 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp @@ -0,0 +1,148 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// template <class... Args> +// constexpr explicit optional(in_place_t, Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + ~X() {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(int i, int j) : i_(i), j_(j) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ +public: + Z(int) {TEST_THROW(6);} +}; + + +int main() +{ + { + constexpr optional<int> opt(in_place, 5); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<int> + { + constexpr test_constexpr_ctor(in_place_t, int i) + : optional<int>(in_place, i) {} + }; + + } + { + optional<const int> opt(in_place, 5); + assert(*opt == 5); + } + { + const optional<X> opt(in_place); + assert(static_cast<bool>(opt) == true); + assert(*opt == X()); + } + { + const optional<X> opt(in_place, 5); + assert(static_cast<bool>(opt) == true); + assert(*opt == X(5)); + } + { + const optional<X> opt(in_place, 5, 4); + assert(static_cast<bool>(opt) == true); + assert(*opt == X(5, 4)); + } + { + constexpr optional<Y> opt(in_place); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t) + : optional<Y>(in_place) {} + }; + + } + { + constexpr optional<Y> opt(in_place, 5); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(5), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, int i) + : optional<Y>(in_place, i) {} + }; + + } + { + constexpr optional<Y> opt(in_place, 5, 4); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(5, 4), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, int i, int j) + : optional<Y>(in_place, i, j) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try + { + const optional<Z> opt(in_place, 1); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp new file mode 100644 index 000000000000..6d9f45a97d45 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U, class... Args> +// constexpr +// explicit optional(in_place_t, initializer_list<U> il, Args&&... args); + +#include <optional> +#include <type_traits> +#include <vector> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + ~X() {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ + int i_; + int j_ = 0; +public: + Z() : i_(0) {} + Z(int i) : i_(i) {} + Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) + {TEST_THROW(6);} + + friend bool operator==(const Z& x, const Z& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +int main() +{ + { + static_assert(!std::is_constructible<X, std::initializer_list<int>&>::value, ""); + static_assert(!std::is_constructible<optional<X>, std::initializer_list<int>&>::value, ""); + } + { + optional<std::vector<int>> opt(in_place, {3, 1}); + assert(static_cast<bool>(opt) == true); + assert((*opt == std::vector<int>{3, 1})); + assert(opt->size() == 2); + } + { + optional<std::vector<int>> opt(in_place, {3, 1}, std::allocator<int>()); + assert(static_cast<bool>(opt) == true); + assert((*opt == std::vector<int>{3, 1})); + assert(opt->size() == 2); + } + { + static_assert(std::is_constructible<optional<Y>, std::initializer_list<int>&>::value, ""); + constexpr optional<Y> opt(in_place, {3, 1}); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y{3, 1}, ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, std::initializer_list<int> i) + : optional<Y>(in_place, i) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + static_assert(std::is_constructible<optional<Z>, std::initializer_list<int>&>::value, ""); + try + { + optional<Z> opt(in_place, {3, 1}); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp new file mode 100644 index 000000000000..bff6f5bf8f6f --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional(optional<T>&& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class T, class ...InitArgs> +void test(InitArgs&&... args) +{ + const optional<T> orig(std::forward<InitArgs>(args)...); + optional<T> rhs(orig); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *orig); +} + +void test_throwing_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Z { + Z() : count(0) {} + Z(Z&& o) : count(o.count + 1) + { if (count == 2) throw 6; } + int count; + }; + Z z; + optional<Z> rhs(std::move(z)); + try + { + optional<Z> lhs(std::move(rhs)); + assert(false); + } + catch (int i) + { + assert(i == 6); + } +#endif +} + + +template <class T, class ...InitArgs> +void test_ref(InitArgs&&... args) +{ + optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(&(*lhs) == &(*rhs)); +} + +void test_reference_extension() +{ +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + using T = TestTypes::TestType; + T::reset(); + { + T t; + T::reset_constructors(); + test_ref<T&>(); + test_ref<T&>(t); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::destroyed == 1); + assert(T::alive == 0); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&>(); + test_ref<T const&>(t); + test_ref<T const&>(ct); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + T t; + T::reset_constructors(); + test_ref<T&&>(); + test_ref<T&&>(std::move(t)); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&&>(); + test_ref<T const&&>(std::move(t)); + test_ref<T const&&>(std::move(ct)); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); + static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); + } +#endif +} + + +int main() +{ + test<int>(); + test<int>(3); + { + optional<const int> o(42); + optional<const int> o2(std::move(o)); + assert(*o2 == 42); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> rhs; + assert(T::alive == 0); + const optional<T> lhs(std::move(rhs)); + assert(lhs.has_value() == false); + assert(rhs.has_value() == false); + assert(T::alive == 0); + } + TestTypes::TestType::reset(); + { + using T = TestTypes::TestType; + T::reset(); + optional<T> rhs(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::move_constructed == 0); + const optional<T> lhs(std::move(rhs)); + assert(lhs.has_value()); + assert(rhs.has_value()); + assert(lhs.value().value == 42); + assert(rhs.value().value == -1); + assert(T::move_constructed == 1); + assert(T::alive == 2); + } + TestTypes::TestType::reset(); + { + using namespace ConstexprTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + using namespace TrivialTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + test_throwing_ctor(); + } + { + struct ThrowsMove { + ThrowsMove() noexcept(false) {} + ThrowsMove(ThrowsMove const&) noexcept(false) {} + ThrowsMove(ThrowsMove &&) noexcept(false) {} + }; + static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, ""); + struct NoThrowMove { + NoThrowMove() noexcept(false) {} + NoThrowMove(NoThrowMove const&) noexcept(false) {} + NoThrowMove(NoThrowMove &&) noexcept(true) {} + }; + static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, ""); + } + { + test_reference_extension(); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp new file mode 100644 index 000000000000..468a00346fc7 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr optional(nullopt_t) noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +template <class Opt> +void +test_constexpr() +{ + static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, ""); + static_assert(std::is_trivially_destructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, ""); + + constexpr Opt opt(nullopt); + static_assert(static_cast<bool>(opt) == false, ""); + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +template <class Opt> +void +test() +{ + static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, ""); + static_assert(!std::is_trivially_destructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, ""); + { + Opt opt(nullopt); + assert(static_cast<bool>(opt) == false); + } + { + const Opt opt(nullopt); + assert(static_cast<bool>(opt) == false); + } + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +int main() +{ + test_constexpr<optional<int>>(); + test_constexpr<optional<int*>>(); + test_constexpr<optional<ImplicitTypes::NoCtors>>(); + test_constexpr<optional<NonTrivialTypes::NoCtors>>(); + test_constexpr<optional<NonConstexprTypes::NoCtors>>(); + test<optional<NonLiteralTypes::NoCtors>>(); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp new file mode 100644 index 000000000000..0e180c14ec67 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// optional(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(optional<U>&& rhs, bool is_going_to_throw = false) +{ + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs = std::move(rhs); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); +#endif +} + +class X +{ + int i_; +public: + X(int i) : i_(i) {} + X(X&& x) : i_(std::exchange(x.i_, 0)) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +struct Z +{ + Z(int) { TEST_THROW(6); } +}; + +int main() +{ + { + optional<short> rhs; + test<int>(std::move(rhs)); + } + { + optional<short> rhs(short{3}); + test<int>(std::move(rhs)); + } + { + optional<int> rhs; + test<X>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<X>(std::move(rhs)); + } + { + optional<int> rhs; + test<Z>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<Z>(std::move(rhs), true); + } + + static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), ""); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp new file mode 100644 index 000000000000..eee749d01707 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp @@ -0,0 +1,153 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// constexpr optional(T&& v); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + + +using std::optional; + + +class Z +{ +public: + Z(int) {} + Z(Z&&) {TEST_THROW(6);} +}; + + +int main() +{ + { + typedef int T; + constexpr optional<T> opt(T(5)); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + } + { + typedef double T; + constexpr optional<T> opt(T(3)); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + } + { + const int x = 42; + optional<const int> o(std::move(x)); + assert(*o == 42); + } + { + typedef TestTypes::TestType T; + T::reset(); + optional<T> opt = T{3}; + assert(T::alive == 1); + assert(T::move_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ExplicitTestTypes::TestType T; + static_assert(!std::is_convertible<T&&, optional<T>>::value, ""); + T::reset(); + optional<T> opt(T{3}); + assert(T::alive == 1); + assert(T::move_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef TestTypes::TestType T; + T::reset(); + optional<T> opt = {3}; + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::copy_constructed == 0); + assert(T::move_constructed == 0); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ConstexprTestTypes::TestType T; + constexpr optional<T> opt = {T(3)}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ConstexprTestTypes::TestType T; + constexpr optional<T> opt = {3}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ExplicitConstexprTestTypes::TestType T; + static_assert(!std::is_convertible<T&&, optional<T>>::value, ""); + constexpr optional<T> opt(T{3}); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + struct Z { + Z(int) {} + Z(Z&&) {throw 6;} + }; + typedef Z T; + try + { + T t(3); + optional<T> opt(std::move(t)); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp new file mode 100644 index 000000000000..5132c9a73d0f --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// ~optional(); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct PODType { + int value; + int value2; +}; + +class X +{ +public: + static bool dtor_called; + X() = default; + ~X() {dtor_called = true;} +}; + +bool X::dtor_called = false; + +int main() +{ + { + typedef int T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef double T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef PODType T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef X T; + static_assert(!std::is_trivially_destructible<T>::value, ""); + static_assert(!std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(!std::is_literal_type<optional<T>>::value, ""); + { + X x; + optional<X> opt{x}; + assert(X::dtor_called == false); + } + assert(X::dtor_called == true); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp new file mode 100644 index 000000000000..cee73da849b6 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// void reset() noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + static bool dtor_called; + ~X() {dtor_called = true;} +}; + +bool X::dtor_called = false; + +int main() +{ + { + optional<int> opt; + static_assert(noexcept(opt.reset()) == true, ""); + opt.reset(); + assert(static_cast<bool>(opt) == false); + } + { + optional<int> opt(3); + opt.reset(); + assert(static_cast<bool>(opt) == false); + } + { + optional<X> opt; + static_assert(noexcept(opt.reset()) == true, ""); + assert(X::dtor_called == false); + opt.reset(); + assert(X::dtor_called == false); + assert(static_cast<bool>(opt) == false); + } + assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 + { + optional<X> opt(X{}); + X::dtor_called = false; + opt.reset(); + assert(X::dtor_called == true); + assert(static_cast<bool>(opt) == false); + X::dtor_called = false; + } + assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp new file mode 100644 index 000000000000..9820d50f632e --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr explicit optional<T>::operator bool() const noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + { + const optional<int> opt; ((void)opt); + ASSERT_NOEXCEPT(bool(opt)); + static_assert(!std::is_convertible<optional<int>, bool>::value, ""); + } + { + constexpr optional<int> opt; + static_assert(!opt, ""); + } + { + constexpr optional<int> opt(0); + static_assert(opt, ""); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp new file mode 100644 index 000000000000..4087cfdf104e --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T& optional<T>::operator*() &; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return (*opt).test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*opt), X&); + // ASSERT_NOT_NOEXCEPT(*opt); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert((*opt).test() == 4); + } + static_assert(test() == 7, ""); +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*opt).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp new file mode 100644 index 000000000000..0779c9047c9e --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::operator*() const &; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + int test() const {return 2;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*opt), X const&); + // ASSERT_NOT_NOEXCEPT(*opt); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert((*opt).test() == 3, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert((*opt).test() == 2); + } +#ifdef _LIBCPP_DEBUG + { + const optional<X> opt; + assert((*opt).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp new file mode 100644 index 000000000000..78fd992952c9 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T&& optional<T>::operator*() const &&; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + int test() const && {return 2;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*std::move(opt)), X const &&); + // ASSERT_NOT_NOEXCEPT(*std::move(opt)); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert((*std::move(opt)).test() == 5, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert((*std::move(opt)).test() == 2); + } +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*std::move(opt)).test() == 5); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp new file mode 100644 index 000000000000..2924123234a8 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T&& optional<T>::operator*() &&; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() && {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return (*std::move(opt)).test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*std::move(opt)), X&&); + // ASSERT_NOT_NOEXCEPT(*std::move(opt)); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert((*std::move(opt)).test() == 6); + } + static_assert(test() == 7, ""); +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*std::move(opt)).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp new file mode 100644 index 000000000000..5df295d01e22 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr bool optional<T>::has_value() const noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + { + const optional<int> opt; ((void)opt); + ASSERT_NOEXCEPT(opt.has_value()); + ASSERT_SAME_TYPE(decltype(opt.has_value()), bool); + } + { + constexpr optional<int> opt; + static_assert(!opt.has_value(), ""); + } + { + constexpr optional<int> opt(0); + static_assert(opt.has_value(), ""); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp new file mode 100644 index 000000000000..2f1648c48c89 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T* optional<T>::operator->(); + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + int test() noexcept {return 3;} +}; + +struct Y +{ + constexpr int test() {return 3;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return opt->test(); +} + +int main() +{ + { + std::optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(opt.operator->()), X*); + // ASSERT_NOT_NOEXCEPT(opt.operator->()); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator->() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert(opt->test() == 3); + } + { + static_assert(test() == 3, ""); + } +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert(opt->test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp new file mode 100644 index 000000000000..887edc7114eb --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T* optional<T>::operator->() const; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const {return 3;} +}; + +struct Y +{ + int test() const noexcept {return 2;} +}; + +struct Z +{ + const Z* operator&() const; + constexpr int test() const {return 1;} +}; + +int main() +{ + { + const std::optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(opt.operator->()), X const*); + // ASSERT_NOT_NOEXCEPT(opt.operator->()); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator->() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert(opt->test() == 3, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert(opt->test() == 2); + } + { + constexpr optional<Z> opt(Z{}); + static_assert(opt->test() == 1, ""); + } +#ifdef _LIBCPP_DEBUG + { + const optional<X> opt; + assert(opt->test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp new file mode 100644 index 000000000000..516a79db5f64 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T& optional<T>::value() &; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() & {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return opt.value().test(); +} + + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(opt.value()); + ASSERT_SAME_TYPE(decltype(opt.value()), X&); + } + { + optional<X> opt; + opt.emplace(); + assert(opt.value().test() == 4); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + try + { + opt.value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif + static_assert(test() == 7, ""); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp new file mode 100644 index 000000000000..6076c509fa41 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::value() const &; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + constexpr int test() const {return 3;} + int test() {return 4;} +}; + +int main() +{ + { + constexpr optional<X> opt; + static_assert(opt.value().test() == 3, ""); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp new file mode 100644 index 000000000000..d4038e4efa6b --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::value() const &; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(opt.value()); + ASSERT_SAME_TYPE(decltype(opt.value()), X const&); + } + { + constexpr optional<X> opt(in_place); + static_assert(opt.value().test() == 3, ""); + } + { + const optional<X> opt(in_place); + assert(opt.value().test() == 3); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + const optional<X> opt; + try + { + opt.value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp new file mode 100644 index 000000000000..e189d3af6886 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::value() const &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(std::move(opt).value()); + ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X const&&); + } + { + constexpr optional<X> opt(in_place); + static_assert(std::move(opt).value().test() == 5, ""); + } + { + const optional<X> opt(in_place); + assert(std::move(opt).value().test() == 5); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + const optional<X> opt; + try + { + std::move(opt).value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp new file mode 100644 index 000000000000..c219e9704716 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> T optional<T>::value_or(U&& v) &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +struct Y +{ + int i_; + + Y(int i) : i_(i) {} +}; + +struct X +{ + int i_; + + X(int i) : i_(i) {} + X(X&& x) : i_(x.i_) {x.i_ = 0;} + X(const Y& y) : i_(y.i_) {} + X(Y&& y) : i_(y.i_+1) {} + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_;} +}; + +int main() +{ + { + optional<X> opt(in_place, 2); + Y y(3); + assert(std::move(opt).value_or(y) == 2); + assert(*opt == 0); + } + { + optional<X> opt(in_place, 2); + assert(std::move(opt).value_or(Y(3)) == 2); + assert(*opt == 0); + } + { + optional<X> opt; + Y y(3); + assert(std::move(opt).value_or(y) == 3); + assert(!opt); + } + { + optional<X> opt; + assert(std::move(opt).value_or(Y(3)) == 4); + assert(!opt); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp new file mode 100644 index 000000000000..36a85811ba49 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> constexpr T optional<T>::value_or(U&& v) const&; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct Y +{ + int i_; + + constexpr Y(int i) : i_(i) {} +}; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} + constexpr X(const Y& y) : i_(y.i_) {} + constexpr X(Y&& y) : i_(y.i_+1) {} + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_;} +}; + +int main() +{ + { + constexpr optional<X> opt(2); + constexpr Y y(3); + static_assert(opt.value_or(y) == 2, ""); + } + { + constexpr optional<X> opt(2); + static_assert(opt.value_or(Y(3)) == 2, ""); + } + { + constexpr optional<X> opt; + constexpr Y y(3); + static_assert(opt.value_or(y) == 3, ""); + } + { + constexpr optional<X> opt; + static_assert(opt.value_or(Y(3)) == 4, ""); + } + { + const optional<X> opt(2); + const Y y(3); + assert(opt.value_or(y) == 2); + } + { + const optional<X> opt(2); + assert(opt.value_or(Y(3)) == 2); + } + { + const optional<X> opt; + const Y y(3); + assert(opt.value_or(y) == 3); + } + { + const optional<X> opt; + assert(opt.value_or(Y(3)) == 4); + } +} diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp new file mode 100644 index 000000000000..2ef485b7fe50 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T& optional<T>::value() &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() && {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return std::move(opt).value().test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(std::move(opt).value()); + ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X&&); + } + { + optional<X> opt; + opt.emplace(); + assert(std::move(opt).value().test() == 6); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + try + { + std::move(opt).value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif + static_assert(test() == 7, ""); +} diff --git a/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp new file mode 100644 index 000000000000..26041259fa93 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp @@ -0,0 +1,306 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// void swap(optional&) +// noexcept(is_nothrow_move_constructible<T>::value && +// is_nothrow_swappable<T>::value) + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; +public: + static unsigned dtor_called; + X(int i) : i_(i) {} + X(X&& x) = default; + X& operator=(X&&) = default; + ~X() {++dtor_called;} + + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +unsigned X::dtor_called = 0; + +class Y +{ + int i_; +public: + static unsigned dtor_called; + Y(int i) : i_(i) {} + Y(Y&&) = default; + ~Y() {++dtor_called;} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} + friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} +}; + +unsigned Y::dtor_called = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {} + Z(Z&&) {TEST_THROW(7);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} + friend void swap(Z&, Z&) {TEST_THROW(6);} +}; + + +int main() +{ + { + optional<int> opt1; + optional<int> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<int> opt1; + optional<int> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(X::dtor_called == 0); + } + { + optional<X> opt1(1); + optional<X> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<X> opt1(1); + optional<X> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); // from inside std::swap + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(Y::dtor_called == 0); + } + { + optional<Y> opt1(1); + optional<Y> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Y> opt1(1); + optional<Y> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 0); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Z> opt1; + optional<Z> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Z> opt1; + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } +#endif +} diff --git a/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp b/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp new file mode 100644 index 000000000000..8a2c77af0ec1 --- /dev/null +++ b/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// T shall be an object type and shall satisfy the requirements of Destructible + +#include <optional> + +using std::optional; + +struct X +{ +private: + ~X() {} +}; + +int main() +{ + using std::optional; + { + // expected-error@optional:* 2 {{static_assert failed "instantiation of optional with a reference type is ill-formed}} + optional<int&> opt1; + optional<int&&> opt2; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed"}} + optional<X> opt3; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}} + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}} + optional<void()> opt4; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}} + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}} + // expected-error@optional:* 1+ {{cannot form a reference to 'void'}} + optional<const void> opt4; + } + // FIXME these are garbage diagnostics that Clang should not produce + // expected-error@optional:* 0+ {{is not a base class}} +} diff --git a/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp b/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp new file mode 100644 index 000000000000..fdd0f154f0e5 --- /dev/null +++ b/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + static_assert(std::is_default_constructible_v<O>, + "optional is always default constructible."); + static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>, + "optional<T> is copy constructible if and only if T is copy constructible."); + static_assert(std::is_move_constructible_v<O> == + (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>), + "optional<T> is move constructible if and only if T is copy or move constructible."); + static_assert(std::is_copy_assignable_v<O> == + (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>), + "optional<T> is copy assignable if and only if T is both copy " + "constructible and copy assignable."); + static_assert(std::is_move_assignable_v<O> == + ((std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>) || + (std::is_move_constructible_v<T> && std::is_move_assignable_v<T>)), + "optional<T> is move assignable if and only if T is both move assignable and " + "move constructible, or both copy constructible and copy assignable."); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +struct TrivialMoveNonTrivialCopy { + TrivialMoveNonTrivialCopy() = default; + TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} + TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; + TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } + TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; +}; + +struct TrivialCopyNonTrivialMove { + TrivialCopyNonTrivialMove() = default; + TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} + TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } +}; + +int main() +{ + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, + DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} + ); +} diff --git a/test/std/utilities/optional/optional.object/types.pass.cpp b/test/std/utilities/optional/optional.object/types.pass.cpp new file mode 100644 index 000000000000..0230a13dded1 --- /dev/null +++ b/test/std/utilities/optional/optional.object/types.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> +// class optional +// { +// public: +// typedef T value_type; +// ... + +#include <optional> +#include <type_traits> + +using std::optional; + +template <class Opt, class T> +void +test() +{ + static_assert(std::is_same<typename Opt::value_type, T>::value, ""); +} + +int main() +{ + test<optional<int>, int>(); + test<optional<const int>, const int>(); + test<optional<double>, double>(); + test<optional<const double>, const double>(); +} diff --git a/test/std/utilities/optional/optional.relops/equal.pass.cpp b/test/std/utilities/optional/optional.relops/equal.pass.cpp new file mode 100644 index 000000000000..6650b6720a8e --- /dev/null +++ b/test/std/utilities/optional/optional.relops/equal.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator == ( const X &lhs, const X &rhs ) + { return lhs.i_ == rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( o1 == o1 , "" ); + static_assert ( o1 == o2 , "" ); + static_assert ( !(o1 == o3), "" ); + static_assert ( !(o1 == o4), "" ); + static_assert ( !(o1 == o5), "" ); + + static_assert ( o2 == o1 , "" ); + static_assert ( o2 == o2 , "" ); + static_assert ( !(o2 == o3), "" ); + static_assert ( !(o2 == o4), "" ); + static_assert ( !(o2 == o5), "" ); + + static_assert ( !(o3 == o1), "" ); + static_assert ( !(o3 == o2), "" ); + static_assert ( o3 == o3 , "" ); + static_assert ( !(o3 == o4), "" ); + static_assert ( o3 == o5 , "" ); + + static_assert ( !(o4 == o1), "" ); + static_assert ( !(o4 == o2), "" ); + static_assert ( !(o4 == o3), "" ); + static_assert ( o4 == o4 , "" ); + static_assert ( !(o4 == o5), "" ); + + static_assert ( !(o5 == o1), "" ); + static_assert ( !(o5 == o2), "" ); + static_assert ( o5 == o3 , "" ); + static_assert ( !(o5 == o4), "" ); + static_assert ( o5 == o5 , "" ); + + } +} diff --git a/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp b/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp new file mode 100644 index 000000000000..f9b30449638a --- /dev/null +++ b/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>= (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator >= ( const X &lhs, const X &rhs ) + { return lhs.i_ >= rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( (o1 >= o1), "" ); + static_assert ( (o1 >= o2), "" ); + static_assert ( !(o1 >= o3), "" ); + static_assert ( !(o1 >= o4), "" ); + static_assert ( !(o1 >= o5), "" ); + + static_assert ( (o2 >= o1), "" ); + static_assert ( (o2 >= o2), "" ); + static_assert ( !(o2 >= o3), "" ); + static_assert ( !(o2 >= o4), "" ); + static_assert ( !(o2 >= o5), "" ); + + static_assert ( (o3 >= o1), "" ); + static_assert ( (o3 >= o2), "" ); + static_assert ( (o3 >= o3), "" ); + static_assert ( !(o3 >= o4), "" ); + static_assert ( (o3 >= o5), "" ); + + static_assert ( (o4 >= o1), "" ); + static_assert ( (o4 >= o2), "" ); + static_assert ( (o4 >= o3), "" ); + static_assert ( (o4 >= o4), "" ); + static_assert ( (o4 >= o5), "" ); + + static_assert ( (o5 >= o1), "" ); + static_assert ( (o5 >= o2), "" ); + static_assert ( (o5 >= o3), "" ); + static_assert ( !(o5 >= o4), "" ); + static_assert ( (o5 >= o5), "" ); + } +} diff --git a/test/std/utilities/optional/optional.relops/greater_than.pass.cpp b/test/std/utilities/optional/optional.relops/greater_than.pass.cpp new file mode 100644 index 000000000000..8a27eb471f28 --- /dev/null +++ b/test/std/utilities/optional/optional.relops/greater_than.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator> (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator > ( const X &lhs, const X &rhs ) + { return lhs.i_ > rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 > o1), "" ); + static_assert ( !(o1 > o2), "" ); + static_assert ( !(o1 > o3), "" ); + static_assert ( !(o1 > o4), "" ); + static_assert ( !(o1 > o5), "" ); + + static_assert ( !(o2 > o1), "" ); + static_assert ( !(o2 > o2), "" ); + static_assert ( !(o2 > o3), "" ); + static_assert ( !(o2 > o4), "" ); + static_assert ( !(o2 > o5), "" ); + + static_assert ( (o3 > o1), "" ); + static_assert ( (o3 > o2), "" ); + static_assert ( !(o3 > o3), "" ); + static_assert ( !(o3 > o4), "" ); + static_assert ( !(o3 > o5), "" ); + + static_assert ( (o4 > o1), "" ); + static_assert ( (o4 > o2), "" ); + static_assert ( (o4 > o3), "" ); + static_assert ( !(o4 > o4), "" ); + static_assert ( (o4 > o5), "" ); + + static_assert ( (o5 > o1), "" ); + static_assert ( (o5 > o2), "" ); + static_assert ( !(o5 > o3), "" ); + static_assert ( !(o5 > o4), "" ); + static_assert ( !(o5 > o5), "" ); + } +} diff --git a/test/std/utilities/optional/optional.relops/less_equal.pass.cpp b/test/std/utilities/optional/optional.relops/less_equal.pass.cpp new file mode 100644 index 000000000000..a7d594dd34a2 --- /dev/null +++ b/test/std/utilities/optional/optional.relops/less_equal.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<= (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator <= ( const X &lhs, const X &rhs ) + { return lhs.i_ <= rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( (o1 <= o1), "" ); + static_assert ( (o1 <= o2), "" ); + static_assert ( (o1 <= o3), "" ); + static_assert ( (o1 <= o4), "" ); + static_assert ( (o1 <= o5), "" ); + + static_assert ( (o2 <= o1), "" ); + static_assert ( (o2 <= o2), "" ); + static_assert ( (o2 <= o3), "" ); + static_assert ( (o2 <= o4), "" ); + static_assert ( (o2 <= o5), "" ); + + static_assert ( !(o3 <= o1), "" ); + static_assert ( !(o3 <= o2), "" ); + static_assert ( (o3 <= o3), "" ); + static_assert ( (o3 <= o4), "" ); + static_assert ( (o3 <= o5), "" ); + + static_assert ( !(o4 <= o1), "" ); + static_assert ( !(o4 <= o2), "" ); + static_assert ( !(o4 <= o3), "" ); + static_assert ( (o4 <= o4), "" ); + static_assert ( !(o4 <= o5), "" ); + + static_assert ( !(o5 <= o1), "" ); + static_assert ( !(o5 <= o2), "" ); + static_assert ( (o5 <= o3), "" ); + static_assert ( (o5 <= o4), "" ); + static_assert ( (o5 <= o5), "" ); + } +} diff --git a/test/std/utilities/optional/optional.relops/less_than.pass.cpp b/test/std/utilities/optional/optional.relops/less_than.pass.cpp new file mode 100644 index 000000000000..deffa5e849f9 --- /dev/null +++ b/test/std/utilities/optional/optional.relops/less_than.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator< (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator < ( const X &lhs, const X &rhs ) + { return lhs.i_ < rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 < o1), "" ); + static_assert ( !(o1 < o2), "" ); + static_assert ( (o1 < o3), "" ); + static_assert ( (o1 < o4), "" ); + static_assert ( (o1 < o5), "" ); + + static_assert ( !(o2 < o1), "" ); + static_assert ( !(o2 < o2), "" ); + static_assert ( (o2 < o3), "" ); + static_assert ( (o2 < o4), "" ); + static_assert ( (o2 < o5), "" ); + + static_assert ( !(o3 < o1), "" ); + static_assert ( !(o3 < o2), "" ); + static_assert ( !(o3 < o3), "" ); + static_assert ( (o3 < o4), "" ); + static_assert ( !(o3 < o5), "" ); + + static_assert ( !(o4 < o1), "" ); + static_assert ( !(o4 < o2), "" ); + static_assert ( !(o4 < o3), "" ); + static_assert ( !(o4 < o4), "" ); + static_assert ( !(o4 < o5), "" ); + + static_assert ( !(o5 < o1), "" ); + static_assert ( !(o5 < o2), "" ); + static_assert ( !(o5 < o3), "" ); + static_assert ( (o5 < o4), "" ); + static_assert ( !(o5 < o5), "" ); + } +} diff --git a/test/std/utilities/optional/optional.relops/not_equal.pass.cpp b/test/std/utilities/optional/optional.relops/not_equal.pass.cpp new file mode 100644 index 000000000000..fd11b2a207ca --- /dev/null +++ b/test/std/utilities/optional/optional.relops/not_equal.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator != ( const X &lhs, const X &rhs ) + { return lhs.i_ != rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 != o1), "" ); + static_assert ( !(o1 != o2), "" ); + static_assert ( (o1 != o3), "" ); + static_assert ( (o1 != o4), "" ); + static_assert ( (o1 != o5), "" ); + + static_assert ( !(o2 != o1), "" ); + static_assert ( !(o2 != o2), "" ); + static_assert ( (o2 != o3), "" ); + static_assert ( (o2 != o4), "" ); + static_assert ( (o2 != o5), "" ); + + static_assert ( (o3 != o1), "" ); + static_assert ( (o3 != o2), "" ); + static_assert ( !(o3 != o3), "" ); + static_assert ( (o3 != o4), "" ); + static_assert ( !(o3 != o5), "" ); + + static_assert ( (o4 != o1), "" ); + static_assert ( (o4 != o2), "" ); + static_assert ( (o4 != o3), "" ); + static_assert ( !(o4 != o4), "" ); + static_assert ( (o4 != o5), "" ); + + static_assert ( (o5 != o1), "" ); + static_assert ( (o5 != o2), "" ); + static_assert ( !(o5 != o3), "" ); + static_assert ( (o5 != o4), "" ); + static_assert ( !(o5 != o5), "" ); + + } +} diff --git a/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp b/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp new file mode 100644 index 000000000000..3fbf19f8ee1b --- /dev/null +++ b/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> +// constexpr optional<decay_t<T>> make_optional(T&& v); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + using std::make_optional; + { + int arr[10]; ((void)arr); + ASSERT_SAME_TYPE(decltype(make_optional(arr)), optional<int*>); + } + { + constexpr auto opt = make_optional(2); + ASSERT_SAME_TYPE(decltype(opt), const optional<int>); + static_assert(opt.value() == 2); + } + { + optional<int> opt = make_optional(2); + assert(*opt == 2); + } + { + std::string s("123"); + optional<std::string> opt = make_optional(s); + assert(*opt == s); + } + { + std::unique_ptr<int> s(new int(3)); + optional<std::unique_ptr<int>> opt = make_optional(std::move(s)); + assert(**opt == 3); + assert(s == nullptr); + } +} diff --git a/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp b/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp new file mode 100644 index 000000000000..bdfeefbcc1d8 --- /dev/null +++ b/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T, class... Args> +// constexpr optional<T> make_optional(Args&&... args); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +int main() +{ + using std::optional; + using std::make_optional; + + { + constexpr auto opt = make_optional<int>('a'); + static_assert(*opt == int('a'), ""); + } + { + std::string s("123"); + auto opt = make_optional<std::string>(s); + assert(*opt == s); + } + { + std::unique_ptr<int> s(new int(3)); + auto opt = make_optional<std::unique_ptr<int>>(std::move(s)); + assert(**opt == 3); + assert(s == nullptr); + } + { + auto opt = make_optional<std::string>(4, 'X'); + assert(*opt == "XXXX"); + } +} diff --git a/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp b/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp new file mode 100644 index 000000000000..e6ed0129ddc7 --- /dev/null +++ b/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T, class U, class... Args> +// constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +struct TestT { + int x; + int size; + constexpr TestT(std::initializer_list<int> il) : x(*il.begin()), size(static_cast<int>(il.size())) {} + constexpr TestT(std::initializer_list<int> il, const int*) + : x(*il.begin()), size(static_cast<int>(il.size())) {} +}; + +int main() +{ + using std::make_optional; + { + constexpr auto opt = make_optional<TestT>({42, 2, 3}); + ASSERT_SAME_TYPE(decltype(opt), const std::optional<TestT>); + static_assert(opt->x == 42, ""); + static_assert(opt->size == 3, ""); + } + { + constexpr auto opt = make_optional<TestT>({42, 2, 3}, nullptr); + static_assert(opt->x == 42, ""); + static_assert(opt->size == 3, ""); + } + { + auto opt = make_optional<std::string>({'1', '2', '3'}); + assert(*opt == "123"); + } + { + auto opt = make_optional<std::string>({'a', 'b', 'c'}, std::allocator<char>{}); + assert(*opt == "abc"); + } +} diff --git a/test/std/utilities/optional/optional.specalg/swap.pass.cpp b/test/std/utilities/optional/optional.specalg/swap.pass.cpp new file mode 100644 index 000000000000..31779243e32a --- /dev/null +++ b/test/std/utilities/optional/optional.specalg/swap.pass.cpp @@ -0,0 +1,352 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> void swap(optional<T>& x, optional<T>& y) +// noexcept(noexcept(x.swap(y))); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; +public: + static unsigned dtor_called; + X(int i) : i_(i) {} + X(X&& x) = default; + X& operator=(X&&) = default; + ~X() {++dtor_called;} + + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +unsigned X::dtor_called = 0; + +class Y +{ + int i_; +public: + static unsigned dtor_called; + Y(int i) : i_(i) {} + Y(Y&&) = default; + ~Y() {++dtor_called;} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} + friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} +}; + +unsigned Y::dtor_called = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {} + Z(Z&&) { TEST_THROW(7);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} + friend void swap(Z&, Z&) { TEST_THROW(6);} +}; + + +struct NonSwappable { + NonSwappable(NonSwappable const&) = delete; +}; +void swap(NonSwappable&, NonSwappable&) = delete; + +void test_swap_sfinae() { + using std::optional; + { + using T = TestTypes::TestType; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::MoveOnly; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::Copyable; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::NoCtors; + static_assert(!std::is_swappable_v<optional<T>>, ""); + } + { + using T = NonSwappable; + static_assert(!std::is_swappable_v<optional<T>>, ""); + } + { + // Even thought CopyOnly has deleted move operations, those operations + // cause optional<CopyOnly> to have implicitly deleted move operations + // that decay into copies. + using T = TestTypes::CopyOnly; + using Opt = optional<T>; + T::reset(); + Opt L(101), R(42); + T::reset_constructors(); + std::swap(L, R); + assert(L->value == 42); + assert(R->value == 101); + assert(T::copy_constructed == 1); + assert(T::constructed == T::copy_constructed); + assert(T::assigned == 2); + assert(T::assigned == T::copy_assigned); + } +} + +int main() +{ + test_swap_sfinae(); + { + optional<int> opt1; + optional<int> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<int> opt1; + optional<int> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(X::dtor_called == 0); + } + { + optional<X> opt1(1); + optional<X> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<X> opt1(1); + optional<X> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); // from inside std::swap + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(Y::dtor_called == 0); + } + { + optional<Y> opt1(1); + optional<Y> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Y> opt1(1); + optional<Y> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 0); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Z> opt1; + optional<Z> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Z> opt1; + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } +#endif // TEST_HAS_NO_EXCEPTIONS +} diff --git a/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp b/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp new file mode 100644 index 000000000000..20c90c7e34fd --- /dev/null +++ b/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// A program that necessitates the instantiation of template optional for +// (possibly cv-qualified) in_place_t is ill-formed. + +#include <optional> + +int main() +{ + using std::optional; + using std::in_place_t; + using std::in_place; + + optional<in_place_t> opt; // expected-note {{requested here}} + // expected-error@optional:* {{"instantiation of optional with in_place_t is ill-formed"}} +} diff --git a/test/std/utilities/utility/forward/forward1.fail.cpp b/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp index 43884d54bf86..687625e8b673 100644 --- a/test/std/utilities/utility/forward/forward1.fail.cpp +++ b/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp @@ -7,18 +7,16 @@ // //===----------------------------------------------------------------------===// -// test forward +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> -#include <utility> +// #include <initializer_list> -struct A -{ -}; - -A source() {return A();} -const A csource() {return A();} +#include <optional> int main() { - std::forward<A&>(source()); // error + using std::optional; + + std::initializer_list<int> list; } diff --git a/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp b/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp new file mode 100644 index 000000000000..56a30ccb0db9 --- /dev/null +++ b/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// A program that necessitates the instantiation of template optional for +// (possibly cv-qualified) nullopt_t is ill-formed. + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + optional<nullopt_t> opt; // expected-note 1 {{requested here}} + optional<const nullopt_t> opt1; // expected-note 1 {{requested here}} + optional<nullopt_t &> opt2; // expected-note 1 {{requested here}} + optional<nullopt_t &&> opt3; // expected-note 1 {{requested here}} + // expected-error@optional:* 4 {{instantiation of optional with nullopt_t is ill-formed}} +} diff --git a/test/std/utilities/template.bitset/bitset.cons/ull_ctor.pass.cpp b/test/std/utilities/template.bitset/bitset.cons/ull_ctor.pass.cpp index 1b121c5fb928..3ba88ee2db53 100644 --- a/test/std/utilities/template.bitset/bitset.cons/ull_ctor.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.cons/ull_ctor.pass.cpp @@ -12,6 +12,7 @@ #include <bitset> #include <cassert> #include <algorithm> // for 'min' and 'max' +#include <cstddef> #include "test_macros.h" @@ -21,9 +22,9 @@ void test_val_ctor() { TEST_CONSTEXPR std::bitset<N> v(0xAAAAAAAAAAAAAAAAULL); assert(v.size() == N); - unsigned M = std::min<std::size_t>(N, 64); + std::size_t M = std::min<std::size_t>(N, 64); for (std::size_t i = 0; i < M; ++i) - assert(v[i] == (i & 1)); + assert(v[i] == ((i & 1) != 0)); for (std::size_t i = M; i < N; ++i) assert(v[i] == false); } diff --git a/test/std/utilities/template.bitset/bitset.members/flip_one.pass.cpp b/test/std/utilities/template.bitset/bitset.members/flip_one.pass.cpp index 88ce8e943caf..18a64a214a45 100644 --- a/test/std/utilities/template.bitset/bitset.members/flip_one.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.members/flip_one.pass.cpp @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // test bitset<N>& flip(size_t pos); #include <bitset> #include <cstdlib> #include <cassert> +#include "test_macros.h" + template <std::size_t N> std::bitset<N> make_bitset() @@ -25,11 +26,15 @@ make_bitset() } template <std::size_t N> -void test_flip_one() +void test_flip_one(bool test_throws) { std::bitset<N> v = make_bitset<N>(); +#ifdef TEST_HAS_NO_EXCEPTIONS + if (test_throws) return; +#else try { +#endif v.flip(50); bool b = v[50]; if (50 >= v.size()) @@ -39,21 +44,25 @@ void test_flip_one() assert(v[50] != b); v.flip(50); assert(v[50] == b); + assert(!test_throws); +#ifndef TEST_HAS_NO_EXCEPTIONS } catch (std::out_of_range&) { + assert(test_throws); } +#endif } int main() { - test_flip_one<0>(); - test_flip_one<1>(); - test_flip_one<31>(); - test_flip_one<32>(); - test_flip_one<33>(); - test_flip_one<63>(); - test_flip_one<64>(); - test_flip_one<65>(); - test_flip_one<1000>(); + test_flip_one<0>(true); + test_flip_one<1>(true); + test_flip_one<31>(true); + test_flip_one<32>(true); + test_flip_one<33>(true); + test_flip_one<63>(false); + test_flip_one<64>(false); + test_flip_one<65>(false); + test_flip_one<1000>(false); } diff --git a/test/std/utilities/template.bitset/bitset.members/reset_one.pass.cpp b/test/std/utilities/template.bitset/bitset.members/reset_one.pass.cpp index f01d35b9a33c..6847694e4b73 100644 --- a/test/std/utilities/template.bitset/bitset.members/reset_one.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.members/reset_one.pass.cpp @@ -7,18 +7,23 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // test bitset<N>& reset(size_t pos); #include <bitset> #include <cassert> +#include "test_macros.h" + template <std::size_t N> -void test_reset_one() +void test_reset_one(bool test_throws) { std::bitset<N> v; +#ifdef TEST_HAS_NO_EXCEPTIONS + if (test_throws) return; +#else try { +#endif v.set(); v.reset(50); if (50 >= v.size()) @@ -28,21 +33,25 @@ void test_reset_one() assert(!v[i]); else assert(v[i]); + assert(!test_throws); +#ifndef TEST_HAS_NO_EXCEPTIONS } catch (std::out_of_range&) { + assert(test_throws); } +#endif } int main() { - test_reset_one<0>(); - test_reset_one<1>(); - test_reset_one<31>(); - test_reset_one<32>(); - test_reset_one<33>(); - test_reset_one<63>(); - test_reset_one<64>(); - test_reset_one<65>(); - test_reset_one<1000>(); + test_reset_one<0>(true); + test_reset_one<1>(true); + test_reset_one<31>(true); + test_reset_one<32>(true); + test_reset_one<33>(true); + test_reset_one<63>(false); + test_reset_one<64>(false); + test_reset_one<65>(false); + test_reset_one<1000>(false); } diff --git a/test/std/utilities/template.bitset/bitset.members/set_one.pass.cpp b/test/std/utilities/template.bitset/bitset.members/set_one.pass.cpp index debe5431d8d0..1c8d6a1c32a4 100644 --- a/test/std/utilities/template.bitset/bitset.members/set_one.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.members/set_one.pass.cpp @@ -7,47 +7,60 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // test bitset<N>& set(size_t pos, bool val = true); #include <bitset> #include <cassert> +#include "test_macros.h" + template <std::size_t N> -void test_set_one() +void test_set_one(bool test_throws) { std::bitset<N> v; +#ifdef TEST_HAS_NO_EXCEPTIONS + if (test_throws) return; +#else try +#endif { v.set(50); if (50 >= v.size()) assert(false); assert(v[50]); + assert(!test_throws); } +#ifndef TEST_HAS_NO_EXCEPTIONS catch (std::out_of_range&) { + assert(test_throws); } try +#endif { v.set(50, false); if (50 >= v.size()) assert(false); assert(!v[50]); + assert(!test_throws); } +#ifndef TEST_HAS_NO_EXCEPTIONS catch (std::out_of_range&) { + assert(test_throws); } +#endif } int main() { - test_set_one<0>(); - test_set_one<1>(); - test_set_one<31>(); - test_set_one<32>(); - test_set_one<33>(); - test_set_one<63>(); - test_set_one<64>(); - test_set_one<65>(); - test_set_one<1000>(); + test_set_one<0>(true); + test_set_one<1>(true); + test_set_one<31>(true); + test_set_one<32>(true); + test_set_one<33>(true); + test_set_one<63>(false); + test_set_one<64>(false); + test_set_one<65>(false); + test_set_one<1000>(false); } diff --git a/test/std/utilities/template.bitset/bitset.members/test.pass.cpp b/test/std/utilities/template.bitset/bitset.members/test.pass.cpp index 161afd11c291..1a2d70613e1f 100644 --- a/test/std/utilities/template.bitset/bitset.members/test.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.members/test.pass.cpp @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // test constexpr bool test(size_t pos) const; #include <bitset> #include <cstdlib> #include <cassert> +#include "test_macros.h" + template <std::size_t N> std::bitset<N> make_bitset() @@ -25,30 +26,38 @@ make_bitset() } template <std::size_t N> -void test_test() +void test_test(bool test_throws) { const std::bitset<N> v1 = make_bitset<N>(); +#ifdef TEST_HAS_NO_EXCEPTIONS + if (test_throws) return; +#else try { +#endif bool b = v1.test(50); if (50 >= v1.size()) assert(false); assert(b == v1[50]); + assert(!test_throws); +#ifndef TEST_HAS_NO_EXCEPTIONS } catch (std::out_of_range&) { + assert(test_throws); } +#endif } int main() { - test_test<0>(); - test_test<1>(); - test_test<31>(); - test_test<32>(); - test_test<33>(); - test_test<63>(); - test_test<64>(); - test_test<65>(); - test_test<1000>(); + test_test<0>(true); + test_test<1>(true); + test_test<31>(true); + test_test<32>(true); + test_test<33>(true); + test_test<63>(false); + test_test<64>(false); + test_test<65>(false); + test_test<1000>(false); } diff --git a/test/std/utilities/template.bitset/bitset.operators/op_and.pass.cpp b/test/std/utilities/template.bitset/bitset.operators/op_and.pass.cpp index 80792d919ccf..d86a10c6df13 100644 --- a/test/std/utilities/template.bitset/bitset.operators/op_and.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.operators/op_and.pass.cpp @@ -33,7 +33,7 @@ void test_op_and() std::bitset<N> v1 = make_bitset<N>(); std::bitset<N> v2 = make_bitset<N>(); std::bitset<N> v3 = v1; - assert((v1 & v2) == (v3 &= v2));; + assert((v1 & v2) == (v3 &= v2)); } int main() diff --git a/test/std/utilities/template.bitset/bitset.operators/op_not.pass.cpp b/test/std/utilities/template.bitset/bitset.operators/op_not.pass.cpp index 65a7004acb86..0a8024d5eb9b 100644 --- a/test/std/utilities/template.bitset/bitset.operators/op_not.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.operators/op_not.pass.cpp @@ -33,7 +33,7 @@ void test_op_not() std::bitset<N> v1 = make_bitset<N>(); std::bitset<N> v2 = make_bitset<N>(); std::bitset<N> v3 = v1; - assert((v1 ^ v2) == (v3 ^= v2));; + assert((v1 ^ v2) == (v3 ^= v2)); } int main() diff --git a/test/std/utilities/template.bitset/bitset.operators/op_or.pass.cpp b/test/std/utilities/template.bitset/bitset.operators/op_or.pass.cpp index dcabaa4a9a4d..449115edd757 100644 --- a/test/std/utilities/template.bitset/bitset.operators/op_or.pass.cpp +++ b/test/std/utilities/template.bitset/bitset.operators/op_or.pass.cpp @@ -33,7 +33,7 @@ void test_op_or() std::bitset<N> v1 = make_bitset<N>(); std::bitset<N> v2 = make_bitset<N>(); std::bitset<N> v3 = v1; - assert((v1 | v2) == (v3 |= v2));; + assert((v1 | v2) == (v3 |= v2)); } int main() diff --git a/test/std/utilities/time/rep.h b/test/std/utilities/time/rep.h index 2ec3514ab567..1c76582d3725 100644 --- a/test/std/utilities/time/rep.h +++ b/test/std/utilities/time/rep.h @@ -10,15 +10,17 @@ #ifndef REP_H #define REP_H +#include "test_macros.h" + class Rep { int data_; public: - _LIBCPP_CONSTEXPR Rep() : data_(-1) {} - explicit _LIBCPP_CONSTEXPR Rep(int i) : data_(i) {} + TEST_CONSTEXPR Rep() : data_(-1) {} + explicit TEST_CONSTEXPR Rep(int i) : data_(i) {} - bool _LIBCPP_CONSTEXPR operator==(int i) const {return data_ == i;} - bool _LIBCPP_CONSTEXPR operator==(const Rep& r) const {return data_ == r.data_;} + bool TEST_CONSTEXPR operator==(int i) const {return data_ == i;} + bool TEST_CONSTEXPR operator==(const Rep& r) const {return data_ == r.data_;} Rep& operator*=(Rep x) {data_ *= x.data_; return *this;} Rep& operator/=(Rep x) {data_ /= x.data_; return *this;} diff --git a/test/std/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp b/test/std/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp index 7d7e82ac5e23..ae5423ef1161 100644 --- a/test/std/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.cast/time_point_cast.pass.cpp @@ -19,6 +19,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + template <class FromDuration, class ToDuration> void test(const FromDuration& df, const ToDuration& d) @@ -35,7 +37,7 @@ test(const FromDuration& df, const ToDuration& d) } } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 template<class FromDuration, long long From, class ToDuration, long long To> void test_constexpr () @@ -65,7 +67,7 @@ int main() std::chrono::duration<double, std::ratio<3600> >(7265./3600)); test(std::chrono::duration<int, std::ratio<2, 3> >(9), std::chrono::duration<int, std::ratio<3, 5> >(10)); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { test_constexpr<std::chrono::milliseconds, 7265000, std::chrono::hours, 2> (); test_constexpr<std::chrono::milliseconds, 7265000, std::chrono::minutes,121> (); diff --git a/test/std/utilities/time/time.point/time.point.comparisons/op_equal.pass.cpp b/test/std/utilities/time/time.point/time.point.comparisons/op_equal.pass.cpp index a37bb266a0a9..a6f7cc0b89b2 100644 --- a/test/std/utilities/time/time.point/time.point.comparisons/op_equal.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.comparisons/op_equal.pass.cpp @@ -22,6 +22,8 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + int main() { typedef std::chrono::system_clock Clock; @@ -55,7 +57,7 @@ int main() assert( (t1 != t2)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr T1 t1(Duration1(3)); constexpr T1 t2(Duration1(3)); diff --git a/test/std/utilities/time/time.point/time.point.comparisons/op_less.pass.cpp b/test/std/utilities/time/time.point/time.point.comparisons/op_less.pass.cpp index 9d94400ed3d1..d7adf29f2ef8 100644 --- a/test/std/utilities/time/time.point/time.point.comparisons/op_less.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.comparisons/op_less.pass.cpp @@ -30,6 +30,8 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + int main() { typedef std::chrono::system_clock Clock; @@ -71,7 +73,7 @@ int main() assert(!(t1 >= t2)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr T1 t1(Duration1(3)); constexpr T1 t2(Duration1(3)); diff --git a/test/std/utilities/time/time.point/time.point.cons/convert.pass.cpp b/test/std/utilities/time/time.point/time.point.cons/convert.pass.cpp index 6cd7dcb7d2f4..33e349fe8941 100644 --- a/test/std/utilities/time/time.point/time.point.cons/convert.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.cons/convert.pass.cpp @@ -17,6 +17,8 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + int main() { typedef std::chrono::system_clock Clock; @@ -27,7 +29,7 @@ int main() std::chrono::time_point<Clock, Duration1> t1 = t2; assert(t1.time_since_epoch() == Duration1(3000)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::chrono::time_point<Clock, Duration2> t2(Duration2(3)); constexpr std::chrono::time_point<Clock, Duration1> t1 = t2; diff --git a/test/std/utilities/time/time.point/time.point.cons/default.pass.cpp b/test/std/utilities/time/time.point/time.point.cons/default.pass.cpp index 01f0bc169933..120fd3fb4e9f 100644 --- a/test/std/utilities/time/time.point/time.point.cons/default.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.cons/default.pass.cpp @@ -16,6 +16,7 @@ #include <chrono> #include <cassert> +#include "test_macros.h" #include "../../rep.h" int main() @@ -26,7 +27,7 @@ int main() std::chrono::time_point<Clock, Duration> t; assert(t.time_since_epoch() == Duration::zero()); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::chrono::time_point<Clock, Duration> t; static_assert(t.time_since_epoch() == Duration::zero(), ""); diff --git a/test/std/utilities/time/time.point/time.point.cons/duration.pass.cpp b/test/std/utilities/time/time.point/time.point.cons/duration.pass.cpp index 9d53d86dea3b..1b96902aba3b 100644 --- a/test/std/utilities/time/time.point/time.point.cons/duration.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.cons/duration.pass.cpp @@ -16,6 +16,8 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + int main() { typedef std::chrono::system_clock Clock; @@ -28,7 +30,7 @@ int main() std::chrono::time_point<Clock, Duration> t(std::chrono::seconds(3)); assert(t.time_since_epoch() == Duration(3000)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::chrono::time_point<Clock, Duration> t(Duration(3)); static_assert(t.time_since_epoch() == Duration(3), ""); diff --git a/test/std/utilities/time/time.point/time.point.nonmember/op_+.pass.cpp b/test/std/utilities/time/time.point/time.point.nonmember/op_+.pass.cpp index 7a8fa6dcf14f..19f5cbcd9f41 100644 --- a/test/std/utilities/time/time.point/time.point.nonmember/op_+.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.nonmember/op_+.pass.cpp @@ -22,6 +22,8 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + int main() { typedef std::chrono::system_clock Clock; @@ -34,7 +36,7 @@ int main() t2 = Duration2(6) + t1; assert(t2.time_since_epoch() == Duration2(3006)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::chrono::time_point<Clock, Duration1> t1(Duration1(3)); constexpr std::chrono::time_point<Clock, Duration2> t2 = t1 + Duration2(5); diff --git a/test/std/utilities/time/time.point/time.point.nonmember/op_-duration.pass.cpp b/test/std/utilities/time/time.point/time.point.nonmember/op_-duration.pass.cpp index 342d27b5aebd..978f09d66bb2 100644 --- a/test/std/utilities/time/time.point/time.point.nonmember/op_-duration.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.nonmember/op_-duration.pass.cpp @@ -18,6 +18,19 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + +template <class D> +void test2739() // LWG2739 +{ + typedef std::chrono::time_point<std::chrono::system_clock> TimePoint; + typedef std::chrono::duration<D> Dur; + const Dur d(5); + TimePoint t0 = std::chrono::system_clock::from_time_t(200); + TimePoint t1 = t0 - d; + assert(t1 < t0); +} + int main() { typedef std::chrono::system_clock Clock; @@ -28,11 +41,13 @@ int main() std::chrono::time_point<Clock, Duration2> t2 = t1 - Duration2(5); assert(t2.time_since_epoch() == Duration2(2995)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::chrono::time_point<Clock, Duration1> t1(Duration1(3)); constexpr std::chrono::time_point<Clock, Duration2> t2 = t1 - Duration2(5); static_assert(t2.time_since_epoch() == Duration2(2995), ""); } #endif + test2739<int32_t>(); + test2739<uint32_t>(); } diff --git a/test/std/utilities/time/time.point/time.point.nonmember/op_-time_point.pass.cpp b/test/std/utilities/time/time.point/time.point.nonmember/op_-time_point.pass.cpp index 5267f07e1b86..fcef3f249733 100644 --- a/test/std/utilities/time/time.point/time.point.nonmember/op_-time_point.pass.cpp +++ b/test/std/utilities/time/time.point/time.point.nonmember/op_-time_point.pass.cpp @@ -18,6 +18,8 @@ #include <chrono> #include <cassert> +#include "test_macros.h" + int main() { typedef std::chrono::system_clock Clock; @@ -28,7 +30,7 @@ int main() std::chrono::time_point<Clock, Duration2> t2(Duration2(5)); assert((t1 - t2) == Duration2(2995)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::chrono::time_point<Clock, Duration1> t1(Duration1(3)); constexpr std::chrono::time_point<Clock, Duration2> t2(Duration2(5)); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.apply/apply.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.apply/apply.pass.cpp index 2e821945d09a..4c15499f5c1d 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.apply/apply.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.apply/apply.pass.cpp @@ -166,7 +166,6 @@ void check_apply_quals_and_types(Tuple&& t) { void test_call_quals_and_arg_types() { - TrackedCallable obj; using Tup = std::tuple<int, int const&, unsigned&&>; const int x = 42; unsigned y = 101; @@ -199,7 +198,7 @@ void test_noexcept() // test that the functions noexcept-ness is propagated using Tup = std::tuple<int, const char*, long>; Tup t; - ASSERT_NOEXCEPT(std::apply(nec, t)); + LIBCPP_ASSERT_NOEXCEPT(std::apply(nec, t)); ASSERT_NOT_NOEXCEPT(std::apply(tc, t)); } { @@ -207,7 +206,7 @@ void test_noexcept() using Tup = std::tuple<NothrowMoveable, int>; Tup t; ASSERT_NOT_NOEXCEPT(std::apply(nec, t)); - ASSERT_NOEXCEPT(std::apply(nec, std::move(t))); + LIBCPP_ASSERT_NOEXCEPT(std::apply(nec, std::move(t))); } } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index 143ae195e6f4..eee1dd88253c 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -175,14 +175,14 @@ void test_noexcept() { Tuple tup; ((void)tup); Tuple const& ctup = tup; ((void)ctup); ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup)); - ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup))); + LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup))); } { using Tuple = std::pair<int, NothrowMoveable>; Tuple tup; ((void)tup); Tuple const& ctup = tup; ((void)ctup); ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup)); - ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup))); + LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup))); } { using Tuple = std::tuple<int, int, int>; @@ -192,7 +192,7 @@ void test_noexcept() { { using Tuple = std::tuple<long, long, long>; Tuple tup; ((void)tup); - ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup)); + LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup)); } { using Tuple = std::array<int, 3>; @@ -202,7 +202,7 @@ void test_noexcept() { { using Tuple = std::array<long, 3>; Tuple tup; ((void)tup); - ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup)); + LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup)); } } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp index a3d14487b47d..a66fba22d919 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp @@ -23,9 +23,9 @@ int main() { { - typedef std::pair<double, char> T0; - typedef std::tuple<int, short> T1; - T0 t0(2.5, 'a'); + typedef std::pair<long, char> T0; + typedef std::tuple<long long, short> T1; + T0 t0(2, 'a'); T1 t1; t1 = t0; assert(std::get<0>(t1) == 2); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp index 91892efaf139..85dcee893a07 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp @@ -36,26 +36,26 @@ struct D int main() { { - typedef std::tuple<double> T0; - typedef std::tuple<int> T1; - T0 t0(2.5); + typedef std::tuple<long> T0; + typedef std::tuple<long long> T1; + T0 t0(2); T1 t1; t1 = t0; assert(std::get<0>(t1) == 2); } { - typedef std::tuple<double, char> T0; - typedef std::tuple<int, int> T1; - T0 t0(2.5, 'a'); + typedef std::tuple<long, char> T0; + typedef std::tuple<long long, int> T1; + T0 t0(2, 'a'); T1 t1; t1 = t0; assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); } { - typedef std::tuple<double, char, D> T0; - typedef std::tuple<int, int, B> T1; - T0 t0(2.5, 'a', D(3)); + typedef std::tuple<long, char, D> T0; + typedef std::tuple<long long, int, B> T1; + T0 t0(2, 'a', D(3)); T1 t1; t1 = t0; assert(std::get<0>(t1) == 2); @@ -65,10 +65,10 @@ int main() { D d(3); D d2(2); - typedef std::tuple<double, char, D&> T0; - typedef std::tuple<int, int, B&> T1; - T0 t0(2.5, 'a', d2); - T1 t1(1.5, 'b', d); + typedef std::tuple<long, char, D&> T0; + typedef std::tuple<long long, int, B&> T1; + T0 t0(2, 'a', d2); + T1 t1(1, 'b', d); t1 = t0; assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp index afd3e0fdb8e3..1a32acd55cff 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp @@ -39,7 +39,7 @@ struct D struct E { E() = default; - E& operator=(int val) { + E& operator=(int) { return *this; } }; @@ -47,26 +47,26 @@ struct E { int main() { { - typedef std::tuple<double> T0; - typedef std::tuple<int> T1; - T0 t0(2.5); + typedef std::tuple<long> T0; + typedef std::tuple<long long> T1; + T0 t0(2); T1 t1; t1 = std::move(t0); assert(std::get<0>(t1) == 2); } { - typedef std::tuple<double, char> T0; - typedef std::tuple<int, int> T1; - T0 t0(2.5, 'a'); + typedef std::tuple<long, char> T0; + typedef std::tuple<long long, int> T1; + T0 t0(2, 'a'); T1 t1; t1 = std::move(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); } { - typedef std::tuple<double, char, D> T0; - typedef std::tuple<int, int, B> T1; - T0 t0(2.5, 'a', D(3)); + typedef std::tuple<long, char, D> T0; + typedef std::tuple<long long, int, B> T1; + T0 t0(2, 'a', D(3)); T1 t1; t1 = std::move(t0); assert(std::get<0>(t1) == 2); @@ -76,19 +76,19 @@ int main() { D d(3); D d2(2); - typedef std::tuple<double, char, D&> T0; - typedef std::tuple<int, int, B&> T1; - T0 t0(2.5, 'a', d2); - T1 t1(1.5, 'b', d); + typedef std::tuple<long, char, D&> T0; + typedef std::tuple<long long, int, B&> T1; + T0 t0(2, 'a', d2); + T1 t1(1, 'b', d); t1 = std::move(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); assert(std::get<2>(t1).id_ == 2); } { - typedef std::tuple<double, char, std::unique_ptr<D>> T0; - typedef std::tuple<int, int, std::unique_ptr<B>> T1; - T0 t0(2.5, 'a', std::unique_ptr<D>(new D(3))); + typedef std::tuple<long, char, std::unique_ptr<D>> T0; + typedef std::tuple<long long, int, std::unique_ptr<B>> T1; + T0 t0(2, 'a', std::unique_ptr<D>(new D(3))); T1 t1; t1 = std::move(t0); assert(std::get<0>(t1) == 2); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp index d5d020779726..edb235a41919 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp @@ -16,9 +16,26 @@ // UNSUPPORTED: c++98, c++03 #include <tuple> +#include <memory> #include <string> #include <cassert> +#include "test_macros.h" + +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; +}; +struct CopyAssignable { + CopyAssignable& operator=(CopyAssignable const&) = default; + CopyAssignable& operator=(CopyAssignable &&) = delete; +}; +static_assert(std::is_copy_assignable<CopyAssignable>::value, ""); +struct MoveAssignable { + MoveAssignable& operator=(MoveAssignable const&) = delete; + MoveAssignable& operator=(MoveAssignable&&) = default; +}; + int main() { { @@ -51,4 +68,37 @@ int main() assert(std::get<1>(t) == 'a'); assert(std::get<2>(t) == "some text"); } + { + // test reference assignment. + using T = std::tuple<int&, int&&>; + int x = 42; + int y = 100; + int x2 = -1; + int y2 = 500; + T t(x, std::move(y)); + T t2(x2, std::move(y2)); + t = t2; + assert(std::get<0>(t) == x2); + assert(&std::get<0>(t) == &x); + assert(std::get<1>(t) == y2); + assert(&std::get<1>(t) == &y); + } + { + // test that the implicitly generated copy assignment operator + // is properly deleted + using T = std::tuple<std::unique_ptr<int>>; + static_assert(!std::is_copy_assignable<T>::value, ""); + } + { + using T = std::tuple<int, NonAssignable>; + static_assert(!std::is_copy_assignable<T>::value, ""); + } + { + using T = std::tuple<int, CopyAssignable>; + static_assert(std::is_copy_assignable<T>::value, ""); + } + { + using T = std::tuple<int, MoveAssignable>; + static_assert(!std::is_copy_assignable<T>::value, ""); + } } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp index fc5e41ad569d..210f14be318a 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp @@ -21,6 +21,33 @@ #include "MoveOnly.h" +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; +}; +struct CopyAssignable { + CopyAssignable& operator=(CopyAssignable const&) = default; + CopyAssignable& operator=(CopyAssignable&&) = delete; +}; +static_assert(std::is_copy_assignable<CopyAssignable>::value, ""); +struct MoveAssignable { + MoveAssignable& operator=(MoveAssignable const&) = delete; + MoveAssignable& operator=(MoveAssignable&&) = default; +}; + + +struct CountAssign { + static int copied; + static int moved; + static void reset() { copied = moved = 0; } + CountAssign() = default; + CountAssign& operator=(CountAssign const&) { ++copied; return *this; } + CountAssign& operator=(CountAssign&&) { ++moved; return *this; } +}; +int CountAssign::copied = 0; +int CountAssign::moved = 0; + + int main() { { @@ -53,4 +80,46 @@ int main() assert(std::get<1>(t) == 1); assert(std::get<2>(t) == 2); } + { + // test reference assignment. + using T = std::tuple<int&, int&&>; + int x = 42; + int y = 100; + int x2 = -1; + int y2 = 500; + T t(x, std::move(y)); + T t2(x2, std::move(y2)); + t = std::move(t2); + assert(std::get<0>(t) == x2); + assert(&std::get<0>(t) == &x); + assert(std::get<1>(t) == y2); + assert(&std::get<1>(t) == &y); + } + { + // test that the implicitly generated move assignment operator + // is properly deleted + using T = std::tuple<std::unique_ptr<int>>; + static_assert(std::is_move_assignable<T>::value, ""); + static_assert(!std::is_copy_assignable<T>::value, ""); + + } + { + using T = std::tuple<int, NonAssignable>; + static_assert(!std::is_move_assignable<T>::value, ""); + } + { + using T = std::tuple<int, MoveAssignable>; + static_assert(std::is_move_assignable<T>::value, ""); + } + { + // The move should decay to a copy. + CountAssign::reset(); + using T = std::tuple<CountAssign, CopyAssignable>; + static_assert(std::is_move_assignable<T>::value, ""); + T t1; + T t2; + t1 = std::move(t2); + assert(CountAssign::copied == 1); + assert(CountAssign::moved == 0); + } } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp index 812e6329bb3e..27656a675982 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp @@ -39,9 +39,9 @@ struct D int main() { { - typedef std::pair<double, std::unique_ptr<D>> T0; - typedef std::tuple<int, std::unique_ptr<B>> T1; - T0 t0(2.5, std::unique_ptr<D>(new D(3))); + typedef std::pair<long, std::unique_ptr<D>> T0; + typedef std::tuple<long long, std::unique_ptr<B>> T1; + T0 t0(2, std::unique_ptr<D>(new D(3))); T1 t1; t1 = std::move(t0); assert(std::get<0>(t1) == 2); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR23256_constrain_UTypes_ctor.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR23256_constrain_UTypes_ctor.pass.cpp index ed3cafadbf08..a5b3d4415e38 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR23256_constrain_UTypes_ctor.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR23256_constrain_UTypes_ctor.pass.cpp @@ -91,6 +91,8 @@ int main() { } { std::tuple<A&&> t(std::forward_as_tuple(A{})); + ((void)t); std::tuple<ExplicitA&&> t2(std::forward_as_tuple(ExplicitA{})); + ((void)t2); } } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR31384.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR31384.pass.cpp new file mode 100644 index 000000000000..dd9b832423a6 --- /dev/null +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR31384.pass.cpp @@ -0,0 +1,88 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <tuple> + +// template <class TupleLike> tuple(TupleLike&&); // libc++ extension + +// See llvm.org/PR31384 +#include <tuple> +#include <cassert> + +int count = 0; + +struct Explicit { + Explicit() = default; + explicit Explicit(int) {} +}; + +struct Implicit { + Implicit() = default; + Implicit(int) {} +}; + +template<class T> +struct Derived : std::tuple<T> { + using std::tuple<T>::tuple; + template<class U> + operator std::tuple<U>() && { ++count; return {}; } +}; + + +template<class T> +struct ExplicitDerived : std::tuple<T> { + using std::tuple<T>::tuple; + template<class U> + explicit operator std::tuple<U>() && { ++count; return {}; } +}; + +int main() { + { + std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo); + assert(count == 1); + std::tuple<Explicit> bar(Derived<int>{42}); ((void)bar); + assert(count == 2); + } + count = 0; + { + std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo); + assert(count == 1); + std::tuple<Implicit> bar(Derived<int>{42}); ((void)bar); + assert(count == 2); + } + count = 0; + { + static_assert(!std::is_convertible< + ExplicitDerived<int>, std::tuple<Explicit>>::value, ""); + std::tuple<Explicit> bar(ExplicitDerived<int>{42}); ((void)bar); + assert(count == 1); + } + count = 0; + { + // FIXME: Libc++ incorrectly rejects this code. +#ifndef _LIBCPP_VERSION + std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo); + static_assert(std::is_convertible< + ExplicitDerived<int>, std::tuple<Implicit>>::value, + "correct STLs accept this"); +#else + static_assert(!std::is_convertible< + ExplicitDerived<int>, std::tuple<Implicit>>::value, + "libc++ incorrectly rejects this"); +#endif + assert(count == 0); + std::tuple<Implicit> bar(ExplicitDerived<int>{42}); ((void)bar); + assert(count == 1); + } + count = 0; + +} diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp index 6ab303c735be..06284df56642 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp @@ -20,9 +20,11 @@ #include <cassert> #include <type_traits> +#include "test_macros.h" +#include "test_convertible.hpp" #include "MoveOnly.h" -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 struct Empty {}; struct A @@ -123,17 +125,23 @@ int main() // extensions #ifdef _LIBCPP_VERSION { - std::tuple<MoveOnly, MoveOnly, MoveOnly> t(MoveOnly(0), - MoveOnly(1)); + using E = MoveOnly; + using Tup = std::tuple<E, E, E>; + // Test that the reduced arity initialization extension is only + // allowed on the explicit constructor. + static_assert(test_convertible<Tup, E, E, E>(), ""); + + Tup t(E(0), E(1)); + static_assert(!test_convertible<Tup, E, E>(), ""); assert(std::get<0>(t) == 0); assert(std::get<1>(t) == 1); assert(std::get<2>(t) == MoveOnly()); - } - { - std::tuple<MoveOnly, MoveOnly, MoveOnly> t(MoveOnly(0)); + + Tup t2(E(0)); + static_assert(!test_convertible<Tup, E>(), ""); assert(std::get<0>(t) == 0); - assert(std::get<1>(t) == MoveOnly()); - assert(std::get<2>(t) == MoveOnly()); + assert(std::get<1>(t) == E()); + assert(std::get<2>(t) == E()); } #endif #if TEST_STD_VER > 11 diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_const_pair.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_const_pair.pass.cpp index c5941618180d..1d0c7b49aaaa 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_const_pair.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_const_pair.pass.cpp @@ -27,8 +27,8 @@ int main() { { - typedef std::pair<double, int> T0; - typedef std::tuple<int, double> T1; + typedef std::pair<long, int> T0; + typedef std::tuple<long long, double> T1; T0 t0(2, 3); T1 t1(std::allocator_arg, A1<int>(5), t0); assert(std::get<0>(t1) == 2); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_convert_copy.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_convert_copy.pass.cpp index 36d9f32879cb..153cd2b3d7ce 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_convert_copy.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_convert_copy.pass.cpp @@ -37,9 +37,9 @@ struct Implicit { int main() { { - typedef std::tuple<double> T0; - typedef std::tuple<int> T1; - T0 t0(2.5); + typedef std::tuple<long> T0; + typedef std::tuple<long long> T1; + T0 t0(2); T1 t1(std::allocator_arg, A1<int>(), t0); assert(std::get<0>(t1) == 2); } @@ -65,9 +65,9 @@ int main() assert(std::get<1>(t1) == 3); } { - typedef std::tuple<double, int, int> T0; - typedef std::tuple<int, alloc_first, alloc_last> T1; - T0 t0(1.5, 2, 3); + typedef std::tuple<long, int, int> T0; + typedef std::tuple<long long, alloc_first, alloc_last> T1; + T0 t0(1, 2, 3); alloc_first::allocator_constructed = false; alloc_last::allocator_constructed = false; T1 t1(std::allocator_arg, A1<int>(5), t0); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp index 367f19e5d8dd..0da132fcfc26 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp @@ -19,6 +19,7 @@ #include <string> #include <cassert> +#include "test_macros.h" template <class ...> struct never { @@ -81,12 +82,13 @@ int main() { // check that the literal '0' can implicitly initialize a stored pointer. std::tuple<int*> t = 0; + assert(std::get<0>(t) == nullptr); } { std::tuple<int> t(2); assert(std::get<0>(t) == 2); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::tuple<int> t(2); static_assert(std::get<0>(t) == 2, ""); @@ -101,7 +103,7 @@ int main() assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::tuple<int, char*> t(2, nullptr); static_assert(std::get<0>(t) == 2, ""); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp index d6d489fd0ea4..bed161a3dcef 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp @@ -19,23 +19,25 @@ #include <utility> #include <cassert> +#include "test_macros.h" + int main() { { - typedef std::pair<double, char> T0; - typedef std::tuple<int, short> T1; - T0 t0(2.5, 'a'); + typedef std::pair<long, char> T0; + typedef std::tuple<long long, short> T1; + T0 t0(2, 'a'); T1 t1 = t0; assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == short('a')); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { - typedef std::pair<double, char> P0; - typedef std::tuple<int, short> T1; - constexpr P0 p0(2.5, 'a'); + typedef std::pair<long, char> P0; + typedef std::tuple<long long, short> T1; + constexpr P0 p0(2, 'a'); constexpr T1 t1 = p0; - static_assert(std::get<0>(t1) != std::get<0>(p0), ""); + static_assert(std::get<0>(t1) == std::get<0>(p0), ""); static_assert(std::get<1>(t1) == std::get<1>(p0), ""); static_assert(std::get<0>(t1) == 2, ""); static_assert(std::get<1>(t1) == short('a'), ""); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp index b7fa2e3a03cc..4609b042556b 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp @@ -20,6 +20,8 @@ #include <string> #include <cassert> +#include "test_macros.h" + struct Explicit { int value; explicit Explicit(int x) : value(x) {} @@ -43,7 +45,7 @@ struct D explicit D(int i) : B(i) {} }; -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 struct A { @@ -66,17 +68,17 @@ struct C int main() { { - typedef std::tuple<double> T0; - typedef std::tuple<int> T1; - T0 t0(2.5); + typedef std::tuple<long> T0; + typedef std::tuple<long long> T1; + T0 t0(2); T1 t1 = t0; assert(std::get<0>(t1) == 2); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { - typedef std::tuple<double> T0; + typedef std::tuple<int> T0; typedef std::tuple<A> T1; - constexpr T0 t0(2.5); + constexpr T0 t0(2); constexpr T1 t1 = t0; static_assert(std::get<0>(t1) == 2, ""); } @@ -89,17 +91,17 @@ int main() } #endif { - typedef std::tuple<double, char> T0; - typedef std::tuple<int, int> T1; - T0 t0(2.5, 'a'); + typedef std::tuple<long, char> T0; + typedef std::tuple<long long, int> T1; + T0 t0(2, 'a'); T1 t1 = t0; assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); } { - typedef std::tuple<double, char, D> T0; - typedef std::tuple<int, int, B> T1; - T0 t0(2.5, 'a', D(3)); + typedef std::tuple<long, char, D> T0; + typedef std::tuple<long long, int, B> T1; + T0 t0(2, 'a', D(3)); T1 t1 = t0; assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); @@ -107,9 +109,9 @@ int main() } { D d(3); - typedef std::tuple<double, char, D&> T0; - typedef std::tuple<int, int, B&> T1; - T0 t0(2.5, 'a', d); + typedef std::tuple<long, char, D&> T0; + typedef std::tuple<long long, int, B&> T1; + T0 t0(2, 'a', d); T1 t1 = t0; d.id_ = 2; assert(std::get<0>(t1) == 2); @@ -117,9 +119,9 @@ int main() assert(std::get<2>(t1).id_ == 2); } { - typedef std::tuple<double, char, int> T0; - typedef std::tuple<int, int, B> T1; - T0 t0(2.5, 'a', 3); + typedef std::tuple<long, char, int> T0; + typedef std::tuple<long long, int, B> T1; + T0 t0(2, 'a', 3); T1 t1(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp index 8423f5d0145f..2af86fdd0868 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp @@ -48,24 +48,24 @@ struct D int main() { { - typedef std::tuple<double> T0; - typedef std::tuple<int> T1; - T0 t0(2.5); + typedef std::tuple<long> T0; + typedef std::tuple<long long> T1; + T0 t0(2); T1 t1 = std::move(t0); assert(std::get<0>(t1) == 2); } { - typedef std::tuple<double, char> T0; - typedef std::tuple<int, int> T1; - T0 t0(2.5, 'a'); + typedef std::tuple<long, char> T0; + typedef std::tuple<long long, int> T1; + T0 t0(2, 'a'); T1 t1 = std::move(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); } { - typedef std::tuple<double, char, D> T0; - typedef std::tuple<int, int, B> T1; - T0 t0(2.5, 'a', D(3)); + typedef std::tuple<long, char, D> T0; + typedef std::tuple<long long, int, B> T1; + T0 t0(2, 'a', D(3)); T1 t1 = std::move(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); @@ -73,9 +73,9 @@ int main() } { D d(3); - typedef std::tuple<double, char, D&> T0; - typedef std::tuple<int, int, B&> T1; - T0 t0(2.5, 'a', d); + typedef std::tuple<long, char, D&> T0; + typedef std::tuple<long long, int, B&> T1; + T0 t0(2, 'a', d); T1 t1 = std::move(t0); d.id_ = 2; assert(std::get<0>(t1) == 2); @@ -83,9 +83,9 @@ int main() assert(std::get<2>(t1).id_ == 2); } { - typedef std::tuple<double, char, std::unique_ptr<D>> T0; - typedef std::tuple<int, int, std::unique_ptr<B>> T1; - T0 t0(2.5, 'a', std::unique_ptr<D>(new D(3))); + typedef std::tuple<long, char, std::unique_ptr<D>> T0; + typedef std::tuple<long long, int, std::unique_ptr<B>> T1; + T0 t0(2, 'a', std::unique_ptr<D>(new D(3))); T1 t1 = std::move(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == int('a')); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp index 783c9d1f06a8..1137df2918dd 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp @@ -19,6 +19,8 @@ #include <string> #include <cassert> +#include "test_macros.h" + struct Empty {}; int main() @@ -50,7 +52,7 @@ int main() assert(std::get<1>(t) == 'a'); assert(std::get<2>(t) == "some text"); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { typedef std::tuple<int> T; constexpr T t0(2); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/dtor.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/dtor.pass.cpp new file mode 100644 index 000000000000..fbcda44e4065 --- /dev/null +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/dtor.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <tuple> + +// template <class... Types> class tuple; + +// ~tuple(); + +#include <tuple> +#include <string> +#include <cassert> +#include <type_traits> + +int main() +{ + static_assert(std::is_trivially_destructible< + std::tuple<> >::value, ""); + static_assert(std::is_trivially_destructible< + std::tuple<void*> >::value, ""); + static_assert(std::is_trivially_destructible< + std::tuple<int, float> >::value, ""); + static_assert(!std::is_trivially_destructible< + std::tuple<std::string> >::value, ""); + static_assert(!std::is_trivially_destructible< + std::tuple<int, std::string> >::value, ""); +} diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp index 0c93673532bb..1cc13cf58ba8 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp @@ -29,7 +29,7 @@ struct ConstructsWithTupleLeaf ConstructsWithTupleLeaf(ConstructsWithTupleLeaf &&) {} template <class T> - ConstructsWithTupleLeaf(T t) { + ConstructsWithTupleLeaf(T) { static_assert(!std::is_same<T, T>::value, "Constructor instantiated for type other than int"); } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move_pair.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move_pair.pass.cpp index 2dfbaff6cc1a..13558f3fbe17 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move_pair.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move_pair.pass.cpp @@ -38,9 +38,9 @@ struct D int main() { { - typedef std::pair<double, std::unique_ptr<D>> T0; - typedef std::tuple<int, std::unique_ptr<B>> T1; - T0 t0(2.5, std::unique_ptr<D>(new D(3))); + typedef std::pair<long, std::unique_ptr<D>> T0; + typedef std::tuple<long long, std::unique_ptr<B>> T1; + T0 t0(2, std::unique_ptr<D>(new D(3))); T1 t1 = std::move(t0); assert(std::get<0>(t1) == 2); assert(std::get<1>(t1)->id_ == 3); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.creation/forward_as_tuple.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.creation/forward_as_tuple.pass.cpp index 2dbe81513a1a..1099e3579687 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.creation/forward_as_tuple.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.creation/forward_as_tuple.pass.cpp @@ -18,6 +18,8 @@ #include <type_traits> #include <cassert> +#include "test_macros.h" + template <class Tuple> void test0(const Tuple&) @@ -54,7 +56,7 @@ test2a(const Tuple& t) assert(std::get<1>(t) == 'a'); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 template <class Tuple> constexpr int test3(const Tuple&) @@ -79,7 +81,7 @@ int main() double i = 2.5; char c = 'a'; test2a(std::forward_as_tuple(i, c)); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert ( test3 (std::forward_as_tuple(i, c)) == 2, "" ); #endif } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.creation/make_tuple.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.creation/make_tuple.pass.cpp index f27e8a09fb97..2c38bf7d230c 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.creation/make_tuple.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.creation/make_tuple.pass.cpp @@ -20,6 +20,8 @@ #include <functional> #include <cassert> +#include "test_macros.h" + int main() { { @@ -40,7 +42,7 @@ int main() assert(i == 0); assert(j == 0); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr auto t1 = std::make_tuple(0, 1, 3.14); constexpr int i1 = std::get<1>(t1); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.creation/tie.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.creation/tie.pass.cpp index 52ecd249402f..c4c3c242d8f8 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.creation/tie.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.creation/tie.pass.cpp @@ -20,6 +20,8 @@ #include <string> #include <cassert> +#include "test_macros.h" + int main() { { @@ -29,7 +31,7 @@ int main() assert(i == 42); assert(s == "C++"); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { static constexpr int i = 42; static constexpr double f = 1.1; diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp index 770edcaca5e1..18095f7e3033 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp @@ -21,6 +21,7 @@ #include <string> #include <cassert> +#include "test_macros.h" #include "MoveOnly.h" int main() @@ -48,7 +49,7 @@ int main() assert(std::get<0>(t) == 1); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { constexpr std::tuple<> t = std::tuple_cat(); ((void)t); // Prevent unused warning diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const.pass.cpp index 002ad148ad6d..f014916742ad 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const.pass.cpp @@ -21,6 +21,8 @@ #include <string> #include <cassert> +#include "test_macros.h" + struct Empty {}; int main() @@ -36,7 +38,7 @@ int main() assert(std::get<0>(t) == "high"); assert(std::get<1>(t) == 5); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { typedef std::tuple<double, int> T; constexpr T t(2.718, 5); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.fail.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.fail.cpp index 58df2df7679a..9c2d992b8e49 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.fail.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.fail.cpp @@ -19,7 +19,7 @@ #include <tuple> -template <class T> void cref(T const&) {}; +template <class T> void cref(T const&) {} template <class T> void cref(T const&&) = delete; std::tuple<int> const tup4() { return std::make_tuple(4); } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_non_const.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_non_const.pass.cpp index 86d1191db556..fc53412899fb 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_non_const.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.elem/get_non_const.pass.cpp @@ -71,7 +71,7 @@ int main() assert(std::get<2>(t) == 4); assert(d == 2.5); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { // get on an rvalue tuple static_assert ( std::get<0> ( std::make_tuple ( 0.0f, 1, 2.0, 3L )) == 0, "" ); static_assert ( std::get<1> ( std::make_tuple ( 0.0f, 1, 2.0, 3L )) == 1, "" ); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.pass.cpp index 42e4fab88ffa..5beedbe9d157 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_element.pass.cpp @@ -23,6 +23,8 @@ #include <tuple> #include <type_traits> +#include "test_macros.h" + template <class T, std::size_t N, class U> void test() { @@ -30,7 +32,7 @@ void test() static_assert((std::is_same<typename std::tuple_element<N, const T>::type, const U>::value), ""); static_assert((std::is_same<typename std::tuple_element<N, volatile T>::type, volatile U>::value), ""); static_assert((std::is_same<typename std::tuple_element<N, const volatile T>::type, const volatile U>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same<typename std::tuple_element_t<N, T>, U>::value), ""); static_assert((std::is_same<typename std::tuple_element_t<N, const T>, const U>::value), ""); static_assert((std::is_same<typename std::tuple_element_t<N, volatile T>, volatile U>::value), ""); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp index 3f132e47b626..50c6f17efbef 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp @@ -21,7 +21,7 @@ int main() { - (void)std::tuple_size<std::tuple<> &>::value; // expected-error {{implicit instantiation of undefined template}} - (void)std::tuple_size<int>::value; // expected-error {{implicit instantiation of undefined template}} - (void)std::tuple_size<std::tuple<>*>::value; // expected-error {{implicit instantiation of undefined template}} + (void)std::tuple_size<std::tuple<> &>::value; // expected-error {{no member named 'value'}} + (void)std::tuple_size<int>::value; // expected-error {{no member named 'value'}} + (void)std::tuple_size<std::tuple<>*>::value; // expected-error {{no member named 'value'}} } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp index 49b4215a1956..40214f632e75 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp @@ -18,19 +18,36 @@ // UNSUPPORTED: c++98, c++03 #include <tuple> +#include <utility> +#include <array> #include <type_traits> +template <class T, class = decltype(std::tuple_size<T>::value)> +constexpr bool has_value(int) { return true; } +template <class> constexpr bool has_value(long) { return false; } +template <class T> constexpr bool has_value() { return has_value<T>(0); } + + template <class T, std::size_t N> void test() { + static_assert(has_value<T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<T> >::value), ""); + static_assert(has_value<const T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<const T> >::value), ""); + static_assert(has_value<volatile T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<volatile T> >::value), ""); + + static_assert(has_value<const volatile T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<const volatile T> >::value), ""); + { + static_assert(!has_value<T &>(), ""); + static_assert(!has_value<T *>(), ""); + } } int main() @@ -39,4 +56,13 @@ int main() test<std::tuple<int>, 1>(); test<std::tuple<char, int>, 2>(); test<std::tuple<char, char*, int>, 3>(); + test<std::pair<int, void*>, 2>(); + test<std::array<int, 42>, 42>(); + { + static_assert(!has_value<void>(), ""); + static_assert(!has_value<void*>(), ""); + static_assert(!has_value<int>(), ""); + static_assert(!has_value<std::pair<int, int>*>(), ""); + static_assert(!has_value<std::array<int, 42>&>(), ""); + } } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp index 957a683b47f8..700dd95c959c 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp @@ -22,5 +22,5 @@ int main() (void)std::tuple_size_v<std::tuple<> &>; // expected-note {{requested here}} (void)std::tuple_size_v<int>; // expected-note {{requested here}} (void)std::tuple_size_v<std::tuple<>*>; // expected-note {{requested here}} - // expected-error@tuple:* 3 {{implicit instantiation of undefined template}} + // expected-error@tuple:* 3 {{no member named 'value'}} } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp index e5991df636f8..a802a05da2bc 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp @@ -21,6 +21,8 @@ #include <string> #include <cassert> +#include "test_macros.h" + int main() { { @@ -49,104 +51,104 @@ int main() } { typedef std::tuple<int, double> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); - const T2 t2(1, char(2)); + const T2 t2(1, 2); assert(t1 == t2); assert(!(t1 != t2)); } { typedef std::tuple<int, double> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); - const T2 t2(1, char(3)); + const T2 t2(1, 3); assert(!(t1 == t2)); assert(t1 != t2); } { typedef std::tuple<int, double> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); - const T2 t2(1.1, char(2)); + const T2 t2(1.1, 2); assert(!(t1 == t2)); assert(t1 != t2); } { typedef std::tuple<int, double> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); - const T2 t2(1.1, char(3)); + const T2 t2(1.1, 3); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 2, 3); assert(t1 == t2); assert(!(t1 != t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1.1, 2, 3); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 3, 3); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 2, 4); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 3, 2); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1.1, 2, 2); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1.1, 3, 3); assert(!(t1 == t2)); assert(t1 != t2); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1.1, 3, 2); assert(!(t1 == t2)); assert(t1 != t2); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; constexpr T1 t1(1, 2, 3); constexpr T2 t2(1.1, 3, 2); static_assert(!(t1 == t2), ""); diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp index 34aafb1e1347..f4d764b87ee9 100644 --- a/test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp +++ b/test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp @@ -33,6 +33,8 @@ #include <string> #include <cassert> +#include "test_macros.h" + int main() { { @@ -46,7 +48,7 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char> T1; + typedef std::tuple<long> T1; typedef std::tuple<double> T2; const T1 t1(1); const T2 t2(1); @@ -56,7 +58,7 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char> T1; + typedef std::tuple<long> T1; typedef std::tuple<double> T2; const T1 t1(1); const T2 t2(0.9); @@ -66,7 +68,7 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char> T1; + typedef std::tuple<long> T1; typedef std::tuple<double> T2; const T1 t1(1); const T2 t2(1.1); @@ -76,8 +78,8 @@ int main() assert(!(t1 >= t2)); } { - typedef std::tuple<char, int> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<long, int> T1; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); const T2 t2(1, 2); assert(!(t1 < t2)); @@ -86,8 +88,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<long, int> T1; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); const T2 t2(0.9, 2); assert(!(t1 < t2)); @@ -96,8 +98,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<long, int> T1; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); const T2 t2(1.1, 2); assert( (t1 < t2)); @@ -106,8 +108,8 @@ int main() assert(!(t1 >= t2)); } { - typedef std::tuple<char, int> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<long, int> T1; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); const T2 t2(1, 1); assert(!(t1 < t2)); @@ -116,8 +118,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int> T1; - typedef std::tuple<double, char> T2; + typedef std::tuple<long, int> T1; + typedef std::tuple<double, long> T2; const T1 t1(1, 2); const T2 t2(1, 3); assert( (t1 < t2)); @@ -126,8 +128,8 @@ int main() assert(!(t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 2, 3); assert(!(t1 < t2)); @@ -136,8 +138,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(0.9, 2, 3); assert(!(t1 < t2)); @@ -146,8 +148,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1.1, 2, 3); assert( (t1 < t2)); @@ -156,8 +158,8 @@ int main() assert(!(t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 1, 3); assert(!(t1 < t2)); @@ -166,8 +168,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 3, 3); assert( (t1 < t2)); @@ -176,8 +178,8 @@ int main() assert(!(t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 2, 2); assert(!(t1 < t2)); @@ -186,8 +188,8 @@ int main() assert( (t1 >= t2)); } { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; const T1 t1(1, 2, 3); const T2 t2(1, 2, 4); assert( (t1 < t2)); @@ -195,10 +197,10 @@ int main() assert(!(t1 > t2)); assert(!(t1 >= t2)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { - typedef std::tuple<char, int, double> T1; - typedef std::tuple<double, char, int> T2; + typedef std::tuple<long, int, double> T1; + typedef std::tuple<double, long, int> T2; constexpr T1 t1(1, 2, 3); constexpr T2 t2(1, 2, 4); static_assert( (t1 < t2), ""); diff --git a/test/std/utilities/utility/exchange/exchange.pass.cpp b/test/std/utilities/utility/exchange/exchange.pass.cpp index 5ef0ac3b09f5..2d01d6c8c8af 100644 --- a/test/std/utilities/utility/exchange/exchange.pass.cpp +++ b/test/std/utilities/utility/exchange/exchange.pass.cpp @@ -22,10 +22,10 @@ int main() int v = 12; assert ( std::exchange ( v, 23 ) == 12 ); assert ( v == 23 ); - assert ( std::exchange ( v, 67.2 ) == 23 ); + assert ( std::exchange ( v, static_cast<short>(67) ) == 23 ); assert ( v == 67 ); - assert ((std::exchange<int, float> ( v, {} )) == 67 ); + assert ((std::exchange<int, short> ( v, {} )) == 67 ); assert ( v == 0 ); } diff --git a/test/std/utilities/utility/forward/forward.fail.cpp b/test/std/utilities/utility/forward/forward.fail.cpp new file mode 100644 index 000000000000..a3bb890482ef --- /dev/null +++ b/test/std/utilities/utility/forward/forward.fail.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test forward + +#include <utility> + +#include "test_macros.h" + +struct A +{ +}; + +A source() {return A();} +const A csource() {return A();} + +int main() +{ +#if TEST_STD_VER >= 11 + { + std::forward<A&>(source()); // expected-note {{requested here}} + // expected-error@type_traits:* 1 {{static_assert failed "can not forward an rvalue as an lvalue"}} + } +#else + { + std::forward<A&>(source()); // expected-error {{no matching function for call to 'forward'}} + } +#endif + { + const A ca = A(); + std::forward<A&>(ca); // expected-error {{no matching function for call to 'forward'}} + } + { + std::forward<A&>(csource()); // expected-error {{no matching function for call to 'forward'}} + } + { + const A ca = A(); + std::forward<A>(ca); // expected-error {{no matching function for call to 'forward'}} + } + { + std::forward<A>(csource()); // expected-error {{no matching function for call to 'forward'}} + } + { + A a; + std::forward(a); // expected-error {{no matching function for call to 'forward'}} + } +} diff --git a/test/std/utilities/utility/forward/forward.pass.cpp b/test/std/utilities/utility/forward/forward.pass.cpp index 94575485df04..afff8d627fad 100644 --- a/test/std/utilities/utility/forward/forward.pass.cpp +++ b/test/std/utilities/utility/forward/forward.pass.cpp @@ -7,32 +7,40 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // test forward #include <utility> +#include <type_traits> #include <cassert> +#include "test_macros.h" + struct A { }; -A source() {return A();} -const A csource() {return A();} - -typedef char one; -struct two {one _[2];}; -struct four {one _[4];}; -struct eight {one _[8];}; - -one test(A&); -two test(const A&); - -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - -four test(A&&); -eight test(const A&&); - -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +A source() noexcept {return A();} +const A csource() noexcept {return A();} + + +constexpr bool test_constexpr_forward() { +#if TEST_STD_VER > 11 + int x = 42; + const int cx = 101; + return std::forward<int&>(x) == 42 + && std::forward<int>(x) == 42 + && std::forward<const int&>(x) == 42 + && std::forward<const int>(x) == 42 + && std::forward<int&&>(x) == 42 + && std::forward<const int&&>(x) == 42 + && std::forward<const int&>(cx) == 101 + && std::forward<const int>(cx) == 101; +#else + return true; +#endif +} int main() { @@ -42,42 +50,42 @@ int main() ((void)a); // Prevent unused warning ((void)ca); // Prevent unused warning -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - static_assert(sizeof(test(std::forward<A&>(a))) == 1, ""); - static_assert(sizeof(test(std::forward<A>(a))) == 4, ""); - static_assert(sizeof(test(std::forward<A>(source()))) == 4, ""); - - static_assert(sizeof(test(std::forward<const A&>(a))) == 2, ""); -// static_assert(sizeof(test(std::forward<const A&>(source()))) == 2, ""); - static_assert(sizeof(test(std::forward<const A>(a))) == 8, ""); - static_assert(sizeof(test(std::forward<const A>(source()))) == 8, ""); - - static_assert(sizeof(test(std::forward<const A&>(ca))) == 2, ""); -// static_assert(sizeof(test(std::forward<const A&>(csource()))) == 2, ""); - static_assert(sizeof(test(std::forward<const A>(ca))) == 8, ""); - static_assert(sizeof(test(std::forward<const A>(csource()))) == 8, ""); - -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - - static_assert(sizeof(test(std::forward<A&>(a))) == 1, ""); - static_assert(sizeof(test(std::forward<A>(a))) == 1, ""); -// static_assert(sizeof(test(std::forward<A>(source()))) == 2, ""); - - static_assert(sizeof(test(std::forward<const A&>(a))) == 2, ""); - static_assert(sizeof(test(std::forward<const A&>(source()))) == 2, ""); - static_assert(sizeof(test(std::forward<const A>(a))) == 2, ""); - static_assert(sizeof(test(std::forward<const A>(source()))) == 2, ""); - - static_assert(sizeof(test(std::forward<const A&>(ca))) == 2, ""); - static_assert(sizeof(test(std::forward<const A&>(csource()))) == 2, ""); - static_assert(sizeof(test(std::forward<const A>(ca))) == 2, ""); - static_assert(sizeof(test(std::forward<const A>(csource()))) == 2, ""); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#if _LIBCPP_STD_VER > 11 - constexpr int i1 = std::move(23); - static_assert(i1 == 23, "" ); + static_assert(std::is_same<decltype(std::forward<A&>(a)), A&>::value, ""); + static_assert(std::is_same<decltype(std::forward<A>(a)), A&&>::value, ""); + static_assert(std::is_same<decltype(std::forward<A>(source())), A&&>::value, ""); + static_assert(noexcept(std::forward<A&>(a)), ""); + static_assert(noexcept(std::forward<A>(a)), ""); + static_assert(noexcept(std::forward<A>(source())), ""); + + static_assert(std::is_same<decltype(std::forward<const A&>(a)), const A&>::value, ""); + static_assert(std::is_same<decltype(std::forward<const A>(a)), const A&&>::value, ""); + static_assert(std::is_same<decltype(std::forward<const A>(source())), const A&&>::value, ""); + static_assert(noexcept(std::forward<const A&>(a)), ""); + static_assert(noexcept(std::forward<const A>(a)), ""); + static_assert(noexcept(std::forward<const A>(source())), ""); + + static_assert(std::is_same<decltype(std::forward<const A&>(ca)), const A&>::value, ""); + static_assert(std::is_same<decltype(std::forward<const A>(ca)), const A&&>::value, ""); + static_assert(std::is_same<decltype(std::forward<const A>(csource())), const A&&>::value, ""); + static_assert(noexcept(std::forward<const A&>(ca)), ""); + static_assert(noexcept(std::forward<const A>(ca)), ""); + static_assert(noexcept(std::forward<const A>(csource())), ""); + +#if TEST_STD_VER > 11 + { + constexpr int i2 = std::forward<int>(42); + static_assert(std::forward<int>(42) == 42, ""); + static_assert(std::forward<const int&>(i2) == 42, ""); + static_assert(test_constexpr_forward(), ""); + } +#endif +#if TEST_STD_VER == 11 && defined(_LIBCPP_VERSION) + // Test that std::forward is constexpr in C++11. This is an extension + // provided by both libc++ and libstdc++. + { constexpr int i2 = std::forward<int>(42); - static_assert(i2 == 42, "" ); + static_assert(std::forward<int>(42) == 42, "" ); + static_assert(std::forward<const int&>(i2) == 42, ""); + } #endif } diff --git a/test/std/utilities/utility/forward/forward5.fail.cpp b/test/std/utilities/utility/forward/forward5.fail.cpp deleted file mode 100644 index 86c2b5651b90..000000000000 --- a/test/std/utilities/utility/forward/forward5.fail.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// test forward - -#include <utility> - -struct A -{ -}; - -A source() {return A();} -const A csource() {return A();} - -int main() -{ - const A ca = A(); - std::forward<A>(csource()); // error -} diff --git a/test/std/utilities/utility/forward/forward_03.pass.cpp b/test/std/utilities/utility/forward/forward_03.pass.cpp new file mode 100644 index 000000000000..7e141bad94e8 --- /dev/null +++ b/test/std/utilities/utility/forward/forward_03.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test forward + +#include <utility> +#include <cassert> + +#include "test_macros.h" + +struct A +{ +}; + +A source() {return A();} +const A csource() {return A();} + +typedef char one; +struct two {one _[2];}; +struct four {one _[4];}; +struct eight {one _[8];}; + +one test(A&); +two test(const A&); + +int main() +{ + A a; + const A ca = A(); + + ((void)a); // Prevent unused warning + ((void)ca); // Prevent unused warning + +#if TEST_STD_VER < 11 + static_assert(sizeof(test(std::forward<A&>(a))) == 1, ""); + static_assert(sizeof(test(std::forward<A>(a))) == 1, ""); + + // Libc++'s C++03 implementation of 'forward' cannot accept true non-const + // rvalues. + // static_assert(sizeof(test(std::forward<A>(source()))) == 2, ""); + + static_assert(sizeof(test(std::forward<const A&>(a))) == 2, ""); + static_assert(sizeof(test(std::forward<const A&>(source()))) == 2, ""); + static_assert(sizeof(test(std::forward<const A>(a))) == 2, ""); + static_assert(sizeof(test(std::forward<const A>(source()))) == 2, ""); + + static_assert(sizeof(test(std::forward<const A&>(ca))) == 2, ""); + static_assert(sizeof(test(std::forward<const A&>(csource()))) == 2, ""); + static_assert(sizeof(test(std::forward<const A>(ca))) == 2, ""); + static_assert(sizeof(test(std::forward<const A>(csource()))) == 2, ""); +#endif +} diff --git a/test/std/utilities/utility/forward/move_only.pass.cpp b/test/std/utilities/utility/forward/move.fail.cpp index 520bf5e5b6a1..bd2126cbaee4 100644 --- a/test/std/utilities/utility/forward/move_only.pass.cpp +++ b/test/std/utilities/utility/forward/move.fail.cpp @@ -7,22 +7,17 @@ // //===----------------------------------------------------------------------===// -// test move - // UNSUPPORTED: c++98, c++03 +// test move + #include <utility> #include <cassert> -class move_only -{ - move_only(const move_only&); - move_only& operator=(const move_only&); -public: - move_only(move_only&&) {} - move_only& operator=(move_only&&) {return *this;} - +struct move_only { move_only() {} + move_only(move_only&&) = default; + move_only& operator=(move_only&&) = default; }; move_only source() {return move_only();} @@ -32,8 +27,8 @@ void test(move_only) {} int main() { - move_only mo; + move_only a; + const move_only ca = move_only(); - test(std::move(mo)); - test(source()); + test(std::move(ca)); // c } diff --git a/test/std/utilities/utility/forward/move.pass.cpp b/test/std/utilities/utility/forward/move.pass.cpp new file mode 100644 index 000000000000..e2edc2a2afad --- /dev/null +++ b/test/std/utilities/utility/forward/move.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test move + +// UNSUPPORTED: c++98, c++03 + +#include <utility> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +class move_only +{ + move_only(const move_only&); + move_only& operator=(const move_only&); +public: + move_only(move_only&&) {} + move_only& operator=(move_only&&) {return *this;} + + move_only() {} +}; + +move_only source() {return move_only();} +const move_only csource() {return move_only();} + +void test(move_only) {} + +int x = 42; +const int& cx = x; + +template <class QualInt> +QualInt get() noexcept { return static_cast<QualInt>(x); } + + +int copy_ctor = 0; +int move_ctor = 0; + +struct A { + A() {} + A(const A&) {++copy_ctor;} + A(A&&) {++move_ctor;} + A& operator=(const A&) = delete; +}; + +constexpr bool test_constexpr_move() { +#if TEST_STD_VER > 11 + int y = 42; + const int cy = y; + return std::move(y) == 42 + && std::move(cy) == 42 + && std::move(static_cast<int&&>(y)) == 42 + && std::move(static_cast<int const&&>(y)) == 42; +#else + return true; +#endif +} + +int main() +{ + { // Test return type and noexcept. + static_assert(std::is_same<decltype(std::move(x)), int&&>::value, ""); + static_assert(noexcept(std::move(x)), ""); + static_assert(std::is_same<decltype(std::move(cx)), const int&&>::value, ""); + static_assert(noexcept(std::move(cx)), ""); + static_assert(std::is_same<decltype(std::move(42)), int&&>::value, ""); + static_assert(noexcept(std::move(42)), ""); + static_assert(std::is_same<decltype(std::move(get<const int&&>())), const int&&>::value, ""); + static_assert(noexcept(std::move(get<int const&&>())), ""); + } + { // test copy and move semantics + A a; + const A ca = A(); + + assert(copy_ctor == 0); + assert(move_ctor == 0); + + A a2 = a; + assert(copy_ctor == 1); + assert(move_ctor == 0); + + A a3 = std::move(a); + assert(copy_ctor == 1); + assert(move_ctor == 1); + + A a4 = ca; + assert(copy_ctor == 2); + assert(move_ctor == 1); + + A a5 = std::move(ca); + assert(copy_ctor == 3); + assert(move_ctor == 1); + } + { // test on a move only type + move_only mo; + test(std::move(mo)); + test(source()); + } +#if TEST_STD_VER > 11 + { + constexpr int y = 42; + static_assert(std::move(y) == 42, ""); + static_assert(test_constexpr_move(), ""); + } +#endif +#if TEST_STD_VER == 11 && defined(_LIBCPP_VERSION) + // Test that std::forward is constexpr in C++11. This is an extension + // provided by both libc++ and libstdc++. + { + constexpr int y = 42; + static_assert(std::move(y) == 42, ""); + } +#endif +} diff --git a/test/std/utilities/utility/forward/move_copy.pass.cpp b/test/std/utilities/utility/forward/move_copy.pass.cpp deleted file mode 100644 index fa15553f669f..000000000000 --- a/test/std/utilities/utility/forward/move_copy.pass.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// test move - -// UNSUPPORTED: c++98, c++03 - -#include <utility> -#include <cassert> - -int copy_ctor = 0; -int move_ctor = 0; - -class A -{ -public: - - A(const A&) {++copy_ctor;} - A& operator=(const A&); - - A(A&&) {++move_ctor;} - A& operator=(A&&); - - A() {} -}; - -A source() {return A();} -const A csource() {return A();} - -void test(A) {} - -int main() -{ - A a; - const A ca = A(); - - assert(copy_ctor == 0); - assert(move_ctor == 0); - - A a2 = a; - assert(copy_ctor == 1); - assert(move_ctor == 0); - - A a3 = std::move(a); - assert(copy_ctor == 1); - assert(move_ctor == 1); - - A a4 = ca; - assert(copy_ctor == 2); - assert(move_ctor == 1); - - A a5 = std::move(ca); - assert(copy_ctor == 3); - assert(move_ctor == 1); -} diff --git a/test/std/utilities/utility/forward/move_only1.fail.cpp b/test/std/utilities/utility/forward/move_only1.fail.cpp deleted file mode 100644 index 5e7623a1bd19..000000000000 --- a/test/std/utilities/utility/forward/move_only1.fail.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// test move - -#include <utility> -#include <cassert> - -#include <typeinfo> -#include <stdio.h> - -class move_only -{ -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(const move_only&); - move_only& operator=(const move_only&); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&); - move_only& operator=(move_only&); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -public: - -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&&) {} - move_only& operator=(move_only&&) {} -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - operator std::__rv<move_only> () {return std::__rv<move_only>(*this);} - move_only(std::__rv<move_only>) {} -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - - move_only() {} -}; - -move_only source() {return move_only();} -const move_only csource() {return move_only();} - -void test(move_only) {} - -int main() -{ - move_only a; - const move_only ca = move_only(); - - test(a); -} diff --git a/test/std/utilities/utility/forward/move_only2.fail.cpp b/test/std/utilities/utility/forward/move_only2.fail.cpp deleted file mode 100644 index 2043f3d4bde7..000000000000 --- a/test/std/utilities/utility/forward/move_only2.fail.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// test move - -#include <utility> -#include <cassert> - -#include <typeinfo> -#include <stdio.h> - -class move_only -{ -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(const move_only&); - move_only& operator=(const move_only&); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&); - move_only& operator=(move_only&); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -public: - -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&&) {} - move_only& operator=(move_only&&) {} -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - operator std::__rv<move_only> () {return std::__rv<move_only>(*this);} - move_only(std::__rv<move_only>) {} -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - - move_only() {} -}; - -move_only source() {return move_only();} -const move_only csource() {return move_only();} - -void test(move_only) {} - -int main() -{ - move_only a; - const move_only ca = move_only(); - - test(ca); -} diff --git a/test/std/utilities/utility/forward/move_only3.fail.cpp b/test/std/utilities/utility/forward/move_only3.fail.cpp deleted file mode 100644 index 84c83ae48f8a..000000000000 --- a/test/std/utilities/utility/forward/move_only3.fail.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// test move - -#include <utility> -#include <cassert> - -class move_only -{ -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(const move_only&); - move_only& operator=(const move_only&); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&); - move_only& operator=(move_only&); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -public: - -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&&) {} - move_only& operator=(move_only&&) {} -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - operator std::__rv<move_only> () {return std::__rv<move_only>(*this);} - move_only(std::__rv<move_only>) {} -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - - move_only() {} -}; - -move_only source() {return move_only();} -const move_only csource() {return move_only();} - -void test(move_only) {} - -int main() -{ - move_only a; - const move_only ca = move_only(); - - test(std::move(ca)); -} diff --git a/test/std/utilities/utility/forward/move_only4.fail.cpp b/test/std/utilities/utility/forward/move_only4.fail.cpp deleted file mode 100644 index 5eeca89abe36..000000000000 --- a/test/std/utilities/utility/forward/move_only4.fail.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// test move - -#include <utility> -#include <cassert> - -#include <typeinfo> -#include <stdio.h> - -class move_only -{ -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(const move_only&); - move_only& operator=(const move_only&); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&); - move_only& operator=(move_only&); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -public: - -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - move_only(move_only&&) {} - move_only& operator=(move_only&&) {} -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - operator std::__rv<move_only> () {return std::__rv<move_only>(*this);} - move_only(std::__rv<move_only>) {} -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - - move_only() {} -}; - -move_only source() {return move_only();} -const move_only csource() {return move_only();} - -void test(move_only) {} - -int main() -{ - move_only a; - const move_only ca = move_only(); - - test(csource()); -} diff --git a/test/std/utilities/utility/pairs/pair.astuple/get_const.pass.cpp b/test/std/utilities/utility/pairs/pair.astuple/get_const.pass.cpp index 9ef7bcff2ba8..c09c8815e16f 100644 --- a/test/std/utilities/utility/pairs/pair.astuple/get_const.pass.cpp +++ b/test/std/utilities/utility/pairs/pair.astuple/get_const.pass.cpp @@ -24,7 +24,7 @@ int main() { { typedef std::pair<int, short> P; - const P p(3, 4); + const P p(3, static_cast<short>(4)); assert(std::get<0>(p) == 3); assert(std::get<1>(p) == 4); } @@ -32,7 +32,7 @@ int main() #if TEST_STD_VER > 11 { typedef std::pair<int, short> P; - constexpr P p1(3, 4); + constexpr P p1(3, static_cast<short>(4)); static_assert(std::get<0>(p1) == 3, ""); static_assert(std::get<1>(p1) == 4, ""); } diff --git a/test/std/utilities/utility/pairs/pair.astuple/get_const_rv.pass.cpp b/test/std/utilities/utility/pairs/pair.astuple/get_const_rv.pass.cpp index edd2f3d0752f..5c38318d26da 100644 --- a/test/std/utilities/utility/pairs/pair.astuple/get_const_rv.pass.cpp +++ b/test/std/utilities/utility/pairs/pair.astuple/get_const_rv.pass.cpp @@ -28,7 +28,7 @@ int main() { { typedef std::pair<std::unique_ptr<int>, short> P; - const P p(std::unique_ptr<int>(new int(3)), 4); + const P p(std::unique_ptr<int>(new int(3)), static_cast<short>(4)); static_assert(std::is_same<const std::unique_ptr<int>&&, decltype(std::get<0>(std::move(p)))>::value, ""); static_assert(noexcept(std::get<0>(std::move(p))), ""); const std::unique_ptr<int>&& ptr = std::get<0>(std::move(p)); @@ -58,7 +58,7 @@ int main() #if TEST_STD_VER > 11 { typedef std::pair<int, short> P; - constexpr const P p1(3, 4); + constexpr const P p1(3, static_cast<short>(4)); static_assert(std::get<0>(std::move(p1)) == 3, ""); static_assert(std::get<1>(std::move(p1)) == 4, ""); } diff --git a/test/std/utilities/utility/pairs/pair.astuple/get_non_const.pass.cpp b/test/std/utilities/utility/pairs/pair.astuple/get_non_const.pass.cpp index 47b4c06134d9..2f8b6c1e8497 100644 --- a/test/std/utilities/utility/pairs/pair.astuple/get_non_const.pass.cpp +++ b/test/std/utilities/utility/pairs/pair.astuple/get_non_const.pass.cpp @@ -34,7 +34,7 @@ int main() { { typedef std::pair<int, short> P; - P p(3, 4); + P p(3, static_cast<short>(4)); assert(std::get<0>(p) == 3); assert(std::get<1>(p) == 4); std::get<0>(p) = 5; diff --git a/test/std/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp b/test/std/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp index aa5ca530913c..0601e4e73a74 100644 --- a/test/std/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp +++ b/test/std/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair @@ -21,12 +23,10 @@ int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::pair<std::unique_ptr<int>, short> P; - P p(std::unique_ptr<int>(new int(3)), 4); + P p(std::unique_ptr<int>(new int(3)), static_cast<short>(4)); std::unique_ptr<int> ptr = std::get<0>(std::move(p)); assert(*ptr == 3); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp index 8c7dee2499dd..1ef2d9402fc3 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp @@ -7,24 +7,94 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair // template<class U, class V> pair(U&& x, V&& y); + #include <utility> #include <memory> #include <cassert> +#include "archetypes.hpp" +#include "test_convertible.hpp" +using namespace ImplicitTypes; // Get implicitly archetypes + +template <class T1, class T1Arg, + bool CanCopy = true, bool CanConvert = CanCopy> +void test_sfinae() { + using P1 = std::pair<T1, int>; + using P2 = std::pair<int, T1>; + using T2 = int const&; + static_assert(std::is_constructible<P1, T1Arg, T2>::value == CanCopy, ""); + static_assert(test_convertible<P1, T1Arg, T2>() == CanConvert, ""); + static_assert(std::is_constructible<P2, T2, T1Arg>::value == CanCopy, ""); + static_assert(test_convertible<P2, T2, T1Arg>() == CanConvert, ""); +} + +struct ExplicitT { + constexpr explicit ExplicitT(int x) : value(x) {} + int value; +}; + +struct ImplicitT { + constexpr ImplicitT(int x) : value(x) {} + int value; +}; + + int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::pair<std::unique_ptr<int>, short*> P; P p(std::unique_ptr<int>(new int(3)), nullptr); assert(*p.first == 3); assert(p.second == nullptr); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + { + // Test non-const lvalue and rvalue types + test_sfinae<AllCtors, AllCtors&>(); + test_sfinae<AllCtors, AllCtors&&>(); + test_sfinae<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>(); + test_sfinae<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>(); + test_sfinae<CopyOnly, CopyOnly&>(); + test_sfinae<CopyOnly, CopyOnly&&>(); + test_sfinae<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>(); + test_sfinae<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>(); + test_sfinae<MoveOnly, MoveOnly&, false>(); + test_sfinae<MoveOnly, MoveOnly&&>(); + test_sfinae<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); + test_sfinae<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, true, false>(); + test_sfinae<NonCopyable, NonCopyable&, false>(); + test_sfinae<NonCopyable, NonCopyable&&, false>(); + test_sfinae<ExplicitTypes::NonCopyable, ExplicitTypes::NonCopyable&, false>(); + test_sfinae<ExplicitTypes::NonCopyable, ExplicitTypes::NonCopyable&&, false>(); + } + { + // Test converting types + test_sfinae<ConvertingType, int&>(); + test_sfinae<ConvertingType, const int&>(); + test_sfinae<ConvertingType, int&&>(); + test_sfinae<ConvertingType, const int&&>(); + test_sfinae<ExplicitTypes::ConvertingType, int&, true, false>(); + test_sfinae<ExplicitTypes::ConvertingType, const int&, true, false>(); + test_sfinae<ExplicitTypes::ConvertingType, int&&, true, false>(); + test_sfinae<ExplicitTypes::ConvertingType, const int&&, true, false>(); + } +#if TEST_STD_VER > 11 + { // explicit constexpr test + constexpr std::pair<ExplicitT, ExplicitT> p(42, 43); + static_assert(p.first.value == 42, ""); + static_assert(p.second.value == 43, ""); + } + { // implicit constexpr test + constexpr std::pair<ImplicitT, ImplicitT> p = {42, 43}; + static_assert(p.first.value == 42, ""); + static_assert(p.second.value == 43, ""); + } +#endif } diff --git a/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp index fdef5961437a..132443f66a7c 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp @@ -21,7 +21,7 @@ int main() { typedef std::pair<int, short> P1; typedef std::pair<double, long> P2; - P1 p1(3, 4); + P1 p1(3, static_cast<short>(4)); P2 p2; p2 = p1; assert(p2.first == 3); diff --git a/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp new file mode 100644 index 000000000000..3f7066310002 --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <utility> + +// template <class T1, class T2> struct pair + +// pair& operator=(pair const& p); + +#include <utility> +#include <memory> +#include <cassert> + + +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; +}; +struct CopyAssignable { + CopyAssignable() = default; + CopyAssignable(CopyAssignable const&) = default; + CopyAssignable& operator=(CopyAssignable const&) = default; + CopyAssignable& operator=(CopyAssignable&&) = delete; +}; +struct MoveAssignable { + MoveAssignable() = default; + MoveAssignable& operator=(MoveAssignable const&) = delete; + MoveAssignable& operator=(MoveAssignable&&) = default; +}; + +struct CountAssign { + static int copied; + static int moved; + static void reset() { copied = moved = 0; } + CountAssign() = default; + CountAssign& operator=(CountAssign const&) { ++copied; return *this; } + CountAssign& operator=(CountAssign&&) { ++moved; return *this; } +}; +int CountAssign::copied = 0; +int CountAssign::moved = 0; + +struct Incomplete; +extern Incomplete inc_obj; + +int main() +{ + { + typedef std::pair<CopyAssignable, short> P; + const P p1(CopyAssignable(), 4); + P p2; + p2 = p1; + assert(p2.second == 4); + } + { + using P = std::pair<int&, int&&>; + int x = 42; + int y = 101; + int x2 = -1; + int y2 = 300; + P p1(x, std::move(y)); + P p2(x2, std::move(y2)); + p1 = p2; + assert(p1.first == x2); + assert(p1.second == y2); + } + { + using P = std::pair<int, NonAssignable>; + static_assert(!std::is_copy_assignable<P>::value, ""); + } + { + CountAssign::reset(); + using P = std::pair<CountAssign, CopyAssignable>; + static_assert(std::is_copy_assignable<P>::value, ""); + P p; + P p2; + p = p2; + assert(CountAssign::copied == 1); + assert(CountAssign::moved == 0); + } + { + using P = std::pair<int, MoveAssignable>; + static_assert(!std::is_copy_assignable<P>::value, ""); + } + { + using P = std::pair<int, Incomplete&>; + static_assert(!std::is_copy_assignable<P>::value, ""); + P p(42, inc_obj); + assert(&p.second == &inc_obj); + } +} + +struct Incomplete {}; +Incomplete inc_obj; diff --git a/test/std/utilities/utility/pairs/pairs.pair/assign_pair_cxx03.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/assign_pair_cxx03.pass.cpp new file mode 100644 index 000000000000..2623b800fff7 --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/assign_pair_cxx03.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// REQUIRES-ANY: c++98, c++03 + +// <utility> + +// template <class T1, class T2> struct pair + +// pair& operator=(pair const& p); + +#include <utility> +#include <memory> +#include <cassert> + +struct NonAssignable { + NonAssignable() {} +private: + NonAssignable& operator=(NonAssignable const&); +}; + +struct Incomplete; +extern Incomplete inc_obj; + +int main() +{ + { + // Test that we don't constrain the assignment operator in C++03 mode. + // Since we don't have access control SFINAE having pair evaluate SFINAE + // may cause a hard error. + typedef std::pair<int, NonAssignable> P; + static_assert(std::is_copy_assignable<P>::value, ""); + } + { + typedef std::pair<int, Incomplete&> P; + static_assert(std::is_copy_assignable<P>::value, ""); + P p(42, inc_obj); + assert(&p.second == &inc_obj); + } +} + +struct Incomplete {}; +Incomplete inc_obj; diff --git a/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp index a753ee520dfa..38089200e4da 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair @@ -17,9 +19,35 @@ #include <memory> #include <cassert> + +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; +}; +struct CopyAssignable { + CopyAssignable() = default; + CopyAssignable& operator=(CopyAssignable const&) = default; + CopyAssignable& operator=(CopyAssignable&&) = delete; +}; +struct MoveAssignable { + MoveAssignable() = default; + MoveAssignable& operator=(MoveAssignable const&) = delete; + MoveAssignable& operator=(MoveAssignable&&) = default; +}; + +struct CountAssign { + static int copied; + static int moved; + static void reset() { copied = moved = 0; } + CountAssign() = default; + CountAssign& operator=(CountAssign const&) { ++copied; return *this; } + CountAssign& operator=(CountAssign&&) { ++moved; return *this; } +}; +int CountAssign::copied = 0; +int CountAssign::moved = 0; + int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::pair<std::unique_ptr<int>, short> P; P p1(std::unique_ptr<int>(new int(3)), 4); @@ -28,5 +56,41 @@ int main() assert(*p2.first == 3); assert(p2.second == 4); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + { + using P = std::pair<int&, int&&>; + int x = 42; + int y = 101; + int x2 = -1; + int y2 = 300; + P p1(x, std::move(y)); + P p2(x2, std::move(y2)); + p1 = std::move(p2); + assert(p1.first == x2); + assert(p1.second == y2); + } + { + using P = std::pair<int, NonAssignable>; + static_assert(!std::is_move_assignable<P>::value, ""); + } + { + // The move decays to the copy constructor + CountAssign::reset(); + using P = std::pair<CountAssign, CopyAssignable>; + static_assert(std::is_move_assignable<P>::value, ""); + P p; + P p2; + p = std::move(p2); + assert(CountAssign::moved == 0); + assert(CountAssign::copied == 1); + } + { + CountAssign::reset(); + using P = std::pair<CountAssign, MoveAssignable>; + static_assert(std::is_move_assignable<P>::value, ""); + P p; + P p2; + p = std::move(p2); + assert(CountAssign::moved == 1); + assert(CountAssign::copied == 0); + } } diff --git a/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp index a200390f4882..76dfc3f65a23 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair @@ -29,15 +31,13 @@ struct Derived int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::pair<std::unique_ptr<Derived>, short> P1; typedef std::pair<std::unique_ptr<Base>, long> P2; - P1 p1(std::unique_ptr<Derived>(), 4); + P1 p1(std::unique_ptr<Derived>(), static_cast<short>(4)); P2 p2; p2 = std::move(p1); assert(p2.first == nullptr); assert(p2.second == 4); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp new file mode 100644 index 000000000000..ef7bebcf5c29 --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp @@ -0,0 +1,140 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <utility> + +// template <class T1, class T2> struct pair + +// template<class U, class V> pair& operator=(tuple<U, V>&& p); + +#include <utility> +#include <tuple> +#include <array> +#include <memory> +#include <cassert> + +// Clang warns about missing braces when initializing std::array. +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-braces" +#endif + +struct CountingType { + static int constructed; + static int copy_constructed; + static int move_constructed; + static int assigned; + static int copy_assigned; + static int move_assigned; + static void reset() { + constructed = copy_constructed = move_constructed = 0; + assigned = copy_assigned = move_assigned = 0; + } + CountingType() : value(0) { ++constructed; } + CountingType(int v) : value(v) { ++constructed; } + CountingType(CountingType const& o) : value(o.value) { ++constructed; ++copy_constructed; } + CountingType(CountingType&& o) : value(o.value) { ++constructed; ++move_constructed; o.value = -1;} + + CountingType& operator=(CountingType const& o) { + ++assigned; + ++copy_assigned; + value = o.value; + return *this; + } + CountingType& operator=(CountingType&& o) { + ++assigned; + ++move_assigned; + value = o.value; + o.value = -1; + return *this; + } + int value; +}; +int CountingType::constructed; +int CountingType::copy_constructed; +int CountingType::move_constructed; +int CountingType::assigned; +int CountingType::copy_assigned; +int CountingType::move_assigned; + +int main() +{ + using C = CountingType; + { + using P = std::pair<int, C>; + using T = std::tuple<int, C>; + T t(42, C{42}); + P p(101, C{101}); + C::reset(); + p = t; + assert(C::constructed == 0); + assert(C::assigned == 1); + assert(C::copy_assigned == 1); + assert(C::move_assigned == 0); + assert(p.first == 42); + assert(p.second.value == 42); + } + { + using P = std::pair<int, C>; + using T = std::tuple<int, C>; + T t(42, -42); + P p(101, 101); + C::reset(); + p = std::move(t); + assert(C::constructed == 0); + assert(C::assigned == 1); + assert(C::copy_assigned == 0); + assert(C::move_assigned == 1); + assert(p.first == 42); + assert(p.second.value == -42); + } + { + using P = std::pair<C, C>; + using T = std::array<C, 2>; + T t = {42, -42}; + P p{101, 101}; + C::reset(); + p = t; + assert(C::constructed == 0); + assert(C::assigned == 2); + assert(C::copy_assigned == 2); + assert(C::move_assigned == 0); + assert(p.first.value == 42); + assert(p.second.value == -42); + } + { + using P = std::pair<C, C>; + using T = std::array<C, 2>; + T t = {42, -42}; + P p{101, 101}; + C::reset(); + p = t; + assert(C::constructed == 0); + assert(C::assigned == 2); + assert(C::copy_assigned == 2); + assert(C::move_assigned == 0); + assert(p.first.value == 42); + assert(p.second.value == -42); + } + { + using P = std::pair<C, C>; + using T = std::array<C, 2>; + T t = {42, -42}; + P p{101, 101}; + C::reset(); + p = std::move(t); + assert(C::constructed == 0); + assert(C::assigned == 2); + assert(C::copy_assigned == 0); + assert(C::move_assigned == 2); + assert(p.first.value == 42); + assert(p.second.value == -42); + } +} diff --git a/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second.pass.cpp index 2041b39c2dc9..bf19d1abe4c5 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair @@ -16,25 +18,34 @@ #include <utility> #include <cassert> -class A -{ - int data_; -public: - A(int data) : data_(data) {} +#include "archetypes.hpp" +#include "test_convertible.hpp" +using namespace ImplicitTypes; // Get implicitly archetypes - bool operator==(const A& a) const {return data_ == a.data_;} +struct ExplicitT { + constexpr explicit ExplicitT(int x) : value(x) {} + constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {} + int value; }; -#if _LIBCPP_STD_VER > 11 -class AC -{ - int data_; -public: - constexpr AC(int data) : data_(data) {} - - constexpr bool operator==(const AC& a) const {return data_ == a.data_;} +struct ImplicitT { + constexpr ImplicitT(int x) : value(x) {} + constexpr ImplicitT(ImplicitT const& o) : value(o.value) {} + int value; }; -#endif + +template <class T1, + bool CanCopy = true, bool CanConvert = CanCopy> +void test_sfinae() { + using P1 = std::pair<T1, int>; + using P2 = std::pair<int, T1>; + using T1Arg = T1 const&; + using T2 = int const&; + static_assert(std::is_constructible<P1, T1Arg, T2>::value == CanCopy, ""); + static_assert(test_convertible<P1, T1Arg, T2>() == CanConvert, ""); + static_assert(std::is_constructible<P2, T2, T1Arg>::value == CanCopy, ""); + static_assert(test_convertible<P2, T2, T1Arg>() == CanConvert, ""); +} int main() { @@ -45,13 +56,22 @@ int main() assert(p.second == nullptr); } { - typedef std::pair<A, int> P; + typedef std::pair<ImplicitT, int> P; P p(1, 2); - assert(p.first == A(1)); + assert(p.first.value == 1); assert(p.second == 2); } - -#if _LIBCPP_STD_VER > 11 + { + test_sfinae<AllCtors>(); + test_sfinae<ExplicitTypes::AllCtors, true, false>(); + test_sfinae<CopyOnly>(); + test_sfinae<ExplicitTypes::CopyOnly, true, false>(); + test_sfinae<MoveOnly, false>(); + test_sfinae<ExplicitTypes::MoveOnly, false>(); + test_sfinae<NonCopyable, false>(); + test_sfinae<ExplicitTypes::NonCopyable, false>(); + } +#if TEST_STD_VER > 11 { typedef std::pair<float, short*> P; constexpr P p(3.5f, 0); @@ -59,10 +79,20 @@ int main() static_assert(p.second == nullptr, ""); } { - typedef std::pair<AC, int> P; - constexpr P p(1, 2); - static_assert(p.first == AC(1), ""); - static_assert(p.second == 2, ""); + using P = std::pair<ExplicitT, int>; + constexpr ExplicitT e(42); + constexpr int x = 10; + constexpr P p(e, x); + static_assert(p.first.value == 42, ""); + static_assert(p.second == 10, ""); + } + { + using P = std::pair<ImplicitT, int>; + constexpr ImplicitT e(42); + constexpr int x = 10; + constexpr P p = {e, x}; + static_assert(p.first.value == 42, ""); + static_assert(p.second == 10, ""); } #endif } diff --git a/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second_cxx03.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second_cxx03.pass.cpp new file mode 100644 index 000000000000..8c56c2003460 --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/const_first_const_second_cxx03.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <utility> + +// template <class T1, class T2> struct pair + +// pair(const T1& x, const T2& y); + +#include <utility> +#include <cassert> + +class A +{ + int data_; +public: + A(int data) : data_(data) {} + + bool operator==(const A& a) const {return data_ == a.data_;} +}; + +int main() +{ + { + typedef std::pair<float, short*> P; + P p(3.5f, 0); + assert(p.first == 3.5f); + assert(p.second == nullptr); + } + { + typedef std::pair<A, int> P; + P p(1, 2); + assert(p.first == A(1)); + assert(p.second == 2); + } +} diff --git a/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp index 286cce47f050..ade8130d7822 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp @@ -7,27 +7,152 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair -// template <class U, class V> pair(const pair<U, V>& p); +// template <class U, class V> EXPLICIT constexpr pair(const pair<U, V>& p); #include <utility> #include <cassert> +#include "archetypes.hpp" +#include "test_convertible.hpp" +using namespace ImplicitTypes; // Get implicitly archetypes + +template <class T1, class U1, + bool CanCopy = true, bool CanConvert = CanCopy> +void test_pair_const() +{ + using P1 = std::pair<T1, int>; + using P2 = std::pair<int, T1>; + using UP1 = std::pair<U1, int> const&; + using UP2 = std::pair<int, U1> const&; + static_assert(std::is_constructible<P1, UP1>::value == CanCopy, ""); + static_assert(test_convertible<P1, UP1>() == CanConvert, ""); + static_assert(std::is_constructible<P2, UP2>::value == CanCopy, ""); + static_assert(test_convertible<P2, UP2>() == CanConvert, ""); +} + +template <class T, class U> +struct DPair : public std::pair<T, U> { + using Base = std::pair<T, U>; + using Base::Base; +}; + +struct ExplicitT { + constexpr explicit ExplicitT(int x) : value(x) {} + constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {} + int value; +}; + +struct ImplicitT { + constexpr ImplicitT(int x) : value(x) {} + constexpr ImplicitT(ImplicitT const& o) : value(o.value) {} + int value; +}; + int main() { { typedef std::pair<int, short> P1; typedef std::pair<double, long> P2; - P1 p1(3, 4); - P2 p2 = p1; + const P1 p1(3, 4); + const P2 p2 = p1; assert(p2.first == 3); assert(p2.second == 4); } + { + // We allow derived types to use this constructor + using P1 = DPair<long, long>; + using P2 = std::pair<int, int>; + P1 p1(42, 101); + P2 p2(p1); + assert(p2.first == 42); + assert(p2.second = 101); + } + { + test_pair_const<AllCtors, AllCtors>(); // copy construction + test_pair_const<AllCtors, AllCtors&>(); + test_pair_const<AllCtors, AllCtors&&>(); + test_pair_const<AllCtors, const AllCtors&>(); + test_pair_const<AllCtors, const AllCtors&&>(); + + test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors>(); // copy construction + test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>(); + test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>(); + test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&, true, false>(); + test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&, true, false>(); + + test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction + test_pair_const<MoveOnly, MoveOnly&, false>(); + test_pair_const<MoveOnly, MoveOnly&&, false>(); + + test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly, false>(); // copy construction + test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); + test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, false>(); + + test_pair_const<CopyOnly, CopyOnly>(); + test_pair_const<CopyOnly, CopyOnly&>(); + test_pair_const<CopyOnly, CopyOnly&&>(); + + test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>(); + test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>(); + test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>(); -#if _LIBCPP_STD_VER > 11 + test_pair_const<NonCopyable, NonCopyable, false>(); + test_pair_const<NonCopyable, NonCopyable&, false>(); + test_pair_const<NonCopyable, NonCopyable&&, false>(); + test_pair_const<NonCopyable, const NonCopyable&, false>(); + test_pair_const<NonCopyable, const NonCopyable&&, false>(); + } + + { // Test construction of references + test_pair_const<NonCopyable&, NonCopyable&>(); + test_pair_const<NonCopyable&, NonCopyable&&>(); + test_pair_const<NonCopyable&, NonCopyable const&, false>(); + test_pair_const<NonCopyable const&, NonCopyable&&>(); + test_pair_const<NonCopyable&&, NonCopyable&&, false>(); + + test_pair_const<ConvertingType&, int, false>(); + test_pair_const<ExplicitTypes::ConvertingType&, int, false>(); + // Unfortunately the below conversions are allowed and create dangling + // references. + //test_pair_const<ConvertingType&&, int>(); + //test_pair_const<ConvertingType const&, int>(); + //test_pair_const<ConvertingType const&&, int>(); + // But these are not because the converting constructor is explicit. + test_pair_const<ExplicitTypes::ConvertingType&&, int, false>(); + test_pair_const<ExplicitTypes::ConvertingType const&, int, false>(); + test_pair_const<ExplicitTypes::ConvertingType const&&, int, false>(); + + } + { + test_pair_const<AllCtors, int, false>(); + test_pair_const<ExplicitTypes::AllCtors, int, false>(); + test_pair_const<ConvertingType, int>(); + test_pair_const<ExplicitTypes::ConvertingType, int, true, false>(); + + test_pair_const<ConvertingType, int>(); + test_pair_const<ConvertingType, ConvertingType>(); + test_pair_const<ConvertingType, ConvertingType const&>(); + test_pair_const<ConvertingType, ConvertingType&>(); + test_pair_const<ConvertingType, ConvertingType&&>(); + + test_pair_const<ExplicitTypes::ConvertingType, int, true, false>(); + test_pair_const<ExplicitTypes::ConvertingType, int&, true, false>(); + test_pair_const<ExplicitTypes::ConvertingType, const int&, true, false>(); + test_pair_const<ExplicitTypes::ConvertingType, int&&, true, false>(); + test_pair_const<ExplicitTypes::ConvertingType, const int&&, true, false>(); + + test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType>(); + test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType const&, true, false>(); + test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&, true, false>(); + test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&&, true, false>(); + } +#if TEST_STD_VER > 11 { typedef std::pair<int, short> P1; typedef std::pair<double, long> P2; @@ -36,5 +161,21 @@ int main() static_assert(p2.first == 3, ""); static_assert(p2.second == 4, ""); } + { + using P1 = std::pair<int, int>; + using P2 = std::pair<ExplicitT, ExplicitT>; + constexpr P1 p1(42, 101); + constexpr P2 p2(p1); + static_assert(p2.first.value == 42, ""); + static_assert(p2.second.value == 101, ""); + } + { + using P1 = std::pair<int, int>; + using P2 = std::pair<ImplicitT, ImplicitT>; + constexpr P1 p1(42, 101); + constexpr P2 p2 = p1; + static_assert(p2.first.value == 42, ""); + static_assert(p2.second.value == 101, ""); + } #endif } diff --git a/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V_cxx03.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V_cxx03.pass.cpp new file mode 100644 index 000000000000..fbf461f9b7e0 --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V_cxx03.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <utility> + +// template <class T1, class T2> struct pair + +// template <class U, class V> pair(const pair<U, V>& p); + +#include <utility> +#include <cassert> + +int main() +{ + { + typedef std::pair<int, short> P1; + typedef std::pair<double, long> P2; + const P1 p1(3, static_cast<short>(4)); + const P2 p2 = p1; + assert(p2.first == 3); + assert(p2.second == 4); + } +} diff --git a/test/std/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp index 1117db3297b8..1003f3c8b68f 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp @@ -22,7 +22,7 @@ int main() { { typedef std::pair<int, short> P1; - P1 p1(3, 4); + P1 p1(3, static_cast<short>(4)); P1 p2 = p1; assert(p2.first == 3); assert(p2.second == 4); @@ -30,7 +30,7 @@ int main() #if TEST_STD_VER > 11 { typedef std::pair<int, short> P1; - constexpr P1 p1(3, 4); + constexpr P1 p1(3, static_cast<short>(4)); constexpr P1 p2 = p1; static_assert(p2.first == 3, ""); static_assert(p2.second == 4, ""); diff --git a/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp index 97182d24d021..ace00a16f21e 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/default.pass.cpp @@ -27,14 +27,15 @@ #include <cassert> #include "test_macros.h" +#include "archetypes.hpp" int main() { { - typedef std::pair<float, short*> P; - P p; - assert(p.first == 0.0f); - assert(p.second == nullptr); + typedef std::pair<float, short*> P; + P p; + assert(p.first == 0.0f); + assert(p.second == nullptr); } #if TEST_STD_VER >= 11 { @@ -43,5 +44,12 @@ int main() static_assert(p.first == 0.0f, ""); static_assert(p.second == nullptr, ""); } + { + using NoDefault = ImplicitTypes::NoDefault; + using P = std::pair<int, NoDefault>; + static_assert(!std::is_default_constructible<P>::value, ""); + using P2 = std::pair<NoDefault, int>; + static_assert(!std::is_default_constructible<P>::value, ""); + } #endif } diff --git a/test/std/utilities/utility/pairs/pairs.pair/dtor.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/dtor.pass.cpp new file mode 100644 index 000000000000..2d87e7ababab --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/dtor.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <utility> + +// template <class T1, class T2> struct pair + +// ~pair() + + +#include <utility> +#include <type_traits> +#include <string> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + static_assert((std::is_trivially_destructible< + std::pair<int, float> >::value), ""); + static_assert((!std::is_trivially_destructible< + std::pair<int, std::string> >::value), ""); +} diff --git a/test/std/utilities/utility/pairs/pairs.pair/move_ctor.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/move_ctor.pass.cpp index 06cb5e5658c9..99e00b025da2 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/move_ctor.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/move_ctor.pass.cpp @@ -31,7 +31,7 @@ int main() { typedef std::pair<int, short> P1; static_assert(std::is_move_constructible<P1>::value, ""); - P1 p1(3, 4); + P1 p1(3, static_cast<short>(4)); P1 p2 = std::move(p1); assert(p2.first == 3); assert(p2.second == 4); diff --git a/test/std/utilities/utility/pairs/pairs.pair/not_constexpr_cxx11.fail.cpp b/test/std/utilities/utility/pairs/pairs.pair/not_constexpr_cxx11.fail.cpp new file mode 100644 index 000000000000..3704dcc32edc --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/not_constexpr_cxx11.fail.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: c++11 + +// <utility> + +// Test that only the default constructor is constexpr in C++11 + +#include <utility> +#include <cassert> + +struct ExplicitT { + constexpr explicit ExplicitT(int x) : value(x) {} + constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {} + int value; +}; + +struct ImplicitT { + constexpr ImplicitT(int x) : value(x) {} + constexpr ImplicitT(ImplicitT const& o) : value(o.value) {} + int value; +}; + +int main() +{ + { + using P = std::pair<int, int>; + constexpr int x = 42; + constexpr P default_p{}; + constexpr P copy_p(default_p); + constexpr P const_U_V(x, x); // expected-error {{must be initialized by a constant expression}} + constexpr P U_V(42, 101); // expected-error {{must be initialized by a constant expression}} + } + { + using P = std::pair<ExplicitT, ExplicitT>; + constexpr std::pair<int, int> other; + constexpr ExplicitT e(99); + constexpr P const_U_V(e, e); // expected-error {{must be initialized by a constant expression}} + constexpr P U_V(42, 101); // expected-error {{must be initialized by a constant expression}} + constexpr P pair_U_V(other); // expected-error {{must be initialized by a constant expression}} + } + { + using P = std::pair<ImplicitT, ImplicitT>; + constexpr std::pair<int, int> other; + constexpr ImplicitT i = 99; + constexpr P const_U_V = {i, i}; // expected-error {{must be initialized by a constant expression}} + constexpr P U_V = {42, 101}; // expected-error {{must be initialized by a constant expression}} + constexpr P pair_U_V = other; // expected-error {{must be initialized by a constant expression}} + } +} diff --git a/test/std/utilities/utility/pairs/pairs.pair/rv_pair_U_V.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/rv_pair_U_V.pass.cpp index 5fb6c98979b5..2856190841c0 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/rv_pair_U_V.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/rv_pair_U_V.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + // <utility> // template <class T1, class T2> struct pair @@ -17,6 +19,24 @@ #include <memory> #include <cassert> +#include "archetypes.hpp" +#include "test_convertible.hpp" +using namespace ImplicitTypes; // Get implicitly archetypes + +template <class T1, class U1, + bool CanCopy = true, bool CanConvert = CanCopy> +void test_pair_rv() +{ + using P1 = std::pair<T1, int>; + using P2 = std::pair<int, T1>; + using UP1 = std::pair<U1, int>&&; + using UP2 = std::pair<int, U1>&&; + static_assert(std::is_constructible<P1, UP1>::value == CanCopy, ""); + static_assert(test_convertible<P1, UP1>() == CanConvert, ""); + static_assert(std::is_constructible<P2, UP2>::value == CanCopy, ""); + static_assert(test_convertible<P2, UP2>() == CanConvert, ""); +} + struct Base { virtual ~Base() {} @@ -27,9 +47,25 @@ struct Derived { }; + +template <class T, class U> +struct DPair : public std::pair<T, U> { + using Base = std::pair<T, U>; + using Base::Base; +}; + +struct ExplicitT { + constexpr explicit ExplicitT(int x) : value(x) {} + int value; +}; + +struct ImplicitT { + constexpr ImplicitT(int x) : value(x) {} + int value; +}; + int main() { -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::pair<std::unique_ptr<Derived>, short> P1; typedef std::pair<std::unique_ptr<Base>, long> P2; @@ -38,5 +74,104 @@ int main() assert(p2.first == nullptr); assert(p2.second == 4); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + { + // We allow derived types to use this constructor + using P1 = DPair<long, long>; + using P2 = std::pair<int, int>; + P1 p1(42, 101); + P2 p2(std::move(p1)); + assert(p2.first == 42); + assert(p2.second = 101); + } + { + test_pair_rv<AllCtors, AllCtors>(); + test_pair_rv<AllCtors, AllCtors&>(); + test_pair_rv<AllCtors, AllCtors&&>(); + test_pair_rv<AllCtors, const AllCtors&>(); + test_pair_rv<AllCtors, const AllCtors&&>(); + + test_pair_rv<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors>(); + test_pair_rv<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>(); + test_pair_rv<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>(); + test_pair_rv<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&, true, false>(); + test_pair_rv<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&, true, false>(); + + test_pair_rv<MoveOnly, MoveOnly>(); + test_pair_rv<MoveOnly, MoveOnly&, false>(); + test_pair_rv<MoveOnly, MoveOnly&&>(); + + test_pair_rv<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly>(); // copy construction + test_pair_rv<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); + test_pair_rv<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, true, false>(); + + test_pair_rv<CopyOnly, CopyOnly>(); + test_pair_rv<CopyOnly, CopyOnly&>(); + test_pair_rv<CopyOnly, CopyOnly&&>(); + + test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>(); + test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>(); + test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>(); + + test_pair_rv<NonCopyable, NonCopyable, false>(); + test_pair_rv<NonCopyable, NonCopyable&, false>(); + test_pair_rv<NonCopyable, NonCopyable&&, false>(); + test_pair_rv<NonCopyable, const NonCopyable&, false>(); + test_pair_rv<NonCopyable, const NonCopyable&&, false>(); + } + { // Test construction of references + test_pair_rv<NonCopyable&, NonCopyable&>(); + test_pair_rv<NonCopyable&, NonCopyable&&>(); + test_pair_rv<NonCopyable&, NonCopyable const&, false>(); + test_pair_rv<NonCopyable const&, NonCopyable&&>(); + test_pair_rv<NonCopyable&&, NonCopyable&&>(); + + test_pair_rv<ConvertingType&, int, false>(); + test_pair_rv<ExplicitTypes::ConvertingType&, int, false>(); + // Unfortunately the below conversions are allowed and create dangling + // references. + //test_pair_rv<ConvertingType&&, int>(); + //test_pair_rv<ConvertingType const&, int>(); + //test_pair_rv<ConvertingType const&&, int>(); + // But these are not because the converting constructor is explicit. + test_pair_rv<ExplicitTypes::ConvertingType&&, int, false>(); + test_pair_rv<ExplicitTypes::ConvertingType const&, int, false>(); + test_pair_rv<ExplicitTypes::ConvertingType const&&, int, false>(); + } + { + test_pair_rv<AllCtors, int, false>(); + test_pair_rv<ExplicitTypes::AllCtors, int, false>(); + test_pair_rv<ConvertingType, int>(); + test_pair_rv<ExplicitTypes::ConvertingType, int, true, false>(); + + test_pair_rv<ConvertingType, int>(); + test_pair_rv<ConvertingType, ConvertingType>(); + test_pair_rv<ConvertingType, ConvertingType const&>(); + test_pair_rv<ConvertingType, ConvertingType&>(); + test_pair_rv<ConvertingType, ConvertingType&&>(); + + test_pair_rv<ExplicitTypes::ConvertingType, int, true, false>(); + test_pair_rv<ExplicitTypes::ConvertingType, int&, true, false>(); + test_pair_rv<ExplicitTypes::ConvertingType, const int&, true, false>(); + test_pair_rv<ExplicitTypes::ConvertingType, int&&, true, false>(); + test_pair_rv<ExplicitTypes::ConvertingType, const int&&, true, false>(); + + test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType>(); + test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType const&, true, false>(); + test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&, true, false>(); + test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&&, true, false>(); + } +#if TEST_STD_VER > 11 + { // explicit constexpr test + constexpr std::pair<int, int> p1(42, 43); + constexpr std::pair<ExplicitT, ExplicitT> p2(std::move(p1)); + static_assert(p2.first.value == 42, ""); + static_assert(p2.second.value == 43, ""); + } + { // implicit constexpr test + constexpr std::pair<int, int> p1(42, 43); + constexpr std::pair<ImplicitT, ImplicitT> p2 = std::move(p1); + static_assert(p2.first.value == 42, ""); + static_assert(p2.second.value == 43, ""); + } +#endif } diff --git a/test/std/utilities/utility/pairs/pairs.pair/special_member_generation_test.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/special_member_generation_test.pass.cpp new file mode 100644 index 000000000000..1331a3153641 --- /dev/null +++ b/test/std/utilities/utility/pairs/pairs.pair/special_member_generation_test.pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <utility> + +// template <class T, class U> struct pair; + +// pair(pair const&) = default; +// pair(pair &&) = default; +// pair& operator=(pair const&); +// pair& operator=(pair&&); + +// Test that the copy/move constructors and assignment operators are +// correctly defined or deleted based on the properties of `T` and `U`. + +#include <cassert> +#include <string> +#include <tuple> + +#include "archetypes.hpp" +using namespace ImplicitTypes; // Get implicitly archetypes + +namespace ConstructorTest { + +template <class T1, bool CanCopy = true, bool CanMove = CanCopy> void test() { + using P1 = std::pair<T1, int>; + using P2 = std::pair<int, T1>; + static_assert(std::is_copy_constructible<P1>::value == CanCopy, ""); + static_assert(std::is_move_constructible<P1>::value == CanMove, ""); + static_assert(std::is_copy_constructible<P2>::value == CanCopy, ""); + static_assert(std::is_move_constructible<P2>::value == CanMove, ""); +}; + +} // namespace ConstructorTest + +void test_constructors_exist() { + using namespace ConstructorTest; + { + test<int>(); + test<int &>(); + test<int &&, false, true>(); + test<const int>(); + test<const int &>(); + test<const int &&, false, true>(); + } + { + test<Copyable>(); + test<Copyable &>(); + test<Copyable &&, false, true>(); + } + { + test<NonCopyable, false>(); + test<NonCopyable &, true>(); + test<NonCopyable &&, false, true>(); + } + { + // Even though CopyOnly has an explicitly deleted move constructor + // pair's move constructor is only implicitly deleted and therefore + // it doesn't participate in overload resolution. + test<CopyOnly, true, true>(); + test<CopyOnly &, true>(); + test<CopyOnly &&, false, true>(); + } + { + test<MoveOnly, false, true>(); + test<MoveOnly &, true>(); + test<MoveOnly &&, false, true>(); + } +} + +namespace AssignmentOperatorTest { + +template <class T1, bool CanCopy = true, bool CanMove = CanCopy> void test() { + using P1 = std::pair<T1, int>; + using P2 = std::pair<int, T1>; + static_assert(std::is_copy_assignable<P1>::value == CanCopy, ""); + static_assert(std::is_move_assignable<P1>::value == CanMove, ""); + static_assert(std::is_copy_assignable<P2>::value == CanCopy, ""); + static_assert(std::is_move_assignable<P2>::value == CanMove, ""); +}; + +} // namespace AssignmentOperatorTest + +void test_assignment_operator_exists() { + using namespace AssignmentOperatorTest; + { + test<int>(); + test<int &>(); + test<int &&>(); + test<const int, false>(); + test<const int &, false>(); + test<const int &&, false>(); + } + { + test<Copyable>(); + test<Copyable &>(); + test<Copyable &&>(); + } + { + test<NonCopyable, false>(); + test<NonCopyable &, false>(); + test<NonCopyable &&, false>(); + } + { + test<CopyOnly, true>(); + test<CopyOnly &, true>(); + test<CopyOnly &&, true>(); + } + { + test<MoveOnly, false, true>(); + test<MoveOnly &, false, false>(); + test<MoveOnly &&, false, true>(); + } +} + +int main() { + test_constructors_exist(); + test_assignment_operator_exists(); +} diff --git a/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp index dfea61eeacdb..95b1f66d64aa 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp @@ -29,8 +29,8 @@ int main() { { typedef std::pair<int, short> P1; - P1 p1(3, 4); - P1 p2(5, 6); + P1 p1(3, static_cast<short>(4)); + P1 p2(5, static_cast<short>(6)); p1.swap(p2); assert(p1.first == 5); assert(p1.second == 6); diff --git a/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp b/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp index 53cf56700df8..200f044c6359 100644 --- a/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp @@ -32,19 +32,25 @@ int main() typedef std::pair<int, short> P; { static_assert(std::is_copy_constructible<P>::value, ""); +#if !defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) static_assert(std::is_trivially_copy_constructible<P>::value, ""); +#endif } #if TEST_STD_VER >= 11 { static_assert(std::is_move_constructible<P>::value, ""); +#if !defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) static_assert(std::is_trivially_move_constructible<P>::value, ""); +#endif } { using P1 = std::pair<Dummy, int>; static_assert(!std::is_copy_constructible<P1>::value, ""); static_assert(!std::is_trivially_copy_constructible<P1>::value, ""); static_assert(std::is_move_constructible<P1>::value, ""); +#if !defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) static_assert(std::is_trivially_move_constructible<P1>::value, ""); +#endif } #endif } diff --git a/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp b/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp index 9ba8532ab29e..3b994dfd4dfe 100644 --- a/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp @@ -21,12 +21,14 @@ #include <utility> #include <cassert> +#include "test_macros.h" + int main() { { typedef std::pair<int, short> P; - P p1(3, 4); - P p2(3, 4); + P p1(3, static_cast<short>(4)); + P p2(3, static_cast<short>(4)); assert( (p1 == p2)); assert(!(p1 != p2)); assert(!(p1 < p2)); @@ -36,8 +38,8 @@ int main() } { typedef std::pair<int, short> P; - P p1(2, 4); - P p2(3, 4); + P p1(2, static_cast<short>(4)); + P p2(3, static_cast<short>(4)); assert(!(p1 == p2)); assert( (p1 != p2)); assert( (p1 < p2)); @@ -47,8 +49,8 @@ int main() } { typedef std::pair<int, short> P; - P p1(3, 2); - P p2(3, 4); + P p1(3, static_cast<short>(2)); + P p2(3, static_cast<short>(4)); assert(!(p1 == p2)); assert( (p1 != p2)); assert( (p1 < p2)); @@ -58,8 +60,8 @@ int main() } { typedef std::pair<int, short> P; - P p1(3, 4); - P p2(2, 4); + P p1(3, static_cast<short>(4)); + P p2(2, static_cast<short>(4)); assert(!(p1 == p2)); assert( (p1 != p2)); assert(!(p1 < p2)); @@ -69,8 +71,8 @@ int main() } { typedef std::pair<int, short> P; - P p1(3, 4); - P p2(3, 2); + P p1(3, static_cast<short>(4)); + P p2(3, static_cast<short>(2)); assert(!(p1 == p2)); assert( (p1 != p2)); assert(!(p1 < p2)); @@ -79,11 +81,11 @@ int main() assert( (p1 >= p2)); } -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 { typedef std::pair<int, short> P; - constexpr P p1(3, 4); - constexpr P p2(3, 2); + constexpr P p1(3, static_cast<short>(4)); + constexpr P p2(3, static_cast<short>(2)); static_assert(!(p1 == p2), ""); static_assert( (p1 != p2), ""); static_assert(!(p1 < p2), ""); diff --git a/test/std/utilities/utility/pairs/pairs.spec/make_pair.pass.cpp b/test/std/utilities/utility/pairs/pairs.spec/make_pair.pass.cpp index 4a6d71e7b9c8..3586243f8bac 100644 --- a/test/std/utilities/utility/pairs/pairs.spec/make_pair.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.spec/make_pair.pass.cpp @@ -15,34 +15,35 @@ #include <memory> #include <cassert> +#include "test_macros.h" + int main() { { typedef std::pair<int, short> P1; - P1 p1 = std::make_pair(3, 4); + P1 p1 = std::make_pair(3, static_cast<short>(4)); assert(p1.first == 3); assert(p1.second == 4); } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 { typedef std::pair<std::unique_ptr<int>, short> P1; - P1 p1 = std::make_pair(std::unique_ptr<int>(new int(3)), 4); + P1 p1 = std::make_pair(std::unique_ptr<int>(new int(3)), static_cast<short>(4)); assert(*p1.first == 3); assert(p1.second == 4); } { typedef std::pair<std::unique_ptr<int>, short> P1; - P1 p1 = std::make_pair(nullptr, 4); + P1 p1 = std::make_pair(nullptr, static_cast<short>(4)); assert(p1.first == nullptr); assert(p1.second == 4); } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#if _LIBCPP_STD_VER > 11 +#endif +#if TEST_STD_VER >= 14 { typedef std::pair<int, short> P1; - constexpr P1 p1 = std::make_pair(3, 4); + constexpr P1 p1 = std::make_pair(3, static_cast<short>(4)); static_assert(p1.first == 3, ""); static_assert(p1.second == 4, ""); } diff --git a/test/std/utilities/utility/pairs/pairs.spec/non_member_swap.pass.cpp b/test/std/utilities/utility/pairs/pairs.spec/non_member_swap.pass.cpp index d9d8f27b5225..62fa94247946 100644 --- a/test/std/utilities/utility/pairs/pairs.spec/non_member_swap.pass.cpp +++ b/test/std/utilities/utility/pairs/pairs.spec/non_member_swap.pass.cpp @@ -20,8 +20,8 @@ int main() { { typedef std::pair<int, short> P1; - P1 p1(3, 4); - P1 p2(5, 6); + P1 p1(3, static_cast<short>(4)); + P1 p2(5, static_cast<short>(6)); swap(p1, p2); assert(p1.first == 5); assert(p1.second == 6); diff --git a/test/std/utilities/utility/utility.inplace/inplace.pass.cpp b/test/std/utilities/utility/utility.inplace/inplace.pass.cpp new file mode 100644 index 000000000000..e87c6f399e93 --- /dev/null +++ b/test/std/utilities/utility/utility.inplace/inplace.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <utility> + +// struct in_place_t { +// explicit in_place_t() = default; +// }; +// inline constexpr in_place_t in_place{}; + +// template <class T> +// struct in_place_type_t { +// explicit in_place_type_t() = default; +// }; +// template <class T> +// inline constexpr in_place_type_t<T> in_place_type{}; + +// template <size_t I> +// struct in_place_index_t { +// explicit in_place_index_t() = default; +// }; +// template <size_t I> +// inline constexpr in_place_index_t<I> in_place_index{}; + +#include <utility> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "type_id.h" + +template <class Tp, class Up> +constexpr bool check_tag(Up) { + return std::is_same<Tp, std::decay_t<Tp>>::value + && std::is_same<Tp, Up>::value; +} + +int main() { + // test in_place_t + { + using T = std::in_place_t; + static_assert(check_tag<T>(std::in_place)); + } + // test in_place_type_t + { + using T1 = std::in_place_type_t<void>; + using T2 = std::in_place_type_t<int>; + using T3 = std::in_place_type_t<const int>; + static_assert(!std::is_same<T1, T2>::value && !std::is_same<T1, T3>::value); + static_assert(!std::is_same<T2, T3>::value); + static_assert(check_tag<T1>(std::in_place_type<void>)); + static_assert(check_tag<T2>(std::in_place_type<int>)); + static_assert(check_tag<T3>(std::in_place_type<const int>)); + } + // test in_place_index_t + { + using T1 = std::in_place_index_t<0>; + using T2 = std::in_place_index_t<1>; + using T3 = std::in_place_index_t<static_cast<size_t>(-1)>; + static_assert(!std::is_same<T1, T2>::value && !std::is_same<T1, T3>::value); + static_assert(!std::is_same<T2, T3>::value); + static_assert(check_tag<T1>(std::in_place_index<0>)); + static_assert(check_tag<T2>(std::in_place_index<1>)); + static_assert(check_tag<T3>(std::in_place_index<static_cast<size_t>(-1)>)); + } +} diff --git a/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp b/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp new file mode 100644 index 000000000000..77fd1719ff33 --- /dev/null +++ b/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp @@ -0,0 +1,37 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +/* + + class bad_variant_access : public exception { +public: + bad_variant_access() noexcept; + virtual const char* what() const noexcept; +}; + +*/ + +#include <cassert> +#include <exception> +#include <type_traits> +#include <variant> + +int main() { + static_assert(std::is_base_of<std::exception, std::bad_variant_access>::value, + ""); + static_assert(noexcept(std::bad_variant_access{}), "must be noexcept"); + static_assert(noexcept(std::bad_variant_access{}.what()), "must be noexcept"); + std::bad_variant_access ex; + assert(ex.what()); +} diff --git a/test/std/utilities/utility/forward/forward6.fail.cpp b/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp index 1f4b37d946ca..8fb3817dba9b 100644 --- a/test/std/utilities/utility/forward/forward6.fail.cpp +++ b/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure @@ -7,16 +8,4 @@ // //===----------------------------------------------------------------------===// -// test forward - -#include <utility> - -struct A -{ -}; - -int main() -{ - A a; - std::forward(a); // error -} +int main() {} diff --git a/test/std/utilities/variant/variant.get/get_if_index.pass.cpp b/test/std/utilities/variant/variant.get/get_if_index.pass.cpp new file mode 100644 index 000000000000..94cc08031fda --- /dev/null +++ b/test/std/utilities/variant/variant.get/get_if_index.pass.cpp @@ -0,0 +1,132 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <size_t I, class... Types> +// constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> +// get_if(variant<Types...>* v) noexcept; +// template <size_t I, class... Types> +// constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> +// get_if(const variant<Types...>* v) noexcept; + +#include "test_macros.h" +#include "variant_test_helpers.hpp" +#include <cassert> +#include <memory> +#include <variant> + +void test_const_get_if() { + { + using V = std::variant<int>; + constexpr const V *v = nullptr; + static_assert(std::get_if<0>(v) == nullptr, ""); + } + { + using V = std::variant<int, const long>; + constexpr V v(42); + ASSERT_NOEXCEPT(std::get_if<0>(&v)); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); + static_assert(*std::get_if<0>(&v) == 42, ""); + static_assert(std::get_if<1>(&v) == nullptr, ""); + } + { + using V = std::variant<int, const long>; + constexpr V v(42l); + ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), const long *); + static_assert(*std::get_if<1>(&v) == 42, ""); + static_assert(std::get_if<0>(&v) == nullptr, ""); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); + assert(std::get_if<0>(&v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); + assert(std::get_if<0>(&v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); + assert(std::get_if<0>(&v) == &x); + } +#endif +} + +void test_get_if() { + { + using V = std::variant<int>; + V *v = nullptr; + assert(std::get_if<0>(v) == nullptr); + } + { + using V = std::variant<int, long>; + V v(42); + ASSERT_NOEXCEPT(std::get_if<0>(&v)); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); + assert(*std::get_if<0>(&v) == 42); + assert(std::get_if<1>(&v) == nullptr); + } + { + using V = std::variant<int, const long>; + V v(42l); + ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), const long *); + assert(*std::get_if<1>(&v) == 42); + assert(std::get_if<0>(&v) == nullptr); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); + assert(std::get_if<0>(&v) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); + assert(std::get_if<0>(&v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); + assert(std::get_if<0>(&v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); + assert(std::get_if<0>(&v) == &x); + } +#endif +} + +int main() { + test_const_get_if(); + test_get_if(); +} diff --git a/test/std/utilities/variant/variant.get/get_if_type.pass.cpp b/test/std/utilities/variant/variant.get/get_if_type.pass.cpp new file mode 100644 index 000000000000..a8cc664ef113 --- /dev/null +++ b/test/std/utilities/variant/variant.get/get_if_type.pass.cpp @@ -0,0 +1,130 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class T, class... Types> +// constexpr add_pointer_t<T> get_if(variant<Types...>* v) noexcept; +// template <class T, class... Types> +// constexpr add_pointer_t<const T> get_if(const variant<Types...>* v) +// noexcept; + +#include "test_macros.h" +#include "variant_test_helpers.hpp" +#include <cassert> +#include <variant> + +void test_const_get_if() { + { + using V = std::variant<int>; + constexpr const V *v = nullptr; + static_assert(std::get_if<int>(v) == nullptr, ""); + } + { + using V = std::variant<int, const long>; + constexpr V v(42); + ASSERT_NOEXCEPT(std::get_if<int>(&v)); + ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), const int *); + static_assert(*std::get_if<int>(&v) == 42, ""); + static_assert(std::get_if<const long>(&v) == nullptr, ""); + } + { + using V = std::variant<int, const long>; + constexpr V v(42l); + ASSERT_SAME_TYPE(decltype(std::get_if<const long>(&v)), const long *); + static_assert(*std::get_if<const long>(&v) == 42, ""); + static_assert(std::get_if<int>(&v) == nullptr, ""); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get_if<int &>(&v)), int *); + assert(std::get_if<int &>(&v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<int &&>(&v)), int *); + assert(std::get_if<int &&>(&v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<const int &&>(&v)), const int *); + assert(std::get_if<const int &&>(&v) == &x); + } +#endif +} + +void test_get_if() { + { + using V = std::variant<int>; + V *v = nullptr; + assert(std::get_if<int>(v) == nullptr); + } + { + using V = std::variant<int, const long>; + V v(42); + ASSERT_NOEXCEPT(std::get_if<int>(&v)); + ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), int *); + assert(*std::get_if<int>(&v) == 42); + assert(std::get_if<const long>(&v) == nullptr); + } + { + using V = std::variant<int, const long>; + V v(42l); + ASSERT_SAME_TYPE(decltype(std::get_if<const long>(&v)), const long *); + assert(*std::get_if<const long>(&v) == 42); + assert(std::get_if<int>(&v) == nullptr); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get_if<int &>(&v)), int *); + assert(std::get_if<int &>(&v) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get_if<const int &>(&v)), const int *); + assert(std::get_if<const int &>(&v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<int &&>(&v)), int *); + assert(std::get_if<int &&>(&v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get_if<const int &&>(&v)), const int *); + assert(std::get_if<const int &&>(&v) == &x); + } +#endif +} + +int main() { + test_const_get_if(); + test_get_if(); +} diff --git a/test/std/utilities/variant/variant.get/get_index.pass.cpp b/test/std/utilities/variant/variant.get/get_index.pass.cpp new file mode 100644 index 000000000000..72d17b0ed971 --- /dev/null +++ b/test/std/utilities/variant/variant.get/get_index.pass.cpp @@ -0,0 +1,287 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <size_t I, class... Types> +// constexpr variant_alternative_t<I, variant<Types...>>& +// get(variant<Types...>& v); +// template <size_t I, class... Types> +// constexpr variant_alternative_t<I, variant<Types...>>&& +// get(variant<Types...>&& v); +// template <size_t I, class... Types> +// constexpr variant_alternative_t<I, variant<Types...>> const& get(const +// variant<Types...>& v); +// template <size_t I, class... Types> +// constexpr variant_alternative_t<I, variant<Types...>> const&& get(const +// variant<Types...>&& v); + +#include "test_macros.h" +#include "variant_test_helpers.hpp" +#include <cassert> +#include <type_traits> +#include <utility> +#include <variant> + +void test_const_lvalue_get() { + { + using V = std::variant<int, const long>; + constexpr V v(42); +#ifndef __clang__ // Avoid https://llvm.org/bugs/show_bug.cgi?id=15481 + ASSERT_NOEXCEPT(std::get<0>(v)); +#endif + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + static_assert(std::get<0>(v) == 42, ""); + } + { + using V = std::variant<int, const long>; + const V v(42); + ASSERT_NOT_NOEXCEPT(std::get<0>(v)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + assert(std::get<0>(v) == 42); + } + { + using V = std::variant<int, const long>; + constexpr V v(42l); +#ifndef __clang__ // Avoid https://llvm.org/bugs/show_bug.cgi?id=15481 + ASSERT_NOEXCEPT(std::get<1>(v)); +#endif + ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); + static_assert(std::get<1>(v) == 42, ""); + } + { + using V = std::variant<int, const long>; + const V v(42l); + ASSERT_NOT_NOEXCEPT(std::get<1>(v)); + ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); + assert(std::get<1>(v) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + assert(&std::get<0>(v) == &x); + } +#endif +} + +void test_lvalue_get() { + { + using V = std::variant<int, const long>; + V v(42); + ASSERT_NOT_NOEXCEPT(std::get<0>(v)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); + assert(std::get<0>(v) == 42); + } + { + using V = std::variant<int, const long>; + V v(42l); + ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); + assert(std::get<1>(v) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + assert(&std::get<0>(v) == &x); + } +#endif +} + +void test_rvalue_get() { + { + using V = std::variant<int, const long>; + V v(42); + ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v))); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); + assert(std::get<0>(std::move(v)) == 42); + } + { + using V = std::variant<int, const long>; + V v(42l); + ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&); + assert(std::get<1>(std::move(v)) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &); + assert(&std::get<0>(std::move(v)) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &); + assert(&std::get<0>(std::move(v)) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); + int &&xref = std::get<0>(std::move(v)); + assert(&xref == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); + const int &&xref = std::get<0>(std::move(v)); + assert(&xref == &x); + } +#endif +} + +void test_const_rvalue_get() { + { + using V = std::variant<int, const long>; + const V v(42); + ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v))); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); + assert(std::get<0>(std::move(v)) == 42); + } + { + using V = std::variant<int, const long>; + const V v(42l); + ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&); + assert(std::get<1>(std::move(v)) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &); + assert(&std::get<0>(std::move(v)) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &); + assert(&std::get<0>(std::move(v)) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); + int &&xref = std::get<0>(std::move(v)); + assert(&xref == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); + const int &&xref = std::get<0>(std::move(v)); + assert(&xref == &x); + } +#endif +} + +template <std::size_t I> using Idx = std::integral_constant<size_t, I>; + +void test_throws_for_all_value_categories() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, long>; + V v0(42); + const V &cv0 = v0; + assert(v0.index() == 0); + V v1(42l); + const V &cv1 = v1; + assert(v1.index() == 1); + std::integral_constant<size_t, 0> zero; + std::integral_constant<size_t, 1> one; + auto test = [](auto idx, auto &&v) { + using Idx = decltype(idx); + try { + std::get<Idx::value>(std::forward<decltype(v)>(v)); + } catch (const std::bad_variant_access &) { + return true; + } catch (...) { /* ... */ + } + return false; + }; + { // lvalue test cases + assert(test(one, v0)); + assert(test(zero, v1)); + } + { // const lvalue test cases + assert(test(one, cv0)); + assert(test(zero, cv1)); + } + { // rvalue test cases + assert(test(one, std::move(v0))); + assert(test(zero, std::move(v1))); + } + { // const rvalue test cases + assert(test(one, std::move(cv0))); + assert(test(zero, std::move(cv1))); + } +#endif +} + +int main() { + test_const_lvalue_get(); + test_lvalue_get(); + test_rvalue_get(); + test_const_rvalue_get(); + test_throws_for_all_value_categories(); +} diff --git a/test/std/utilities/variant/variant.get/get_type.pass.cpp b/test/std/utilities/variant/variant.get/get_type.pass.cpp new file mode 100644 index 000000000000..fc355378a21a --- /dev/null +++ b/test/std/utilities/variant/variant.get/get_type.pass.cpp @@ -0,0 +1,287 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class T, class... Types> constexpr T& get(variant<Types...>& v); +// template <class T, class... Types> constexpr T&& get(variant<Types...>&& v); +// template <class T, class... Types> constexpr const T& get(const +// variant<Types...>& v); +// template <class T, class... Types> constexpr const T&& get(const +// variant<Types...>&& v); + +#include "test_macros.h" +#include "variant_test_helpers.hpp" +#include <cassert> +#include <type_traits> +#include <utility> +#include <variant> + +void test_const_lvalue_get() { + { + using V = std::variant<int, const long>; + constexpr V v(42); +#ifndef __clang__ // Avoid https://llvm.org/bugs/show_bug.cgi?id=15481 + ASSERT_NOEXCEPT(std::get<int>(v)); +#endif + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + static_assert(std::get<int>(v) == 42, ""); + } + { + using V = std::variant<int, const long>; + const V v(42); + ASSERT_NOT_NOEXCEPT(std::get<int>(v)); + ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); + assert(std::get<int>(v) == 42); + } + { + using V = std::variant<int, const long>; + constexpr V v(42l); +#ifndef __clang__ // Avoid https://llvm.org/bugs/show_bug.cgi?id=15481 + ASSERT_NOEXCEPT(std::get<const long>(v)); +#endif + ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &); + static_assert(std::get<const long>(v) == 42, ""); + } + { + using V = std::variant<int, const long>; + const V v(42l); + ASSERT_NOT_NOEXCEPT(std::get<const long>(v)); + ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &); + assert(std::get<const long>(v) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get<int &>(v)), int &); + assert(&std::get<int &>(v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<int &&>(v)), int &); + assert(&std::get<int &&>(v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<const int &&>(v)), const int &); + assert(&std::get<const int &&>(v) == &x); + } +#endif +} + +void test_lvalue_get() { + { + using V = std::variant<int, const long>; + V v(42); + ASSERT_NOT_NOEXCEPT(std::get<int>(v)); + ASSERT_SAME_TYPE(decltype(std::get<int>(v)), int &); + assert(std::get<int>(v) == 42); + } + { + using V = std::variant<int, const long>; + V v(42l); + ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &); + assert(std::get<const long>(v) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<int &>(v)), int &); + assert(&std::get<int &>(v) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<const int &>(v)), const int &); + assert(&std::get<const int &>(v) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<int &&>(v)), int &); + assert(&std::get<int &&>(v) == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<const int &&>(v)), const int &); + assert(&std::get<const int &&>(v) == &x); + } +#endif +} + +void test_rvalue_get() { + { + using V = std::variant<int, const long>; + V v(42); + ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v))); + ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), int &&); + assert(std::get<int>(std::move(v)) == 42); + } + { + using V = std::variant<int, const long>; + V v(42l); + ASSERT_SAME_TYPE(decltype(std::get<const long>(std::move(v))), + const long &&); + assert(std::get<const long>(std::move(v)) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<int &>(std::move(v))), int &); + assert(&std::get<int &>(std::move(v)) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + V v(x); + ASSERT_SAME_TYPE(decltype(std::get<const int &>(std::move(v))), + const int &); + assert(&std::get<const int &>(std::move(v)) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<int &&>(std::move(v))), int &&); + int &&xref = std::get<int &&>(std::move(v)); + assert(&xref == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<const int &&>(std::move(v))), + const int &&); + const int &&xref = std::get<const int &&>(std::move(v)); + assert(&xref == &x); + } +#endif +} + +void test_const_rvalue_get() { + { + using V = std::variant<int, const long>; + const V v(42); + ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v))); + ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), const int &&); + assert(std::get<int>(std::move(v)) == 42); + } + { + using V = std::variant<int, const long>; + const V v(42l); + ASSERT_SAME_TYPE(decltype(std::get<const long>(std::move(v))), + const long &&); + assert(std::get<const long>(std::move(v)) == 42); + } +// FIXME: Remove these once reference support is reinstated +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get<int &>(std::move(v))), int &); + assert(&std::get<int &>(std::move(v)) == &x); + } + { + using V = std::variant<const int &>; + int x = 42; + const V v(x); + ASSERT_SAME_TYPE(decltype(std::get<const int &>(std::move(v))), + const int &); + assert(&std::get<const int &>(std::move(v)) == &x); + } + { + using V = std::variant<int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<int &&>(std::move(v))), int &&); + int &&xref = std::get<int &&>(std::move(v)); + assert(&xref == &x); + } + { + using V = std::variant<const int &&>; + int x = 42; + const V v(std::move(x)); + ASSERT_SAME_TYPE(decltype(std::get<const int &&>(std::move(v))), + const int &&); + const int &&xref = std::get<const int &&>(std::move(v)); + assert(&xref == &x); + } +#endif +} + +template <class Tp> struct identity { using type = Tp; }; + +void test_throws_for_all_value_categories() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, long>; + V v0(42); + const V &cv0 = v0; + assert(v0.index() == 0); + V v1(42l); + const V &cv1 = v1; + assert(v1.index() == 1); + identity<int> zero; + identity<long> one; + auto test = [](auto idx, auto &&v) { + using Idx = decltype(idx); + try { + std::get<typename Idx::type>(std::forward<decltype(v)>(v)); + } catch (const std::bad_variant_access &) { + return true; + } catch (...) { /* ... */ + } + return false; + }; + { // lvalue test cases + assert(test(one, v0)); + assert(test(zero, v1)); + } + { // const lvalue test cases + assert(test(one, cv0)); + assert(test(zero, cv1)); + } + { // rvalue test cases + assert(test(one, std::move(v0))); + assert(test(zero, std::move(v1))); + } + { // const rvalue test cases + assert(test(one, std::move(cv0))); + assert(test(zero, std::move(cv1))); + } +#endif +} + +int main() { + test_const_lvalue_get(); + test_lvalue_get(); + test_rvalue_get(); + test_const_rvalue_get(); + test_throws_for_all_value_categories(); +} diff --git a/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp b/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp new file mode 100644 index 000000000000..103b0498197d --- /dev/null +++ b/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class T, class... Types> +// constexpr bool holds_alternative(const variant<Types...>& v) noexcept; + +#include "test_macros.h" +#include <variant> + +int main() { + { + using V = std::variant<int>; + constexpr V v; + static_assert(std::holds_alternative<int>(v), ""); + } + { + using V = std::variant<int, long>; + constexpr V v; + static_assert(std::holds_alternative<int>(v), ""); + static_assert(!std::holds_alternative<long>(v), ""); + } + { // noexcept test + using V = std::variant<int>; + const V v; + ASSERT_NOEXCEPT(std::holds_alternative<int>(v)); + } +} diff --git a/test/std/utilities/variant/variant.hash/hash.pass.cpp b/test/std/utilities/variant/variant.hash/hash.pass.cpp new file mode 100644 index 000000000000..d807a7c7e2ea --- /dev/null +++ b/test/std/utilities/variant/variant.hash/hash.pass.cpp @@ -0,0 +1,124 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class... Types> struct hash<variant<Types...>>; +// template <> struct hash<monostate>; + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +#ifndef TEST_HAS_NO_EXCEPTIONS +namespace std { +template <> struct hash<::MakeEmptyT> { + size_t operator()(const ::MakeEmptyT &) const { + assert(false); + return 0; + } +}; +} +#endif + +void test_hash_variant() { + { + using V = std::variant<int, long, int>; + using H = std::hash<V>; + const V v(std::in_place_index<0>, 42); + const V v_copy = v; + V v2(std::in_place_index<0>, 100); + const H h{}; + assert(h(v) == h(v)); + assert(h(v) != h(v2)); + assert(h(v) == h(v_copy)); + { + ASSERT_SAME_TYPE(decltype(h(v)), std::size_t); + static_assert(std::is_copy_constructible<H>::value, ""); + } + } + { + using V = std::variant<std::monostate, int, long, const char *>; + using H = std::hash<V>; + const char *str = "hello"; + const V v0; + const V v0_other; + const V v1(42); + const V v1_other(100); + V v2(100l); + V v2_other(999l); + V v3(str); + V v3_other("not hello"); + const H h{}; + assert(h(v0) == h(v0)); + assert(h(v0) == h(v0_other)); + assert(h(v1) == h(v1)); + assert(h(v1) != h(v1_other)); + assert(h(v2) == h(v2)); + assert(h(v2) != h(v2_other)); + assert(h(v3) == h(v3)); + assert(h(v3) != h(v3_other)); + assert(h(v0) != h(v1)); + assert(h(v0) != h(v2)); + assert(h(v0) != h(v3)); + assert(h(v1) != h(v2)); + assert(h(v1) != h(v3)); + assert(h(v2) != h(v3)); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<int, MakeEmptyT>; + using H = std::hash<V>; + V v; + makeEmpty(v); + V v2; + makeEmpty(v2); + const H h{}; + assert(h(v) == h(v2)); + } +#endif +} + +void test_hash_monostate() { + using H = std::hash<std::monostate>; + const H h{}; + std::monostate m1{}; + const std::monostate m2{}; + assert(h(m1) == h(m1)); + assert(h(m2) == h(m2)); + assert(h(m1) == h(m2)); + { + ASSERT_SAME_TYPE(decltype(h(m1)), std::size_t); + static_assert(std::is_copy_constructible<H>::value, ""); + } +} + +void test_hash_variant_duplicate_elements() { + // Test that the index of the alternative participates in the hash value. + using V = std::variant<std::monostate, std::monostate>; + using H = std::hash<V>; + H h{}; + const V v1(std::in_place_index<0>); + const V v2(std::in_place_index<1>); + assert(h(v1) == h(v1)); + assert(h(v2) == h(v2)); + LIBCPP_ASSERT(h(v1) != h(v2)); +} + +int main() { + test_hash_variant(); + test_hash_variant_duplicate_elements(); + test_hash_monostate(); +} diff --git a/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp b/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp new file mode 100644 index 000000000000..84689a050391 --- /dev/null +++ b/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp @@ -0,0 +1,77 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <size_t I, class T> struct variant_alternative; // undefined +// template <size_t I, class T> struct variant_alternative<I, const T>; +// template <size_t I, class T> struct variant_alternative<I, volatile T>; +// template <size_t I, class T> struct variant_alternative<I, const volatile T>; +// template <size_t I, class T> +// using variant_alternative_t = typename variant_alternative<I, T>::type; +// +// template <size_t I, class... Types> +// struct variant_alternative<I, variant<Types...>>; + +#include <memory> +#include <type_traits> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +template <class V, size_t I, class E> void test() { + static_assert( + std::is_same_v<typename std::variant_alternative<I, V>::type, E>, ""); + static_assert( + std::is_same_v<typename std::variant_alternative<I, const V>::type, + const E>, + ""); + static_assert( + std::is_same_v<typename std::variant_alternative<I, volatile V>::type, + volatile E>, + ""); + static_assert( + std::is_same_v< + typename std::variant_alternative<I, const volatile V>::type, + const volatile E>, + ""); + static_assert(std::is_same_v<std::variant_alternative_t<I, V>, E>, ""); + static_assert(std::is_same_v<std::variant_alternative_t<I, const V>, const E>, + ""); + static_assert( + std::is_same_v<std::variant_alternative_t<I, volatile V>, volatile E>, + ""); + static_assert(std::is_same_v<std::variant_alternative_t<I, const volatile V>, + const volatile E>, + ""); +} + +int main() { + { + using V = std::variant<int, void *, const void *, long double>; + test<V, 0, int>(); + test<V, 1, void *>(); + test<V, 2, const void *>(); + test<V, 3, long double>(); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, int &, const int &, int &&, long double>; + test<V, 0, int>(); + test<V, 1, int &>(); + test<V, 2, const int &>(); + test<V, 3, int &&>(); + test<V, 4, long double>(); + } +#endif +} diff --git a/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp b/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp new file mode 100644 index 000000000000..2085fa56effe --- /dev/null +++ b/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp @@ -0,0 +1,44 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class T> struct variant_size; // undefined +// template <class T> struct variant_size<const T>; +// template <class T> struct variant_size<volatile T>; +// template <class T> struct variant_size<const volatile T>; +// template <class T> constexpr size_t variant_size_v +// = variant_size<T>::value; + +#include <memory> +#include <type_traits> +#include <variant> + +template <class V, size_t E> void test() { + static_assert(std::variant_size<V>::value == E, ""); + static_assert(std::variant_size<const V>::value == E, ""); + static_assert(std::variant_size<volatile V>::value == E, ""); + static_assert(std::variant_size<const volatile V>::value == E, ""); + static_assert(std::variant_size_v<V> == E, ""); + static_assert(std::variant_size_v<const V> == E, ""); + static_assert(std::variant_size_v<volatile V> == E, ""); + static_assert(std::variant_size_v<const volatile V> == E, ""); + static_assert(std::is_base_of<std::integral_constant<std::size_t, E>, + std::variant_size<V>>::value, + ""); +}; + +int main() { + test<std::variant<>, 0>(); + test<std::variant<void *>, 1>(); + test<std::variant<long, long, void *, double>, 4>(); +} diff --git a/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp b/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp new file mode 100644 index 000000000000..49abba2954e5 --- /dev/null +++ b/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp @@ -0,0 +1,55 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// constexpr bool operator<(monostate, monostate) noexcept { return false; } +// constexpr bool operator>(monostate, monostate) noexcept { return false; } +// constexpr bool operator<=(monostate, monostate) noexcept { return true; } +// constexpr bool operator>=(monostate, monostate) noexcept { return true; } +// constexpr bool operator==(monostate, monostate) noexcept { return true; } +// constexpr bool operator!=(monostate, monostate) noexcept { return false; } + +#include "test_macros.h" +#include <cassert> +#include <type_traits> +#include <variant> + +int main() { + using M = std::monostate; + constexpr M m1{}; + constexpr M m2{}; + { + static_assert((m1 < m2) == false, ""); + ASSERT_NOEXCEPT(m1 < m2); + } + { + static_assert((m1 > m2) == false, ""); + ASSERT_NOEXCEPT(m1 > m2); + } + { + static_assert((m1 <= m2) == true, ""); + ASSERT_NOEXCEPT(m1 <= m2); + } + { + static_assert((m1 >= m2) == true, ""); + ASSERT_NOEXCEPT(m1 >= m2); + } + { + static_assert((m1 == m2) == true, ""); + ASSERT_NOEXCEPT(m1 == m2); + } + { + static_assert((m1 != m2) == false, ""); + ASSERT_NOEXCEPT(m1 != m2); + } +} diff --git a/test/std/utilities/variant/variant.monostate/monostate.pass.cpp b/test/std/utilities/variant/variant.monostate/monostate.pass.cpp new file mode 100644 index 000000000000..76cddf90043d --- /dev/null +++ b/test/std/utilities/variant/variant.monostate/monostate.pass.cpp @@ -0,0 +1,28 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// struct monostate {}; + +#include <type_traits> +#include <variant> + +int main() { + using M = std::monostate; + static_assert(std::is_trivially_default_constructible<M>::value, ""); + static_assert(std::is_trivially_copy_constructible<M>::value, ""); + static_assert(std::is_trivially_copy_assignable<M>::value, ""); + static_assert(std::is_trivially_destructible<M>::value, ""); + constexpr M m{}; + ((void)m); +} diff --git a/test/std/utilities/variant/variant.relops/relops.pass.cpp b/test/std/utilities/variant/variant.relops/relops.pass.cpp new file mode 100644 index 000000000000..4337b4bdbbd7 --- /dev/null +++ b/test/std/utilities/variant/variant.relops/relops.pass.cpp @@ -0,0 +1,227 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> +// constexpr bool +// operator==(variant<Types...> const&, variant<Types...> const&) noexcept; +// +// template <class ...Types> +// constexpr bool +// operator!=(variant<Types...> const&, variant<Types...> const&) noexcept; +// +// template <class ...Types> +// constexpr bool +// operator<(variant<Types...> const&, variant<Types...> const&) noexcept; +// +// template <class ...Types> +// constexpr bool +// operator>(variant<Types...> const&, variant<Types...> const&) noexcept; +// +// template <class ...Types> +// constexpr bool +// operator<=(variant<Types...> const&, variant<Types...> const&) noexcept; +// +// template <class ...Types> +// constexpr bool +// operator>=(variant<Types...> const&, variant<Types...> const&) noexcept; + +#include <cassert> +#include <type_traits> +#include <utility> +#include <variant> + +#include "test_macros.h" + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct MakeEmptyT { + MakeEmptyT() = default; + MakeEmptyT(MakeEmptyT &&) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } +}; +inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) { + assert(false); + return false; +} +inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) { + assert(false); + return false; +} +inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) { + assert(false); + return false; +} +inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) { + assert(false); + return false; +} +inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) { + assert(false); + return false; +} +inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) { + assert(false); + return false; +} + +template <class Variant> void makeEmpty(Variant &v) { + Variant v2(std::in_place_type<MakeEmptyT>); + try { + v = std::move(v2); + assert(false); + } catch (...) { + assert(v.valueless_by_exception()); + } +} +#endif // TEST_HAS_NO_EXCEPTIONS + +void test_equality() { + { + using V = std::variant<int, long>; + constexpr V v1(42); + constexpr V v2(42); + static_assert(v1 == v2, ""); + static_assert(v2 == v1, ""); + static_assert(!(v1 != v2), ""); + static_assert(!(v2 != v1), ""); + } + { + using V = std::variant<int, long>; + constexpr V v1(42); + constexpr V v2(43); + static_assert(!(v1 == v2), ""); + static_assert(!(v2 == v1), ""); + static_assert(v1 != v2, ""); + static_assert(v2 != v1, ""); + } + { + using V = std::variant<int, long>; + constexpr V v1(42); + constexpr V v2(42l); + static_assert(!(v1 == v2), ""); + static_assert(!(v2 == v1), ""); + static_assert(v1 != v2, ""); + static_assert(v2 != v1, ""); + } + { + using V = std::variant<int, long>; + constexpr V v1(42l); + constexpr V v2(42l); + static_assert(v1 == v2, ""); + static_assert(v2 == v1, ""); + static_assert(!(v1 != v2), ""); + static_assert(!(v2 != v1), ""); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<int, MakeEmptyT>; + V v1; + V v2; + makeEmpty(v2); + assert(!(v1 == v2)); + assert(!(v2 == v1)); + assert(v1 != v2); + assert(v2 != v1); + } + { + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V v2; + assert(!(v1 == v2)); + assert(!(v2 == v1)); + assert(v1 != v2); + assert(v2 != v1); + } + { + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V v2; + makeEmpty(v2); + assert(v1 == v2); + assert(v2 == v1); + assert(!(v1 != v2)); + assert(!(v2 != v1)); + } +#endif +} + +template <class Var> +constexpr bool test_less(const Var &l, const Var &r, bool expect_less, + bool expect_greater) { + return ((l < r) == expect_less) && (!(l >= r) == expect_less) && + ((l > r) == expect_greater) && (!(l <= r) == expect_greater); +} + +void test_relational() { + { // same index, same value + using V = std::variant<int, long>; + constexpr V v1(1); + constexpr V v2(1); + static_assert(test_less(v1, v2, false, false), ""); + } + { // same index, value < other_value + using V = std::variant<int, long>; + constexpr V v1(0); + constexpr V v2(1); + static_assert(test_less(v1, v2, true, false), ""); + } + { // same index, value > other_value + using V = std::variant<int, long>; + constexpr V v1(1); + constexpr V v2(0); + static_assert(test_less(v1, v2, false, true), ""); + } + { // LHS.index() < RHS.index() + using V = std::variant<int, long>; + constexpr V v1(0); + constexpr V v2(0l); + static_assert(test_less(v1, v2, true, false), ""); + } + { // LHS.index() > RHS.index() + using V = std::variant<int, long>; + constexpr V v1(0l); + constexpr V v2(0); + static_assert(test_less(v1, v2, false, true), ""); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { // LHS.index() < RHS.index(), RHS is empty + using V = std::variant<int, MakeEmptyT>; + V v1; + V v2; + makeEmpty(v2); + assert(test_less(v1, v2, false, true)); + } + { // LHS.index() > RHS.index(), LHS is empty + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V v2; + assert(test_less(v1, v2, true, false)); + } + { // LHS.index() == RHS.index(), LHS and RHS are empty + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V v2; + makeEmpty(v2); + assert(test_less(v1, v2, false, false)); + } +#endif +} + +int main() { + test_equality(); + test_relational(); +} diff --git a/test/std/utilities/utility/forward/forward4.fail.cpp b/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp index 276506f811b5..4d7c8563caad 100644 --- a/test/std/utilities/utility/forward/forward4.fail.cpp +++ b/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure @@ -7,19 +8,14 @@ // //===----------------------------------------------------------------------===// -// test forward +// UNSUPPORTED: c++98, c++03, c++11, c++14 -#include <utility> +// <variant> -struct A -{ -}; +// constexpr size_t variant_npos = -1; -A source() {return A();} -const A csource() {return A();} +#include <variant> -int main() -{ - const A ca = A(); - std::forward<A>(ca); // error +int main() { + static_assert(std::variant_npos == static_cast<std::size_t>(-1), ""); } diff --git a/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp new file mode 100644 index 000000000000..10022b14aa06 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp @@ -0,0 +1,232 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <class T> +// variant& operator=(T&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +namespace MetaHelpers { + +struct Dummy { + Dummy() = default; +}; + +struct ThrowsCtorT { + ThrowsCtorT(int) noexcept(false) {} + ThrowsCtorT &operator=(int) noexcept { return *this; } +}; + +struct ThrowsAssignT { + ThrowsAssignT(int) noexcept {} + ThrowsAssignT &operator=(int) noexcept(false) { return *this; } +}; + +struct NoThrowT { + NoThrowT(int) noexcept {} + NoThrowT &operator=(int) noexcept { return *this; } +}; + +} // namespace MetaHelpers + +namespace RuntimeHelpers { +#ifndef TEST_HAS_NO_EXCEPTIONS + +struct ThrowsCtorT { + int value; + ThrowsCtorT() : value(0) {} + ThrowsCtorT(int) noexcept(false) { throw 42; } + ThrowsCtorT &operator=(int v) noexcept { + value = v; + return *this; + } +}; + +struct ThrowsAssignT { + int value; + ThrowsAssignT() : value(0) {} + ThrowsAssignT(int v) noexcept : value(v) {} + ThrowsAssignT &operator=(int) noexcept(false) { throw 42; } +}; + +struct NoThrowT { + int value; + NoThrowT() : value(0) {} + NoThrowT(int v) noexcept : value(v) {} + NoThrowT &operator=(int v) noexcept { + value = v; + return *this; + } +}; + +#endif // !defined(TEST_HAS_NO_EXCEPTIONS) +} // namespace RuntimeHelpers + +void test_T_assignment_noexcept() { + using namespace MetaHelpers; + { + using V = std::variant<Dummy, NoThrowT>; + static_assert(std::is_nothrow_assignable<V, int>::value, ""); + } + { + using V = std::variant<Dummy, ThrowsCtorT>; + static_assert(!std::is_nothrow_assignable<V, int>::value, ""); + } + { + using V = std::variant<Dummy, ThrowsAssignT>; + static_assert(!std::is_nothrow_assignable<V, int>::value, ""); + } +} + +void test_T_assignment_sfinae() { + { + using V = std::variant<long, unsigned>; + static_assert(!std::is_assignable<V, int>::value, "ambiguous"); + } + { + using V = std::variant<std::string, std::string>; + static_assert(!std::is_assignable<V, const char *>::value, "ambiguous"); + } + { + using V = std::variant<std::string, void *>; + static_assert(!std::is_assignable<V, int>::value, "no matching operator="); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, int &&>; + static_assert(!std::is_assignable<V, int>::value, "ambiguous"); + } + { + using V = std::variant<int, const int &>; + static_assert(!std::is_assignable<V, int>::value, "ambiguous"); + } +#endif +} + +void test_T_assignment_basic() { + { + std::variant<int> v(43); + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v) == 42); + } + { + std::variant<int, long> v(43l); + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v) == 42); + v = 43l; + assert(v.index() == 1); + assert(std::get<1>(v) == 43); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &, int &&, long>; + int x = 42; + V v(43l); + v = x; + assert(v.index() == 0); + assert(&std::get<0>(v) == &x); + v = std::move(x); + assert(v.index() == 1); + assert(&std::get<1>(v) == &x); + // 'long' is selected by FUN(const int &) since 'const int &' cannot bind + // to 'int&'. + const int &cx = x; + v = cx; + assert(v.index() == 2); + assert(std::get<2>(v) == 42); + } +#endif +} + +void test_T_assignment_performs_construction() { + using namespace RuntimeHelpers; +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<std::string, ThrowsCtorT>; + V v(std::in_place_type<std::string>, "hello"); + try { + v = 42; + } catch (...) { /* ... */ + } + assert(v.valueless_by_exception()); + } + { + using V = std::variant<ThrowsAssignT, std::string>; + V v(std::in_place_type<std::string>, "hello"); + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v).value == 42); + } +#endif +} + +void test_T_assignment_performs_assignment() { + using namespace RuntimeHelpers; +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<ThrowsCtorT>; + V v; + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v).value == 42); + } + { + using V = std::variant<ThrowsCtorT, std::string>; + V v; + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v).value == 42); + } + { + using V = std::variant<ThrowsAssignT>; + V v(100); + try { + v = 42; + assert(false); + } catch (...) { /* ... */ + } + assert(v.index() == 0); + assert(std::get<0>(v).value == 100); + } + { + using V = std::variant<std::string, ThrowsAssignT>; + V v(100); + try { + v = 42; + assert(false); + } catch (...) { /* ... */ + } + assert(v.index() == 1); + assert(std::get<1>(v).value == 100); + } +#endif +} + +int main() { + test_T_assignment_basic(); + test_T_assignment_performs_construction(); + test_T_assignment_performs_assignment(); + test_T_assignment_noexcept(); + test_T_assignment_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp new file mode 100644 index 000000000000..d92f16fd6418 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp @@ -0,0 +1,397 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// variant& operator=(variant const&); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NoCopy { + NoCopy(const NoCopy &) = delete; + NoCopy &operator=(const NoCopy &) = default; +}; + +struct NothrowCopy { + NothrowCopy(const NothrowCopy &) noexcept = default; + NothrowCopy &operator=(const NothrowCopy &) noexcept = default; +}; + +struct CopyOnly { + CopyOnly(const CopyOnly &) = default; + CopyOnly(CopyOnly &&) = delete; + CopyOnly &operator=(const CopyOnly &) = default; + CopyOnly &operator=(CopyOnly &&) = delete; +}; + +struct MoveOnly { + MoveOnly(const MoveOnly &) = delete; + MoveOnly(MoveOnly &&) = default; + MoveOnly &operator=(const MoveOnly &) = default; +}; + +struct MoveOnlyNT { + MoveOnlyNT(const MoveOnlyNT &) = delete; + MoveOnlyNT(MoveOnlyNT &&) {} + MoveOnlyNT &operator=(const MoveOnlyNT &) = default; +}; + +struct CopyAssign { + static int alive; + static int copy_construct; + static int copy_assign; + static int move_construct; + static int move_assign; + static void reset() { + copy_construct = copy_assign = move_construct = move_assign = alive = 0; + } + CopyAssign(int v) : value(v) { ++alive; } + CopyAssign(const CopyAssign &o) : value(o.value) { + ++alive; + ++copy_construct; + } + CopyAssign(CopyAssign &&o) : value(o.value) { + o.value = -1; + ++alive; + ++move_construct; + } + CopyAssign &operator=(const CopyAssign &o) { + value = o.value; + ++copy_assign; + return *this; + } + CopyAssign &operator=(CopyAssign &&o) { + value = o.value; + o.value = -1; + ++move_assign; + return *this; + } + ~CopyAssign() { --alive; } + int value; +}; + +int CopyAssign::alive = 0; +int CopyAssign::copy_construct = 0; +int CopyAssign::copy_assign = 0; +int CopyAssign::move_construct = 0; +int CopyAssign::move_assign = 0; + +struct CopyMaybeThrows { + CopyMaybeThrows(const CopyMaybeThrows &); + CopyMaybeThrows &operator=(const CopyMaybeThrows &); +}; +struct CopyDoesThrow { + CopyDoesThrow(const CopyDoesThrow &) noexcept(false); + CopyDoesThrow &operator=(const CopyDoesThrow &) noexcept(false); +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct CopyThrows { + CopyThrows() = default; + CopyThrows(const CopyThrows &) { throw 42; } + CopyThrows &operator=(const CopyThrows &) { throw 42; } +}; + +struct MoveThrows { + static int alive; + MoveThrows() { ++alive; } + MoveThrows(const MoveThrows &) { ++alive; } + MoveThrows(MoveThrows &&) { throw 42; } + MoveThrows &operator=(const MoveThrows &) { return *this; } + MoveThrows &operator=(MoveThrows &&) { throw 42; } + ~MoveThrows() { --alive; } +}; + +int MoveThrows::alive = 0; + +struct MakeEmptyT { + static int alive; + MakeEmptyT() { ++alive; } + MakeEmptyT(const MakeEmptyT &) { + ++alive; + // Don't throw from the copy constructor since variant's assignment + // operator performs a copy before committing to the assignment. + } + MakeEmptyT(MakeEmptyT &&) { throw 42; } + MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } + ~MakeEmptyT() { --alive; } +}; + +int MakeEmptyT::alive = 0; + +template <class Variant> void makeEmpty(Variant &v) { + Variant v2(std::in_place_type<MakeEmptyT>); + try { + v = v2; + assert(false); + } catch (...) { + assert(v.valueless_by_exception()); + } +} +#endif // TEST_HAS_NO_EXCEPTIONS + +void test_copy_assignment_not_noexcept() { + { + using V = std::variant<CopyMaybeThrows>; + static_assert(!std::is_nothrow_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, CopyDoesThrow>; + static_assert(!std::is_nothrow_copy_assignable<V>::value, ""); + } +} + +void test_copy_assignment_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_copy_assignable<V>::value, ""); + } + { + // variant only provides copy assignment when both the copy and move + // constructors are well formed + using V = std::variant<int, CopyOnly>; + static_assert(!std::is_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, NoCopy>; + static_assert(!std::is_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(!std::is_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(!std::is_copy_assignable<V>::value, ""); + } +} + +void test_copy_assignment_empty_empty() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, long, MET>; + V v1(std::in_place_index<0>); + makeEmpty(v1); + V v2(std::in_place_index<0>); + makeEmpty(v2); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } +#endif +} + +void test_copy_assignment_non_empty_empty() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET>; + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>); + makeEmpty(v2); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_index<2>, "hello"); + V v2(std::in_place_index<0>); + makeEmpty(v2); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } +#endif +} + +void test_copy_assignment_empty_non_empty() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET>; + V v1(std::in_place_index<0>); + makeEmpty(v1); + V v2(std::in_place_index<0>, 42); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 0); + assert(std::get<0>(v1) == 42); + } + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_index<0>); + makeEmpty(v1); + V v2(std::in_place_type<std::string>, "hello"); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 2); + assert(std::get<2>(v1) == "hello"); + } +#endif +} + +void test_copy_assignment_same_index() { + { + using V = std::variant<int>; + V v1(43); + V v2(42); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 0); + assert(std::get<0>(v1) == 42); + } + { + using V = std::variant<int, long, unsigned>; + V v1(43l); + V v2(42l); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1) == 42); + } + { + using V = std::variant<int, CopyAssign, unsigned>; + V v1(std::in_place_type<CopyAssign>, 43); + V v2(std::in_place_type<CopyAssign>, 42); + CopyAssign::reset(); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1).value == 42); + assert(CopyAssign::copy_construct == 0); + assert(CopyAssign::move_construct == 0); + assert(CopyAssign::copy_assign == 1); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_type<MET>); + MET &mref = std::get<1>(v1); + V v2(std::in_place_type<MET>); + try { + v1 = v2; + assert(false); + } catch (...) { + } + assert(v1.index() == 1); + assert(&std::get<1>(v1) == &mref); + } +#endif +} + +void test_copy_assignment_different_index() { + { + using V = std::variant<int, long, unsigned>; + V v1(43); + V v2(42l); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1) == 42); + } + { + using V = std::variant<int, CopyAssign, unsigned>; + CopyAssign::reset(); + V v1(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<CopyAssign>, 42); + assert(CopyAssign::copy_construct == 0); + assert(CopyAssign::move_construct == 0); + assert(CopyAssign::alive == 1); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1).value == 42); + assert(CopyAssign::alive == 2); + assert(CopyAssign::copy_construct == 1); + assert(CopyAssign::move_construct == 1); + assert(CopyAssign::copy_assign == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + // Test that if copy construction throws then original value is + // unchanged. + using V = std::variant<int, CopyThrows, std::string>; + V v1(std::in_place_type<std::string>, "hello"); + V v2(std::in_place_type<CopyThrows>); + try { + v1 = v2; + assert(false); + } catch (...) { /* ... */ + } + assert(v1.index() == 2); + assert(std::get<2>(v1) == "hello"); + } + { + // Test that if move construction throws then the variant is left + // valueless by exception. + using V = std::variant<int, MoveThrows, std::string>; + V v1(std::in_place_type<std::string>, "hello"); + V v2(std::in_place_type<MoveThrows>); + assert(MoveThrows::alive == 1); + try { + v1 = v2; + assert(false); + } catch (...) { /* ... */ + } + assert(v1.valueless_by_exception()); + assert(v2.index() == 1); + assert(MoveThrows::alive == 1); + } + { + using V = std::variant<int, CopyThrows, std::string>; + V v1(std::in_place_type<CopyThrows>); + V v2(std::in_place_type<std::string>, "hello"); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 2); + assert(std::get<2>(v1) == "hello"); + assert(v2.index() == 2); + assert(std::get<2>(v2) == "hello"); + } + { + using V = std::variant<int, MoveThrows, std::string>; + V v1(std::in_place_type<MoveThrows>); + V v2(std::in_place_type<std::string>, "hello"); + V &vref = (v1 = v2); + assert(&vref == &v1); + assert(v1.index() == 2); + assert(std::get<2>(v1) == "hello"); + assert(v2.index() == 2); + assert(std::get<2>(v2) == "hello"); + } +#endif +} + + +int main() { + test_copy_assignment_empty_empty(); + test_copy_assignment_non_empty_empty(); + test_copy_assignment_empty_non_empty(); + test_copy_assignment_same_index(); + test_copy_assignment_different_index(); + test_copy_assignment_sfinae(); + test_copy_assignment_not_noexcept(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp new file mode 100644 index 000000000000..232d77c882eb --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp @@ -0,0 +1,319 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// variant& operator=(variant&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <utility> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +struct NoCopy { + NoCopy(const NoCopy &) = delete; + NoCopy &operator=(const NoCopy &) = default; +}; + +struct CopyOnly { + CopyOnly(const CopyOnly &) = default; + CopyOnly(CopyOnly &&) = delete; + CopyOnly &operator=(const CopyOnly &) = default; + CopyOnly &operator=(CopyOnly &&) = delete; +}; + +struct MoveOnly { + MoveOnly(const MoveOnly &) = delete; + MoveOnly(MoveOnly &&) = default; + MoveOnly &operator=(const MoveOnly &) = delete; + MoveOnly &operator=(MoveOnly &&) = default; +}; + +struct MoveOnlyNT { + MoveOnlyNT(const MoveOnlyNT &) = delete; + MoveOnlyNT(MoveOnlyNT &&) {} + MoveOnlyNT &operator=(const MoveOnlyNT &) = delete; + MoveOnlyNT &operator=(MoveOnlyNT &&) = default; +}; + +struct MoveOnlyOddNothrow { + MoveOnlyOddNothrow(MoveOnlyOddNothrow &&) noexcept(false) {} + MoveOnlyOddNothrow(const MoveOnlyOddNothrow &) = delete; + MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow &&) noexcept = default; + MoveOnlyOddNothrow &operator=(const MoveOnlyOddNothrow &) = delete; +}; + +struct MoveAssignOnly { + MoveAssignOnly(MoveAssignOnly &&) = delete; + MoveAssignOnly &operator=(MoveAssignOnly &&) = default; +}; + +struct MoveAssign { + static int move_construct; + static int move_assign; + static void reset() { move_construct = move_assign = 0; } + MoveAssign(int v) : value(v) {} + MoveAssign(MoveAssign &&o) : value(o.value) { + ++move_construct; + o.value = -1; + } + MoveAssign &operator=(MoveAssign &&o) { + value = o.value; + ++move_assign; + o.value = -1; + return *this; + } + int value; +}; + +int MoveAssign::move_construct = 0; +int MoveAssign::move_assign = 0; + +void test_move_assignment_noexcept() { + { + using V = std::variant<int>; + static_assert(std::is_nothrow_move_assignable<V>::value, ""); + } + { + using V = std::variant<MoveOnly>; + static_assert(std::is_nothrow_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, long>; + static_assert(std::is_nothrow_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(std::is_nothrow_move_assignable<V>::value, ""); + } + { + using V = std::variant<MoveOnlyNT>; + static_assert(!std::is_nothrow_move_assignable<V>::value, ""); + } + { + using V = std::variant<MoveOnlyOddNothrow>; + static_assert(!std::is_nothrow_move_assignable<V>::value, ""); + } +} + +void test_move_assignment_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_move_assignable<V>::value, ""); + } + { + // variant only provides move assignment when both the move constructor + // and move assignment operator are well formed. + using V = std::variant<int, CopyOnly>; + static_assert(!std::is_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, NoCopy>; + static_assert(!std::is_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(std::is_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(std::is_move_assignable<V>::value, ""); + } + { + // variant only provides move assignment when the types also provide + // a move constructor. + using V = std::variant<int, MoveAssignOnly>; + static_assert(!std::is_move_assignable<V>::value, ""); + } +} + +void test_move_assignment_empty_empty() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, long, MET>; + V v1(std::in_place_index<0>); + makeEmpty(v1); + V v2(std::in_place_index<0>); + makeEmpty(v2); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } +#endif +} + +void test_move_assignment_non_empty_empty() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET>; + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>); + makeEmpty(v2); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_index<2>, "hello"); + V v2(std::in_place_index<0>); + makeEmpty(v2); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } +#endif +} + +void test_move_assignment_empty_non_empty() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET>; + V v1(std::in_place_index<0>); + makeEmpty(v1); + V v2(std::in_place_index<0>, 42); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 0); + assert(std::get<0>(v1) == 42); + } + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_index<0>); + makeEmpty(v1); + V v2(std::in_place_type<std::string>, "hello"); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 2); + assert(std::get<2>(v1) == "hello"); + } +#endif +} + +void test_move_assignment_same_index() { + { + using V = std::variant<int>; + V v1(43); + V v2(42); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 0); + assert(std::get<0>(v1) == 42); + } + { + using V = std::variant<int, long, unsigned>; + V v1(43l); + V v2(42l); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1) == 42); + } + { + using V = std::variant<int, MoveAssign, unsigned>; + V v1(std::in_place_type<MoveAssign>, 43); + V v2(std::in_place_type<MoveAssign>, 42); + MoveAssign::reset(); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1).value == 42); + assert(MoveAssign::move_construct == 0); + assert(MoveAssign::move_assign == 1); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_type<MET>); + MET &mref = std::get<1>(v1); + V v2(std::in_place_type<MET>); + try { + v1 = std::move(v2); + assert(false); + } catch (...) { + } + assert(v1.index() == 1); + assert(&std::get<1>(v1) == &mref); + } +#endif +} + +void test_move_assignment_different_index() { + { + using V = std::variant<int, long, unsigned>; + V v1(43); + V v2(42l); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1) == 42); + } + { + using V = std::variant<int, MoveAssign, unsigned>; + V v1(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<MoveAssign>, 42); + MoveAssign::reset(); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 1); + assert(std::get<1>(v1).value == 42); + assert(MoveAssign::move_construct == 1); + assert(MoveAssign::move_assign == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + using MET = MakeEmptyT; + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_type<int>); + V v2(std::in_place_type<MET>); + try { + v1 = std::move(v2); + assert(false); + } catch (...) { + } + assert(v1.valueless_by_exception()); + assert(v1.index() == std::variant_npos); + } + { + using V = std::variant<int, MET, std::string>; + V v1(std::in_place_type<MET>); + V v2(std::in_place_type<std::string>, "hello"); + V &vref = (v1 = std::move(v2)); + assert(&vref == &v1); + assert(v1.index() == 2); + assert(std::get<2>(v1) == "hello"); + } +#endif +} + +int main() { + test_move_assignment_empty_empty(); + test_move_assignment_non_empty_empty(); + test_move_assignment_empty_non_empty(); + test_move_assignment_same_index(); + test_move_assignment_different_index(); + test_move_assignment_sfinae(); + test_move_assignment_noexcept(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp new file mode 100644 index 000000000000..d33ea0bd3f4e --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -0,0 +1,112 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <class T> constexpr variant(T&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +struct Dummy { + Dummy() = default; +}; + +struct ThrowsT { + ThrowsT(int) noexcept(false) {} +}; + +struct NoThrowT { + NoThrowT(int) noexcept(true) {} +}; + +void test_T_ctor_noexcept() { + { + using V = std::variant<Dummy, NoThrowT>; + static_assert(std::is_nothrow_constructible<V, int>::value, ""); + } + { + using V = std::variant<Dummy, ThrowsT>; + static_assert(!std::is_nothrow_constructible<V, int>::value, ""); + } +} + +void test_T_ctor_sfinae() { + { + using V = std::variant<long, unsigned>; + static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + } + { + using V = std::variant<std::string, std::string>; + static_assert(!std::is_constructible<V, const char *>::value, "ambiguous"); + } + { + using V = std::variant<std::string, void *>; + static_assert(!std::is_constructible<V, int>::value, + "no matching constructor"); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, int &&>; + static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + } + { + using V = std::variant<int, const int &>; + static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + } +#endif +} + +void test_T_ctor_basic() { + { + constexpr std::variant<int> v(42); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 42, ""); + } + { + constexpr std::variant<int, long> v(42l); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<const int &, int &&, long>; + static_assert(std::is_convertible<int &, V>::value, "must be implicit"); + int x = 42; + V v(x); + assert(v.index() == 0); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<const int &, int &&, long>; + static_assert(std::is_convertible<int, V>::value, "must be implicit"); + int x = 42; + V v(std::move(x)); + assert(v.index() == 1); + assert(&std::get<1>(v) == &x); + } +#endif +} + +int main() { + test_T_ctor_basic(); + test_T_ctor_noexcept(); + test_T_ctor_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp new file mode 100644 index 000000000000..18216c6da923 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -0,0 +1,159 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// variant(variant const&); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NonT { + NonT(int v) : value(v) {} + NonT(const NonT &o) : value(o.value) {} + int value; +}; +static_assert(!std::is_trivially_copy_constructible<NonT>::value, ""); + +struct NoCopy { + NoCopy(const NoCopy &) = delete; +}; + +struct MoveOnly { + MoveOnly(const MoveOnly &) = delete; + MoveOnly(MoveOnly &&) = default; +}; + +struct MoveOnlyNT { + MoveOnlyNT(const MoveOnlyNT &) = delete; + MoveOnlyNT(MoveOnlyNT &&) {} +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct MakeEmptyT { + static int alive; + MakeEmptyT() { ++alive; } + MakeEmptyT(const MakeEmptyT &) { + ++alive; + // Don't throw from the copy constructor since variant's assignment + // operator performs a copy before committing to the assignment. + } + MakeEmptyT(MakeEmptyT &&) { throw 42; } + MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } + ~MakeEmptyT() { --alive; } +}; + +int MakeEmptyT::alive = 0; + +template <class Variant> void makeEmpty(Variant &v) { + Variant v2(std::in_place_type<MakeEmptyT>); + try { + v = v2; + assert(false); + } catch (...) { + assert(v.valueless_by_exception()); + } +} +#endif // TEST_HAS_NO_EXCEPTIONS + +void test_copy_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, NoCopy>; + static_assert(!std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(!std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(!std::is_copy_constructible<V>::value, ""); + } +} + +void test_copy_ctor_basic() { + { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = v; + assert(v2.index() == 0); + assert(std::get<0>(v2) == 42); + } + { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = v; + assert(v2.index() == 1); + assert(std::get<1>(v2) == 42); + } + { + std::variant<NonT> v(std::in_place_index<0>, 42); + assert(v.index() == 0); + std::variant<NonT> v2(v); + assert(v2.index() == 0); + assert(std::get<0>(v2).value == 42); + } + { + std::variant<int, NonT> v(std::in_place_index<1>, 42); + assert(v.index() == 1); + std::variant<int, NonT> v2(v); + assert(v2.index() == 1); + assert(std::get<1>(v2).value == 42); + } +} + +void test_copy_ctor_valueless_by_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + const V &cv1 = v1; + V v(cv1); + assert(v.valueless_by_exception()); +#endif +} + +template <size_t Idx> +constexpr bool test_constexpr_copy_ctor_extension_imp( + std::variant<long, void*, const int> const& v) +{ + auto v2 = v; + return v2.index() == v.index() && + v2.index() == Idx && + std::get<Idx>(v2) == std::get<Idx>(v); +} + +void test_constexpr_copy_ctor_extension() { +#ifdef _LIBCPP_VERSION + using V = std::variant<long, void*, const int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), ""); + static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), ""); + static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), ""); +#endif +} + +int main() { + test_copy_ctor_basic(); + test_copy_ctor_valueless_by_exception(); + test_copy_ctor_sfinae(); + test_constexpr_copy_ctor_extension(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp new file mode 100644 index 000000000000..a4a86ff6c1ca --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp @@ -0,0 +1,112 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// constexpr variant() noexcept(see below); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +struct NonDefaultConstructible { + NonDefaultConstructible(int) {} +}; + +struct NotNoexcept { + NotNoexcept() noexcept(false) {} +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct DefaultCtorThrows { + DefaultCtorThrows() { throw 42; } +}; +#endif + +void test_default_ctor_sfinae() { + { + using V = std::variant<std::monostate, int>; + static_assert(std::is_default_constructible<V>::value, ""); + } + { + using V = std::variant<NonDefaultConstructible, int>; + static_assert(!std::is_default_constructible<V>::value, ""); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &, int>; + static_assert(!std::is_default_constructible<V>::value, ""); + } +#endif +} + +void test_default_ctor_noexcept() { + { + using V = std::variant<int>; + static_assert(std::is_nothrow_default_constructible<V>::value, ""); + } + { + using V = std::variant<NotNoexcept>; + static_assert(!std::is_nothrow_default_constructible<V>::value, ""); + } +} + +void test_default_ctor_throws() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<DefaultCtorThrows, int>; + try { + V v; + assert(false); + } catch (const int &ex) { + assert(ex == 42); + } catch (...) { + assert(false); + } +#endif +} + +void test_default_ctor_basic() { + { + std::variant<int> v; + assert(v.index() == 0); + assert(std::get<0>(v) == 0); + } + { + std::variant<int, long> v; + assert(v.index() == 0); + assert(std::get<0>(v) == 0); + } + { + using V = std::variant<int, long>; + constexpr V v; + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 0, ""); + } + { + using V = std::variant<int, long>; + constexpr V v; + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 0, ""); + } +} + +int main() { + test_default_ctor_basic(); + test_default_ctor_sfinae(); + test_default_ctor_noexcept(); + test_default_ctor_throws(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp new file mode 100644 index 000000000000..18115722f8d1 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp @@ -0,0 +1,103 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <size_t I, class ...Args> +// constexpr explicit variant(in_place_index_t<I>, Args&&...); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +void test_ctor_sfinae() { + { + using V = std::variant<int>; + static_assert( + std::is_constructible<V, std::in_place_index_t<0>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, int>(), ""); + } + { + using V = std::variant<int, long, long long>; + static_assert( + std::is_constructible<V, std::in_place_index_t<1>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<1>, int>(), ""); + } + { + using V = std::variant<int, long, int *>; + static_assert( + std::is_constructible<V, std::in_place_index_t<2>, int *>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<2>, int *>(), ""); + } + { // args not convertible to type + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<0>, int *>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, int *>(), ""); + } + { // index not in variant + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<3>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<3>, int>(), ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<int> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 42, ""); + } + { + constexpr std::variant<int, long, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + constexpr std::variant<int, const int, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_index<0>, x); + assert(v.index() == 0); + assert(std::get<0>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_index<1>, x); + assert(v.index() == 1); + assert(std::get<1>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_index<2>, x); + assert(v.index() == 2); + assert(std::get<2>(v) == x); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp new file mode 100644 index 000000000000..608cdf9d6efb --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp @@ -0,0 +1,103 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <size_t I, class Up, class ...Args> +// constexpr explicit +// variant(in_place_index_t<I>, initializer_list<Up>, Args&&...); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +struct InitList { + std::size_t size; + constexpr InitList(std::initializer_list<int> il) : size(il.size()) {} +}; + +struct InitListArg { + std::size_t size; + int value; + constexpr InitListArg(std::initializer_list<int> il, int v) + : size(il.size()), value(v) {} +}; + +void test_ctor_sfinae() { + using IL = std::initializer_list<int>; + { // just init list + using V = std::variant<InitList, InitListArg, int>; + static_assert(std::is_constructible<V, std::in_place_index_t<0>, IL>::value, + ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, IL>(), ""); + } + { // too many arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<0>, IL, int>::value, + ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, IL, int>(), + ""); + } + { // too few arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<1>, IL>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<1>, IL>(), ""); + } + { // init list and arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + std::is_constructible<V, std::in_place_index_t<1>, IL, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<1>, IL, int>(), + ""); + } + { // not constructible from arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<2>, IL>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<2>, IL>(), ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<InitList, InitListArg, InitList> v( + std::in_place_index<0>, {1, 2, 3}); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v).size == 3, ""); + } + { + constexpr std::variant<InitList, InitListArg, InitList> v( + std::in_place_index<2>, {1, 2, 3}); + static_assert(v.index() == 2, ""); + static_assert(std::get<2>(v).size == 3, ""); + } + { + constexpr std::variant<InitList, InitListArg, InitListArg> v( + std::in_place_index<1>, {1, 2, 3, 4}, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v).size == 4, ""); + static_assert(std::get<1>(v).value == 42, ""); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp new file mode 100644 index 000000000000..a023f02bad6e --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <class Tp, class ...Args> +// constexpr explicit variant(in_place_type_t<Tp>, Args&&...); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +void test_ctor_sfinae() { + { + using V = std::variant<int>; + static_assert( + std::is_constructible<V, std::in_place_type_t<int>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, int>(), ""); + } + { + using V = std::variant<int, long, long long>; + static_assert( + std::is_constructible<V, std::in_place_type_t<long>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<long>, int>(), ""); + } + { + using V = std::variant<int, long, int *>; + static_assert( + std::is_constructible<V, std::in_place_type_t<int *>, int *>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<int *>, int *>(), + ""); + } + { // duplicate type + using V = std::variant<int, long, int>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<int>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, int>(), ""); + } + { // args not convertible to type + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<int>, int *>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, int *>(), ""); + } + { // type not in variant + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<long long>, int>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<long long>, int>(), + ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<int> v(std::in_place_type<int>, 42); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 42, ""); + } + { + constexpr std::variant<int, long> v(std::in_place_type<long>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + constexpr std::variant<int, const int, long> v( + std::in_place_type<const int>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_type<const int>, x); + assert(v.index() == 0); + assert(std::get<0>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_type<volatile int>, x); + assert(v.index() == 1); + assert(std::get<1>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_type<int>, x); + assert(v.index() == 2); + assert(std::get<2>(v) == x); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp new file mode 100644 index 000000000000..e151572c4666 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp @@ -0,0 +1,110 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <class Tp, class Up, class ...Args> +// constexpr explicit +// variant(in_place_type_t<Tp>, initializer_list<Up>, Args&&...); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +struct InitList { + std::size_t size; + constexpr InitList(std::initializer_list<int> il) : size(il.size()) {} +}; + +struct InitListArg { + std::size_t size; + int value; + constexpr InitListArg(std::initializer_list<int> il, int v) + : size(il.size()), value(v) {} +}; + +void test_ctor_sfinae() { + using IL = std::initializer_list<int>; + { // just init list + using V = std::variant<InitList, InitListArg, int>; + static_assert( + std::is_constructible<V, std::in_place_type_t<InitList>, IL>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<InitList>, IL>(), + ""); + } + { // too many arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert(!std::is_constructible<V, std::in_place_type_t<InitList>, IL, + int>::value, + ""); + static_assert( + !test_convertible<V, std::in_place_type_t<InitList>, IL, int>(), ""); + } + { // too few arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<InitListArg>, IL>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<InitListArg>, IL>(), + ""); + } + { // init list and arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert(std::is_constructible<V, std::in_place_type_t<InitListArg>, + IL, int>::value, + ""); + static_assert( + !test_convertible<V, std::in_place_type_t<InitListArg>, IL, int>(), ""); + } + { // not constructible from arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<int>, IL>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, IL>(), ""); + } + { // duplicate types in variant + using V = std::variant<InitListArg, InitListArg, int>; + static_assert(!std::is_constructible<V, std::in_place_type_t<InitListArg>, + IL, int>::value, + ""); + static_assert( + !test_convertible<V, std::in_place_type_t<InitListArg>, IL, int>(), ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<InitList, InitListArg> v( + std::in_place_type<InitList>, {1, 2, 3}); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v).size == 3, ""); + } + { + constexpr std::variant<InitList, InitListArg> v( + std::in_place_type<InitListArg>, {1, 2, 3, 4}, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v).size == 4, ""); + static_assert(std::get<1>(v).value == 42, ""); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp new file mode 100644 index 000000000000..66f67fe8d3f2 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -0,0 +1,197 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// variant(variant&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct ThrowsMove { + ThrowsMove(ThrowsMove &&) noexcept(false) {} +}; + +struct NoCopy { + NoCopy(const NoCopy &) = delete; +}; + +struct MoveOnly { + int value; + MoveOnly(int v) : value(v) {} + MoveOnly(const MoveOnly &) = delete; + MoveOnly(MoveOnly &&) = default; +}; + +struct MoveOnlyNT { + int value; + MoveOnlyNT(int v) : value(v) {} + MoveOnlyNT(const MoveOnlyNT &) = delete; + MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; } +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct MakeEmptyT { + static int alive; + MakeEmptyT() { ++alive; } + MakeEmptyT(const MakeEmptyT &) { + ++alive; + // Don't throw from the copy constructor since variant's assignment + // operator performs a copy before committing to the assignment. + } + MakeEmptyT(MakeEmptyT &&) { throw 42; } + MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } + ~MakeEmptyT() { --alive; } +}; + +int MakeEmptyT::alive = 0; + +template <class Variant> void makeEmpty(Variant &v) { + Variant v2(std::in_place_type<MakeEmptyT>); + try { + v = v2; + assert(false); + } catch (...) { + assert(v.valueless_by_exception()); + } +} +#endif // TEST_HAS_NO_EXCEPTIONS + +void test_move_noexcept() { + { + using V = std::variant<int, long>; + static_assert(std::is_nothrow_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(std::is_nothrow_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(!std::is_nothrow_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, ThrowsMove>; + static_assert(!std::is_nothrow_move_constructible<V>::value, ""); + } +} + +void test_move_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, NoCopy>; + static_assert(!std::is_move_constructible<V>::value, ""); + } +} + +void test_move_ctor_basic() { + { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = std::move(v); + assert(v2.index() == 0); + assert(std::get<0>(v2) == 42); + } + { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = std::move(v); + assert(v2.index() == 1); + assert(std::get<1>(v2) == 42); + } + { + std::variant<MoveOnly> v(std::in_place_index<0>, 42); + assert(v.index() == 0); + std::variant<MoveOnly> v2(std::move(v)); + assert(v2.index() == 0); + assert(std::get<0>(v2).value == 42); + } + { + std::variant<int, MoveOnly> v(std::in_place_index<1>, 42); + assert(v.index() == 1); + std::variant<int, MoveOnly> v2(std::move(v)); + assert(v2.index() == 1); + assert(std::get<1>(v2).value == 42); + } + { + std::variant<MoveOnlyNT> v(std::in_place_index<0>, 42); + assert(v.index() == 0); + std::variant<MoveOnlyNT> v2(std::move(v)); + assert(v2.index() == 0); + assert(std::get<0>(v).value == -1); + assert(std::get<0>(v2).value == 42); + } + { + std::variant<int, MoveOnlyNT> v(std::in_place_index<1>, 42); + assert(v.index() == 1); + std::variant<int, MoveOnlyNT> v2(std::move(v)); + assert(v2.index() == 1); + assert(std::get<1>(v).value == -1); + assert(std::get<1>(v2).value == 42); + } +} + +void test_move_ctor_valueless_by_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V v(std::move(v1)); + assert(v.valueless_by_exception()); +#endif +} + +template <size_t Idx> +constexpr bool test_constexpr_ctor_extension_imp( + std::variant<long, void*, const int> const& v) +{ + auto copy = v; + auto v2 = std::move(copy); + return v2.index() == v.index() && + v2.index() == Idx && + std::get<Idx>(v2) == std::get<Idx>(v); +} + +void test_constexpr_move_ctor_extension() { +#ifdef _LIBCPP_VERSION + using V = std::variant<long, void*, const int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_move_constructible<V>::value, ""); + static_assert(test_constexpr_ctor_extension_imp<0>(V(42l)), ""); + static_assert(test_constexpr_ctor_extension_imp<1>(V(nullptr)), ""); + static_assert(test_constexpr_ctor_extension_imp<2>(V(101)), ""); +#endif +} + +int main() { + test_move_ctor_basic(); + test_move_ctor_valueless_by_exception(); + test_move_noexcept(); + test_move_ctor_sfinae(); + test_constexpr_move_ctor_extension(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp b/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp new file mode 100644 index 000000000000..7299394ee7bb --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp @@ -0,0 +1,75 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// ~variant(); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NonTDtor { + static int count; + NonTDtor() = default; + ~NonTDtor() { ++count; } +}; +int NonTDtor::count = 0; +static_assert(!std::is_trivially_destructible<NonTDtor>::value, ""); + +struct NonTDtor1 { + static int count; + NonTDtor1() = default; + ~NonTDtor1() { ++count; } +}; +int NonTDtor1::count = 0; +static_assert(!std::is_trivially_destructible<NonTDtor1>::value, ""); + +struct TDtor { + TDtor(const TDtor &) {} // non-trivial copy + ~TDtor() = default; +}; +static_assert(!std::is_trivially_copy_constructible<TDtor>::value, ""); +static_assert(std::is_trivially_destructible<TDtor>::value, ""); + +int main() { + { + using V = std::variant<int, long, TDtor>; + static_assert(std::is_trivially_destructible<V>::value, ""); + } + { + using V = std::variant<NonTDtor, int, NonTDtor1>; + static_assert(!std::is_trivially_destructible<V>::value, ""); + { + V v(std::in_place_index<0>); + assert(NonTDtor::count == 0); + assert(NonTDtor1::count == 0); + } + assert(NonTDtor::count == 1); + assert(NonTDtor1::count == 0); + NonTDtor::count = 0; + { V v(std::in_place_index<1>); } + assert(NonTDtor::count == 0); + assert(NonTDtor1::count == 0); + { + V v(std::in_place_index<2>); + assert(NonTDtor::count == 0); + assert(NonTDtor1::count == 0); + } + assert(NonTDtor::count == 0); + assert(NonTDtor1::count == 1); + } +} diff --git a/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp new file mode 100644 index 000000000000..8f694cfd5eda --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp @@ -0,0 +1,137 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <size_t I, class ...Args> void emplace(Args&&... args); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "archetypes.hpp" +#include "test_convertible.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +template <class Var, size_t I, class... Args> +constexpr auto test_emplace_exists_imp(int) -> decltype( + std::declval<Var>().template emplace<I>(std::declval<Args>()...), true) { + return true; +} + +template <class, size_t, class...> +constexpr auto test_emplace_exists_imp(long) -> bool { + return false; +} + +template <class Var, size_t I, class... Args> constexpr bool emplace_exists() { + return test_emplace_exists_imp<Var, I, Args...>(0); +} + +void test_emplace_sfinae() { + { + using V = std::variant<int, void *, const void *, TestTypes::NoCtors>; + static_assert(emplace_exists<V, 0>(), ""); + static_assert(emplace_exists<V, 0, int>(), ""); + static_assert(!emplace_exists<V, 0, decltype(nullptr)>(), + "cannot construct"); + static_assert(emplace_exists<V, 1, decltype(nullptr)>(), ""); + static_assert(emplace_exists<V, 1, int *>(), ""); + static_assert(!emplace_exists<V, 1, const int *>(), ""); + static_assert(!emplace_exists<V, 1, int>(), "cannot construct"); + static_assert(emplace_exists<V, 2, const int *>(), ""); + static_assert(emplace_exists<V, 2, int *>(), ""); + static_assert(!emplace_exists<V, 3>(), "cannot construct"); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, int &, const int &, int &&, TestTypes::NoCtors>; + static_assert(emplace_exists<V, 0>(), ""); + static_assert(emplace_exists<V, 0, int>(), ""); + static_assert(emplace_exists<V, 0, long long>(), ""); + static_assert(!emplace_exists<V, 0, int, int>(), "too many args"); + static_assert(emplace_exists<V, 1, int &>(), ""); + static_assert(!emplace_exists<V, 1>(), "cannot default construct ref"); + static_assert(!emplace_exists<V, 1, const int &>(), "cannot bind ref"); + static_assert(!emplace_exists<V, 1, int &&>(), "cannot bind ref"); + static_assert(emplace_exists<V, 2, int &>(), ""); + static_assert(emplace_exists<V, 2, const int &>(), ""); + static_assert(emplace_exists<V, 2, int &&>(), ""); + static_assert(!emplace_exists<V, 2, void *>(), + "not constructible from void*"); + static_assert(emplace_exists<V, 3, int>(), ""); + static_assert(!emplace_exists<V, 3, int &>(), "cannot bind ref"); + static_assert(!emplace_exists<V, 3, const int &>(), "cannot bind ref"); + static_assert(!emplace_exists<V, 3, const int &&>(), "cannot bind ref"); + static_assert(!emplace_exists<V, 4>(), "no ctors"); + } +#endif +} + +void test_basic() { + { + using V = std::variant<int>; + V v(42); + v.emplace<0>(); + assert(std::get<0>(v) == 0); + v.emplace<0>(42); + assert(std::get<0>(v) == 42); + } + { + using V = + std::variant<int, long, const void *, TestTypes::NoCtors, std::string>; + const int x = 100; + V v(std::in_place_index<0>, -1); + // default emplace a value + v.emplace<1>(); + assert(std::get<1>(v) == 0); + v.emplace<2>(&x); + assert(std::get<2>(v) == &x); + // emplace with multiple args + v.emplace<4>(3, 'a'); + assert(std::get<4>(v) == "aaa"); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors, + std::string>; + const int x = 100; + int y = 42; + int z = 43; + V v(std::in_place_index<0>, -1); + // default emplace a value + v.emplace<1>(); + assert(std::get<1>(v) == 0); + // emplace a reference + v.emplace<2>(x); + assert(&std::get<2>(v) == &x); + // emplace an rvalue reference + v.emplace<3>(std::move(y)); + assert(&std::get<3>(v) == &y); + // re-emplace a new reference over the active member + v.emplace<3>(std::move(z)); + assert(&std::get<3>(v) == &z); + // emplace with multiple args + v.emplace<5>(3, 'a'); + assert(std::get<5>(v) == "aaa"); + } +#endif +} + +int main() { + test_basic(); + test_emplace_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp new file mode 100644 index 000000000000..f466b160cb4f --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp @@ -0,0 +1,85 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <size_t I, class U, class ...Args> +// void emplace(initializer_list<U> il,Args&&... args); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "archetypes.hpp" +#include "test_convertible.hpp" +#include "test_macros.h" + +struct InitList { + std::size_t size; + constexpr InitList(std::initializer_list<int> il) : size(il.size()) {} +}; + +struct InitListArg { + std::size_t size; + int value; + constexpr InitListArg(std::initializer_list<int> il, int v) + : size(il.size()), value(v) {} +}; + +template <class Var, size_t I, class... Args> +constexpr auto test_emplace_exists_imp(int) -> decltype( + std::declval<Var>().template emplace<I>(std::declval<Args>()...), true) { + return true; +} + +template <class, size_t, class...> +constexpr auto test_emplace_exists_imp(long) -> bool { + return false; +} + +template <class Var, size_t I, class... Args> constexpr bool emplace_exists() { + return test_emplace_exists_imp<Var, I, Args...>(0); +} + +void test_emplace_sfinae() { + using V = + std::variant<int, TestTypes::NoCtors, InitList, InitListArg, long, long>; + using IL = std::initializer_list<int>; + static_assert(!emplace_exists<V, 1, IL>(), "no such constructor"); + static_assert(emplace_exists<V, 2, IL>(), ""); + static_assert(!emplace_exists<V, 2, int>(), "args don't match"); + static_assert(!emplace_exists<V, 2, IL, int>(), "too many args"); + static_assert(emplace_exists<V, 3, IL, int>(), ""); + static_assert(!emplace_exists<V, 3, int>(), "args don't match"); + static_assert(!emplace_exists<V, 3, IL>(), "too few args"); + static_assert(!emplace_exists<V, 3, IL, int, int>(), "too many args"); +} + +void test_basic() { + using V = std::variant<int, InitList, InitListArg, TestTypes::NoCtors>; + V v; + v.emplace<1>({1, 2, 3}); + assert(std::get<1>(v).size == 3); + v.emplace<2>({1, 2, 3, 4}, 42); + assert(std::get<2>(v).size == 4); + assert(std::get<2>(v).value == 42); + v.emplace<1>({1}); + assert(std::get<1>(v).size == 1); +} + +int main() { + test_basic(); + test_emplace_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp new file mode 100644 index 000000000000..4ca2cc4803e3 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp @@ -0,0 +1,138 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <class T, class ...Args> void emplace(Args&&... args); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "archetypes.hpp" +#include "test_convertible.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +template <class Var, class T, class... Args> +constexpr auto test_emplace_exists_imp(int) -> decltype( + std::declval<Var>().template emplace<T>(std::declval<Args>()...), true) { + return true; +} + +template <class, class, class...> +constexpr auto test_emplace_exists_imp(long) -> bool { + return false; +} + +template <class... Args> constexpr bool emplace_exists() { + return test_emplace_exists_imp<Args...>(0); +} + +void test_emplace_sfinae() { + { + using V = std::variant<int, void *, const void *, TestTypes::NoCtors>; + static_assert(emplace_exists<V, int>(), ""); + static_assert(emplace_exists<V, int, int>(), ""); + static_assert(!emplace_exists<V, int, decltype(nullptr)>(), + "cannot construct"); + static_assert(emplace_exists<V, void *, decltype(nullptr)>(), ""); + static_assert(!emplace_exists<V, void *, int>(), "cannot construct"); + static_assert(emplace_exists<V, void *, int *>(), ""); + static_assert(!emplace_exists<V, void *, const int *>(), ""); + static_assert(emplace_exists<V, const void *, const int *>(), ""); + static_assert(emplace_exists<V, const void *, int *>(), ""); + static_assert(!emplace_exists<V, TestTypes::NoCtors>(), "cannot construct"); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + using V = std::variant<int, int &, const int &, int &&, long, long, + TestTypes::NoCtors>; + static_assert(emplace_exists<V, int>(), ""); + static_assert(emplace_exists<V, int, int>(), ""); + static_assert(emplace_exists<V, int, long long>(), ""); + static_assert(!emplace_exists<V, int, int, int>(), "too many args"); + static_assert(emplace_exists<V, int &, int &>(), ""); + static_assert(!emplace_exists<V, int &>(), "cannot default construct ref"); + static_assert(!emplace_exists<V, int &, const int &>(), "cannot bind ref"); + static_assert(!emplace_exists<V, int &, int &&>(), "cannot bind ref"); + static_assert(emplace_exists<V, const int &, int &>(), ""); + static_assert(emplace_exists<V, const int &, const int &>(), ""); + static_assert(emplace_exists<V, const int &, int &&>(), ""); + static_assert(!emplace_exists<V, const int &, void *>(), + "not constructible from void*"); + static_assert(emplace_exists<V, int &&, int>(), ""); + static_assert(!emplace_exists<V, int &&, int &>(), "cannot bind ref"); + static_assert(!emplace_exists<V, int &&, const int &>(), "cannot bind ref"); + static_assert(!emplace_exists<V, int &&, const int &&>(), "cannot bind ref"); + static_assert(!emplace_exists<V, long, long>(), "ambiguous"); + static_assert(!emplace_exists<V, TestTypes::NoCtors>(), + "cannot construct void"); +#endif +} + +void test_basic() { + { + using V = std::variant<int>; + V v(42); + v.emplace<int>(); + assert(std::get<0>(v) == 0); + v.emplace<int>(42); + assert(std::get<0>(v) == 42); + } + { + using V = + std::variant<int, long, const void *, TestTypes::NoCtors, std::string>; + const int x = 100; + V v(std::in_place_type<int>, -1); + // default emplace a value + v.emplace<long>(); + assert(std::get<1>(v) == 0); + v.emplace<const void *>(&x); + assert(std::get<2>(v) == &x); + // emplace with multiple args + v.emplace<std::string>(3, 'a'); + assert(std::get<4>(v) == "aaa"); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors, + std::string>; + const int x = 100; + int y = 42; + int z = 43; + V v(std::in_place_index<0>, -1); + // default emplace a value + v.emplace<long>(); + assert(std::get<long>(v) == 0); + // emplace a reference + v.emplace<const int &>(x); + assert(&std::get<const int &>(v) == &x); + // emplace an rvalue reference + v.emplace<int &&>(std::move(y)); + assert(&std::get<int &&>(v) == &y); + // re-emplace a new reference over the active member + v.emplace<int &&>(std::move(z)); + assert(&std::get<int &&>(v) == &z); + // emplace with multiple args + v.emplace<std::string>(3, 'a'); + assert(std::get<std::string>(v) == "aaa"); + } +#endif +} + +int main() { + test_basic(); + test_emplace_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp b/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp new file mode 100644 index 000000000000..b2be8ac5b3fd --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp @@ -0,0 +1,85 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// template <class T, class U, class ...Args> +// void emplace(initializer_list<U> il,Args&&... args); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "archetypes.hpp" +#include "test_convertible.hpp" +#include "test_macros.h" + +struct InitList { + std::size_t size; + constexpr InitList(std::initializer_list<int> il) : size(il.size()) {} +}; + +struct InitListArg { + std::size_t size; + int value; + constexpr InitListArg(std::initializer_list<int> il, int v) + : size(il.size()), value(v) {} +}; + +template <class Var, class T, class... Args> +constexpr auto test_emplace_exists_imp(int) -> decltype( + std::declval<Var>().template emplace<T>(std::declval<Args>()...), true) { + return true; +} + +template <class, class, class...> +constexpr auto test_emplace_exists_imp(long) -> bool { + return false; +} + +template <class... Args> constexpr bool emplace_exists() { + return test_emplace_exists_imp<Args...>(0); +} + +void test_emplace_sfinae() { + using V = + std::variant<int, TestTypes::NoCtors, InitList, InitListArg, long, long>; + using IL = std::initializer_list<int>; + static_assert(emplace_exists<V, InitList, IL>(), ""); + static_assert(!emplace_exists<V, InitList, int>(), "args don't match"); + static_assert(!emplace_exists<V, InitList, IL, int>(), "too many args"); + static_assert(emplace_exists<V, InitListArg, IL, int>(), ""); + static_assert(!emplace_exists<V, InitListArg, int>(), "args don't match"); + static_assert(!emplace_exists<V, InitListArg, IL>(), "too few args"); + static_assert(!emplace_exists<V, InitListArg, IL, int, int>(), + "too many args"); +} + +void test_basic() { + using V = std::variant<int, InitList, InitListArg, TestTypes::NoCtors>; + V v; + v.emplace<InitList>({1, 2, 3}); + assert(std::get<InitList>(v).size == 3); + v.emplace<InitListArg>({1, 2, 3, 4}, 42); + assert(std::get<InitListArg>(v).size == 4); + assert(std::get<InitListArg>(v).value == 42); + v.emplace<InitList>({1}); + assert(std::get<InitList>(v).size == 1); +} + +int main() { + test_basic(); + test_emplace_sfinae(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp b/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp new file mode 100644 index 000000000000..4b30188ce6ff --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp @@ -0,0 +1,58 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Clang 3.8 doesn't allow constexpr variables of non-literal type +// XFAIL: clang-3.8, apple-clang-7, apple-clang-8 + +// <variant> + +// template <class ...Types> class variant; + +// constexpr size_t index() const noexcept; + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "archetypes.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +int main() { + { + using V = std::variant<int, ConstexprTestTypes::NoCtors>; + constexpr V v; + static_assert(v.index() == 0, ""); + } + { + using V = std::variant<int, long>; + constexpr V v(std::in_place_index<1>); + static_assert(v.index() == 1, ""); + } + { + using V = std::variant<int, std::string>; + V v("abc"); + assert(v.index() == 1); + v = 42; + assert(v.index() == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<int, MakeEmptyT>; + V v; + assert(v.index() == 0); + makeEmpty(v); + assert(v.index() == std::variant_npos); + } +#endif +} diff --git a/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp b/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp new file mode 100644 index 000000000000..8546beb1319c --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp @@ -0,0 +1,51 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Clang 3.8 doesn't allow constexpr variables of non-literal type +// XFAIL: clang-3.8, apple-clang-7, apple-clang-8 + +// <variant> + +// template <class ...Types> class variant; + +// constexpr bool valueless_by_exception() const noexcept; + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "archetypes.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +int main() { + { + using V = std::variant<int, ConstexprTestTypes::NoCtors>; + constexpr V v; + static_assert(!v.valueless_by_exception(), ""); + } + { + using V = std::variant<int, long, std::string>; + const V v("abc"); + assert(!v.valueless_by_exception()); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<int, MakeEmptyT>; + V v; + assert(!v.valueless_by_exception()); + makeEmpty(v); + assert(v.valueless_by_exception()); + } +#endif +} diff --git a/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp b/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp new file mode 100644 index 000000000000..416c6b4e334d --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp @@ -0,0 +1,591 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// void swap(variant& rhs) noexcept(see below) + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +struct NotSwappable {}; +void swap(NotSwappable &, NotSwappable &) = delete; + +struct NotCopyable { + NotCopyable() = default; + NotCopyable(const NotCopyable &) = delete; + NotCopyable &operator=(const NotCopyable &) = delete; +}; + +struct NotCopyableWithSwap { + NotCopyableWithSwap() = default; + NotCopyableWithSwap(const NotCopyableWithSwap &) = delete; + NotCopyableWithSwap &operator=(const NotCopyableWithSwap &) = delete; +}; +void swap(NotCopyableWithSwap &, NotCopyableWithSwap) {} + +struct NotMoveAssignable { + NotMoveAssignable() = default; + NotMoveAssignable(NotMoveAssignable &&) = default; + NotMoveAssignable &operator=(NotMoveAssignable &&) = delete; +}; + +struct NotMoveAssignableWithSwap { + NotMoveAssignableWithSwap() = default; + NotMoveAssignableWithSwap(NotMoveAssignableWithSwap &&) = default; + NotMoveAssignableWithSwap &operator=(NotMoveAssignableWithSwap &&) = delete; +}; +void swap(NotMoveAssignableWithSwap &, NotMoveAssignableWithSwap &) noexcept {} + +template <bool Throws> void do_throw() {} + +template <> void do_throw<true>() { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw 42; +#else + std::abort(); +#endif +} + +template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign, + bool NT_Swap, bool EnableSwap = true> +struct NothrowTypeImp { + static int move_called; + static int move_assign_called; + static int swap_called; + static void reset() { move_called = move_assign_called = swap_called = 0; } + NothrowTypeImp() = default; + explicit NothrowTypeImp(int v) : value(v) {} + NothrowTypeImp(const NothrowTypeImp &o) noexcept(NT_Copy) : value(o.value) { + assert(false); + } // never called by test + NothrowTypeImp(NothrowTypeImp &&o) noexcept(NT_Move) : value(o.value) { + ++move_called; + do_throw<!NT_Move>(); + o.value = -1; + } + NothrowTypeImp &operator=(const NothrowTypeImp &) noexcept(NT_CopyAssign) { + assert(false); + return *this; + } // never called by the tests + NothrowTypeImp &operator=(NothrowTypeImp &&o) noexcept(NT_MoveAssign) { + ++move_assign_called; + do_throw<!NT_MoveAssign>(); + value = o.value; + o.value = -1; + return *this; + } + int value; +}; +template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign, + bool NT_Swap, bool EnableSwap> +int NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, NT_Swap, + EnableSwap>::move_called = 0; +template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign, + bool NT_Swap, bool EnableSwap> +int NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, NT_Swap, + EnableSwap>::move_assign_called = 0; +template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign, + bool NT_Swap, bool EnableSwap> +int NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, NT_Swap, + EnableSwap>::swap_called = 0; + +template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign, + bool NT_Swap> +void swap(NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, + NT_Swap, true> &lhs, + NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, + NT_Swap, true> &rhs) noexcept(NT_Swap) { + lhs.swap_called++; + do_throw<!NT_Swap>(); + int tmp = lhs.value; + lhs.value = rhs.value; + rhs.value = tmp; +} + +// throwing copy, nothrow move ctor/assign, no swap provided +using NothrowMoveable = NothrowTypeImp<false, true, false, true, false, false>; +// throwing copy and move assign, nothrow move ctor, no swap provided +using NothrowMoveCtor = NothrowTypeImp<false, true, false, false, false, false>; +// nothrow move ctor, throwing move assignment, swap provided +using NothrowMoveCtorWithThrowingSwap = + NothrowTypeImp<false, true, false, false, false, true>; +// throwing move ctor, nothrow move assignment, no swap provided +using ThrowingMoveCtor = + NothrowTypeImp<false, false, false, true, false, false>; +// throwing special members, nothrowing swap +using ThrowingTypeWithNothrowSwap = + NothrowTypeImp<false, false, false, false, true, true>; +using NothrowTypeWithThrowingSwap = + NothrowTypeImp<true, true, true, true, false, true>; +// throwing move assign with nothrow move and nothrow swap +using ThrowingMoveAssignNothrowMoveCtorWithSwap = + NothrowTypeImp<false, true, false, false, true, true>; +// throwing move assign with nothrow move but no swap. +using ThrowingMoveAssignNothrowMoveCtor = + NothrowTypeImp<false, true, false, false, false, false>; + +struct NonThrowingNonNoexceptType { + static int move_called; + static void reset() { move_called = 0; } + NonThrowingNonNoexceptType() = default; + NonThrowingNonNoexceptType(int v) : value(v) {} + NonThrowingNonNoexceptType(NonThrowingNonNoexceptType &&o) noexcept(false) + : value(o.value) { + ++move_called; + o.value = -1; + } + NonThrowingNonNoexceptType & + operator=(NonThrowingNonNoexceptType &&) noexcept(false) { + assert(false); // never called by the tests. + return *this; + } + int value; +}; +int NonThrowingNonNoexceptType::move_called = 0; + +struct ThrowsOnSecondMove { + int value; + int move_count; + ThrowsOnSecondMove(int v) : value(v), move_count(0) {} + ThrowsOnSecondMove(ThrowsOnSecondMove &&o) noexcept(false) + : value(o.value), move_count(o.move_count + 1) { + if (move_count == 2) + do_throw<true>(); + o.value = -1; + } + ThrowsOnSecondMove &operator=(ThrowsOnSecondMove &&) { + assert(false); // not called by test + return *this; + } +}; + +void test_swap_valueless_by_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, MakeEmptyT>; + { // both empty + V v1; + makeEmpty(v1); + V v2; + makeEmpty(v2); + assert(MakeEmptyT::alive == 0); + { // member swap + v1.swap(v2); + assert(v1.valueless_by_exception()); + assert(v2.valueless_by_exception()); + assert(MakeEmptyT::alive == 0); + } + { // non-member swap + swap(v1, v2); + assert(v1.valueless_by_exception()); + assert(v2.valueless_by_exception()); + assert(MakeEmptyT::alive == 0); + } + } + { // only one empty + V v1(42); + V v2; + makeEmpty(v2); + { // member swap + v1.swap(v2); + assert(v1.valueless_by_exception()); + assert(std::get<0>(v2) == 42); + // swap again + v2.swap(v1); + assert(v2.valueless_by_exception()); + assert(std::get<0>(v1) == 42); + } + { // non-member swap + swap(v1, v2); + assert(v1.valueless_by_exception()); + assert(std::get<0>(v2) == 42); + // swap again + swap(v1, v2); + assert(v2.valueless_by_exception()); + assert(std::get<0>(v1) == 42); + } + } +#endif +} + +void test_swap_same_alternative() { + { + using T = ThrowingTypeWithNothrowSwap; + using V = std::variant<T, int>; + T::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>, 100); + v1.swap(v2); + assert(T::swap_called == 1); + assert(std::get<0>(v1).value == 100); + assert(std::get<0>(v2).value == 42); + swap(v1, v2); + assert(T::swap_called == 2); + assert(std::get<0>(v1).value == 42); + assert(std::get<0>(v2).value == 100); + } + { + using T = NothrowMoveable; + using V = std::variant<T, int>; + T::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>, 100); + v1.swap(v2); + assert(T::swap_called == 0); + assert(T::move_called == 1); + assert(T::move_assign_called == 2); + assert(std::get<0>(v1).value == 100); + assert(std::get<0>(v2).value == 42); + T::reset(); + swap(v1, v2); + assert(T::swap_called == 0); + assert(T::move_called == 1); + assert(T::move_assign_called == 2); + assert(std::get<0>(v1).value == 42); + assert(std::get<0>(v2).value == 100); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using T = NothrowTypeWithThrowingSwap; + using V = std::variant<T, int>; + T::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + assert(T::swap_called == 1); + assert(T::move_called == 0); + assert(T::move_assign_called == 0); + assert(std::get<0>(v1).value == 42); + assert(std::get<0>(v2).value == 100); + } + { + using T = ThrowingMoveCtor; + using V = std::variant<T, int>; + T::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + assert(T::move_called == 1); // call threw + assert(T::move_assign_called == 0); + assert(std::get<0>(v1).value == + 42); // throw happened before v1 was moved from + assert(std::get<0>(v2).value == 100); + } + { + using T = ThrowingMoveAssignNothrowMoveCtor; + using V = std::variant<T, int>; + T::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<0>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + assert(T::move_called == 1); + assert(T::move_assign_called == 1); // call threw and didn't complete + assert(std::get<0>(v1).value == -1); // v1 was moved from + assert(std::get<0>(v2).value == 100); + } +#endif +} + +void test_swap_different_alternatives() { + { + using T = NothrowMoveCtorWithThrowingSwap; + using V = std::variant<T, int>; + T::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<1>, 100); + v1.swap(v2); + assert(T::swap_called == 0); + // The libc++ implementation double copies the argument, and not + // the variant swap is called on. + LIBCPP_ASSERT(T::move_called == 1); + assert(T::move_called <= 2); + assert(T::move_assign_called == 0); + assert(std::get<1>(v1) == 100); + assert(std::get<0>(v2).value == 42); + T::reset(); + swap(v1, v2); + assert(T::swap_called == 0); + LIBCPP_ASSERT(T::move_called == 2); + assert(T::move_called <= 2); + assert(T::move_assign_called == 0); + assert(std::get<0>(v1).value == 42); + assert(std::get<1>(v2) == 100); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using T1 = ThrowingTypeWithNothrowSwap; + using T2 = NonThrowingNonNoexceptType; + using V = std::variant<T1, T2>; + T1::reset(); + T2::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<1>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + assert(T1::swap_called == 0); + assert(T1::move_called == 1); // throws + assert(T1::move_assign_called == 0); + // FIXME: libc++ shouldn't move from T2 here. + LIBCPP_ASSERT(T2::move_called == 1); + assert(T2::move_called <= 1); + assert(std::get<0>(v1).value == 42); + if (T2::move_called != 0) + assert(v2.valueless_by_exception()); + else + assert(std::get<1>(v2).value == 100); + } + { + using T1 = NonThrowingNonNoexceptType; + using T2 = ThrowingTypeWithNothrowSwap; + using V = std::variant<T1, T2>; + T1::reset(); + T2::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<1>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + LIBCPP_ASSERT(T1::move_called == 0); + assert(T1::move_called <= 1); + assert(T2::swap_called == 0); + assert(T2::move_called == 1); // throws + assert(T2::move_assign_called == 0); + if (T1::move_called != 0) + assert(v1.valueless_by_exception()); + else + assert(std::get<0>(v1).value == 42); + assert(std::get<1>(v2).value == 100); + } +// FIXME: The tests below are just very libc++ specific +#ifdef _LIBCPP_VERSION + { + using T1 = ThrowsOnSecondMove; + using T2 = NonThrowingNonNoexceptType; + using V = std::variant<T1, T2>; + T2::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<1>, 100); + v1.swap(v2); + assert(T2::move_called == 2); + assert(std::get<1>(v1).value == 100); + assert(std::get<0>(v2).value == 42); + assert(std::get<0>(v2).move_count == 1); + } + { + using T1 = NonThrowingNonNoexceptType; + using T2 = ThrowsOnSecondMove; + using V = std::variant<T1, T2>; + T1::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<1>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + assert(T1::move_called == 1); + assert(v1.valueless_by_exception()); + assert(std::get<0>(v2).value == 42); + } +#endif +// testing libc++ extension. If either variant stores a nothrow move +// constructible type v1.swap(v2) provides the strong exception safety +// guarantee. +#ifdef _LIBCPP_VERSION + { + + using T1 = ThrowingTypeWithNothrowSwap; + using T2 = NothrowMoveable; + using V = std::variant<T1, T2>; + T1::reset(); + T2::reset(); + V v1(std::in_place_index<0>, 42); + V v2(std::in_place_index<1>, 100); + try { + v1.swap(v2); + assert(false); + } catch (int) { + } + assert(T1::swap_called == 0); + assert(T1::move_called == 1); + assert(T1::move_assign_called == 0); + assert(T2::swap_called == 0); + assert(T2::move_called == 2); + assert(T2::move_assign_called == 0); + assert(std::get<0>(v1).value == 42); + assert(std::get<1>(v2).value == 100); + // swap again, but call v2's swap. + T1::reset(); + T2::reset(); + try { + v2.swap(v1); + assert(false); + } catch (int) { + } + assert(T1::swap_called == 0); + assert(T1::move_called == 1); + assert(T1::move_assign_called == 0); + assert(T2::swap_called == 0); + assert(T2::move_called == 2); + assert(T2::move_assign_called == 0); + assert(std::get<0>(v1).value == 42); + assert(std::get<1>(v2).value == 100); + } +#endif // _LIBCPP_VERSION +#endif +} + +template <class Var> +constexpr auto has_swap_member_imp(int) + -> decltype(std::declval<Var &>().swap(std::declval<Var &>()), true) { + return true; +} + +template <class Var> constexpr auto has_swap_member_imp(long) -> bool { + return false; +} + +template <class Var> constexpr bool has_swap_member() { + return has_swap_member_imp<Var>(0); +} + +void test_swap_sfinae() { + { + // This variant type does not provide either a member or non-member swap + // but is still swappable via the generic swap algorithm, since the + // variant is move constructible and move assignable. + using V = std::variant<int, NotSwappable>; + LIBCPP_STATIC_ASSERT(!has_swap_member<V>()); + static_assert(std::is_swappable_v<V>, ""); + } + { + using V = std::variant<int, NotCopyable>; + LIBCPP_STATIC_ASSERT(!has_swap_member<V>(), ""); + static_assert(!std::is_swappable_v<V>, ""); + } + { + using V = std::variant<int, NotCopyableWithSwap>; + LIBCPP_STATIC_ASSERT(!has_swap_member<V>(), ""); + static_assert(!std::is_swappable_v<V>, ""); + } + { + using V = std::variant<int, NotMoveAssignable>; + LIBCPP_STATIC_ASSERT(!has_swap_member<V>(), ""); + static_assert(!std::is_swappable_v<V>, ""); + } +} + +void test_swap_noexcept() { + { + using V = std::variant<int, NothrowMoveable>; + static_assert(std::is_swappable_v<V> && has_swap_member<V>(), ""); + static_assert(std::is_nothrow_swappable_v<V>, ""); + // instantiate swap + V v1, v2; + v1.swap(v2); + swap(v1, v2); + } + { + using V = std::variant<int, NothrowMoveCtor>; + static_assert(std::is_swappable_v<V> && has_swap_member<V>(), ""); + static_assert(!std::is_nothrow_swappable_v<V>, ""); + // instantiate swap + V v1, v2; + v1.swap(v2); + swap(v1, v2); + } + { + using V = std::variant<int, ThrowingTypeWithNothrowSwap>; + static_assert(std::is_swappable_v<V> && has_swap_member<V>(), ""); + static_assert(!std::is_nothrow_swappable_v<V>, ""); + // instantiate swap + V v1, v2; + v1.swap(v2); + swap(v1, v2); + } + { + using V = std::variant<int, ThrowingMoveAssignNothrowMoveCtor>; + static_assert(std::is_swappable_v<V> && has_swap_member<V>(), ""); + static_assert(!std::is_nothrow_swappable_v<V>, ""); + // instantiate swap + V v1, v2; + v1.swap(v2); + swap(v1, v2); + } + { + using V = std::variant<int, ThrowingMoveAssignNothrowMoveCtorWithSwap>; + static_assert(std::is_swappable_v<V> && has_swap_member<V>(), ""); + static_assert(std::is_nothrow_swappable_v<V>, ""); + // instantiate swap + V v1, v2; + v1.swap(v2); + swap(v1, v2); + } + { + using V = std::variant<int, NotMoveAssignableWithSwap>; + static_assert(std::is_swappable_v<V> && has_swap_member<V>(), ""); + static_assert(std::is_nothrow_swappable_v<V>, ""); + // instantiate swap + V v1, v2; + v1.swap(v2); + swap(v1, v2); + } + { + // This variant type does not provide either a member or non-member swap + // but is still swappable via the generic swap algorithm, since the + // variant is move constructible and move assignable. + using V = std::variant<int, NotSwappable>; + LIBCPP_STATIC_ASSERT(!has_swap_member<V>()); + static_assert(std::is_swappable_v<V>, ""); + static_assert(std::is_nothrow_swappable_v<V>, ""); + V v1, v2; + swap(v1, v2); + } +} + +#ifdef _LIBCPP_VERSION +// This is why variant should SFINAE member swap. :-) +template class std::variant<int, NotSwappable>; +#endif + +int main() { + test_swap_valueless_by_exception(); + test_swap_same_alternative(); + test_swap_different_alternatives(); + test_swap_sfinae(); + test_swap_noexcept(); +} diff --git a/test/std/utilities/variant/variant.variant/variant_array.fail.cpp b/test/std/utilities/variant/variant.variant/variant_array.fail.cpp new file mode 100644 index 000000000000..11ee332e216e --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant_array.fail.cpp @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + + +#include <variant> +#include <type_traits> +#include <string> +#include <cassert> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" +#include "test_convertible.hpp" + +int main() +{ + // expected-error@variant:* 3 {{static_assert failed}} + std::variant<int, int[]> v; // expected-note {{requested here}} + std::variant<int, int[42]> v2; // expected-note {{requested here}} + std::variant<int, int[][42]> v3; // expected-note {{requested here}} +} diff --git a/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp b/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp new file mode 100644 index 000000000000..2d8cc0b3da0f --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp @@ -0,0 +1,26 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +int main() +{ + // expected-error@variant:* 1 {{static_assert failed}} + std::variant<> v; // expected-note {{requested here}} +} diff --git a/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp b/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp new file mode 100644 index 000000000000..bda27f0e5eba --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp @@ -0,0 +1,28 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +int main() +{ + // expected-error@variant:* 3 {{static_assert failed}} + std::variant<int, int&> v; // expected-note {{requested here}} + std::variant<int, const int &> v2; // expected-note {{requested here}} + std::variant<int, int&&> v3; // expected-note {{requested here}} +} diff --git a/test/std/utilities/variant/variant.variant/variant_void.fail.cpp b/test/std/utilities/variant/variant.variant/variant_void.fail.cpp new file mode 100644 index 000000000000..3d0da5620b50 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant_void.fail.cpp @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + + +#include <variant> +#include <type_traits> +#include <string> +#include <cassert> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" +#include "test_convertible.hpp" + +int main() +{ + // expected-error@variant:* 3 {{static_assert failed}} + std::variant<int, void> v; // expected-note {{requested here}} + std::variant<int, const void> v2; // expected-note {{requested here}} + std::variant<const volatile void, int> v3; // expected-note {{requested here}} +} diff --git a/test/std/utilities/variant/variant.visit/visit.pass.cpp b/test/std/utilities/variant/variant.visit/visit.pass.cpp new file mode 100644 index 000000000000..46d225883ae9 --- /dev/null +++ b/test/std/utilities/variant/variant.visit/visit.pass.cpp @@ -0,0 +1,291 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> +// template <class Visitor, class... Variants> +// constexpr see below visit(Visitor&& vis, Variants&&... vars); + +#include <cassert> +#include <memory> +#include <string> +#include <type_traits> +#include <utility> +#include <variant> + +#include "test_macros.h" +#include "type_id.h" +#include "variant_test_helpers.hpp" + +enum CallType : unsigned { + CT_None, + CT_NonConst = 1, + CT_Const = 2, + CT_LValue = 4, + CT_RValue = 8 +}; + +inline constexpr CallType operator|(CallType LHS, CallType RHS) { + return static_cast<CallType>(static_cast<unsigned>(LHS) | + static_cast<unsigned>(RHS)); +} + +struct ForwardingCallObject { + + template <class... Args> bool operator()(Args &&...) & { + set_call<Args &&...>(CT_NonConst | CT_LValue); + return true; + } + + template <class... Args> bool operator()(Args &&...) const & { + set_call<Args &&...>(CT_Const | CT_LValue); + return true; + } + + // Don't allow the call operator to be invoked as an rvalue. + template <class... Args> bool operator()(Args &&...) && { + set_call<Args &&...>(CT_NonConst | CT_RValue); + return true; + } + + template <class... Args> bool operator()(Args &&...) const && { + set_call<Args &&...>(CT_Const | CT_RValue); + return true; + } + + template <class... Args> static void set_call(CallType type) { + assert(last_call_type == CT_None); + assert(last_call_args == nullptr); + last_call_type = type; + last_call_args = std::addressof(makeArgumentID<Args...>()); + } + + template <class... Args> static bool check_call(CallType type) { + bool result = last_call_type == type && last_call_args && + *last_call_args == makeArgumentID<Args...>(); + last_call_type = CT_None; + last_call_args = nullptr; + return result; + } + + static CallType last_call_type; + static const TypeID *last_call_args; +}; + +CallType ForwardingCallObject::last_call_type = CT_None; +const TypeID *ForwardingCallObject::last_call_args = nullptr; + +void test_call_operator_forwarding() { + using Fn = ForwardingCallObject; + Fn obj{}; + const Fn &cobj = obj; + { // test call operator forwarding - single variant, single arg + using V = std::variant<int>; + V v(42); + std::visit(obj, v); + assert(Fn::check_call<int &>(CT_NonConst | CT_LValue)); + std::visit(cobj, v); + assert(Fn::check_call<int &>(CT_Const | CT_LValue)); + std::visit(std::move(obj), v); + assert(Fn::check_call<int &>(CT_NonConst | CT_RValue)); + std::visit(std::move(cobj), v); + assert(Fn::check_call<int &>(CT_Const | CT_RValue)); + } + { // test call operator forwarding - single variant, multi arg + using V = std::variant<int, long, double>; + V v(42l); + std::visit(obj, v); + assert(Fn::check_call<long &>(CT_NonConst | CT_LValue)); + std::visit(cobj, v); + assert(Fn::check_call<long &>(CT_Const | CT_LValue)); + std::visit(std::move(obj), v); + assert(Fn::check_call<long &>(CT_NonConst | CT_RValue)); + std::visit(std::move(cobj), v); + assert(Fn::check_call<long &>(CT_Const | CT_RValue)); + } + { // test call operator forwarding - multi variant, multi arg + using V = std::variant<int, long, double>; + using V2 = std::variant<int *, std::string>; + V v(42l); + V2 v2("hello"); + std::visit(obj, v, v2); + assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_LValue))); + std::visit(cobj, v, v2); + assert((Fn::check_call<long &, std::string &>(CT_Const | CT_LValue))); + std::visit(std::move(obj), v, v2); + assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_RValue))); + std::visit(std::move(cobj), v, v2); + assert((Fn::check_call<long &, std::string &>(CT_Const | CT_RValue))); + } +} + +void test_argument_forwarding() { + using Fn = ForwardingCallObject; + Fn obj{}; + const auto Val = CT_LValue | CT_NonConst; + { // single argument - value type + using V = std::variant<int>; + V v(42); + const V &cv = v; + std::visit(obj, v); + assert(Fn::check_call<int &>(Val)); + std::visit(obj, cv); + assert(Fn::check_call<const int &>(Val)); + std::visit(obj, std::move(v)); + assert(Fn::check_call<int &&>(Val)); + std::visit(obj, std::move(cv)); + assert(Fn::check_call<const int &&>(Val)); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { // single argument - lvalue reference + using V = std::variant<int &>; + int x = 42; + V v(x); + const V &cv = v; + std::visit(obj, v); + assert(Fn::check_call<int &>(Val)); + std::visit(obj, cv); + assert(Fn::check_call<int &>(Val)); + std::visit(obj, std::move(v)); + assert(Fn::check_call<int &>(Val)); + std::visit(obj, std::move(cv)); + assert(Fn::check_call<int &>(Val)); + } + { // single argument - rvalue reference + using V = std::variant<int &&>; + int x = 42; + V v(std::move(x)); + const V &cv = v; + std::visit(obj, v); + assert(Fn::check_call<int &>(Val)); + std::visit(obj, cv); + assert(Fn::check_call<int &>(Val)); + std::visit(obj, std::move(v)); + assert(Fn::check_call<int &&>(Val)); + std::visit(obj, std::move(cv)); + assert(Fn::check_call<int &&>(Val)); + } + { // multi argument - multi variant + using S = const std::string &; + using V = std::variant<int, S, long &&>; + const std::string str = "hello"; + long l = 43; + V v1(42); + const V &cv1 = v1; + V v2(str); + const V &cv2 = v2; + V v3(std::move(l)); + const V &cv3 = v3; + std::visit(obj, v1, v2, v3); + assert((Fn::check_call<int &, S, long &>(Val))); + std::visit(obj, cv1, cv2, std::move(v3)); + assert((Fn::check_call<const int &, S, long &&>(Val))); + } +#endif +} + +struct ReturnFirst { + template <class... Args> constexpr int operator()(int f, Args &&...) const { + return f; + } +}; + +struct ReturnArity { + template <class... Args> constexpr int operator()(Args &&...) const { + return sizeof...(Args); + } +}; + +void test_constexpr() { + constexpr ReturnFirst obj{}; + constexpr ReturnArity aobj{}; + { + using V = std::variant<int>; + constexpr V v(42); + static_assert(std::visit(obj, v) == 42, ""); + } + { + using V = std::variant<short, long, char>; + constexpr V v(42l); + static_assert(std::visit(obj, v) == 42, ""); + } + { + using V1 = std::variant<int>; + using V2 = std::variant<int, char *, long long>; + using V3 = std::variant<bool, int, int>; + constexpr V1 v1; + constexpr V2 v2(nullptr); + constexpr V3 v3; + static_assert(std::visit(aobj, v1, v2, v3) == 3, ""); + } + { + using V1 = std::variant<int>; + using V2 = std::variant<int, char *, long long>; + using V3 = std::variant<void *, int, int>; + constexpr V1 v1; + constexpr V2 v2(nullptr); + constexpr V3 v3; + static_assert(std::visit(aobj, v1, v2, v3) == 3, ""); + } +} + +void test_exceptions() { +#ifndef TEST_HAS_NO_EXCEPTIONS + ReturnArity obj{}; + auto test = [&](auto &&... args) { + try { + std::visit(obj, args...); + } catch (const std::bad_variant_access &) { + return true; + } catch (...) { + } + return false; + }; + { + using V = std::variant<int, MakeEmptyT>; + V v; + makeEmpty(v); + assert(test(v)); + } + { + using V = std::variant<int, MakeEmptyT>; + using V2 = std::variant<long, std::string, void *>; + V v; + makeEmpty(v); + V2 v2("hello"); + assert(test(v, v2)); + } + { + using V = std::variant<int, MakeEmptyT>; + using V2 = std::variant<long, std::string, void *>; + V v; + makeEmpty(v); + V2 v2("hello"); + assert(test(v2, v)); + } + { + using V = std::variant<int, MakeEmptyT>; + using V2 = std::variant<long, std::string, void *, MakeEmptyT>; + V v; + makeEmpty(v); + V2 v2; + makeEmpty(v2); + assert(test(v, v2)); + } +#endif +} + +int main() { + test_call_operator_forwarding(); + test_argument_forwarding(); + test_constexpr(); + test_exceptions(); +} |