1c24e6dd3SEric Fiselier //===----------------------------------------------------------------------===//
2c24e6dd3SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c24e6dd3SEric Fiselier //
7c24e6dd3SEric Fiselier //===----------------------------------------------------------------------===//
8c24e6dd3SEric Fiselier
9c24e6dd3SEric Fiselier // test move
10c24e6dd3SEric Fiselier
11c24e6dd3SEric Fiselier #include <utility>
12c24e6dd3SEric Fiselier #include <type_traits>
13c24e6dd3SEric Fiselier #include <cassert>
14c24e6dd3SEric Fiselier
15c24e6dd3SEric Fiselier #include "test_macros.h"
16c24e6dd3SEric Fiselier
17c24e6dd3SEric Fiselier class move_only
18c24e6dd3SEric Fiselier {
19c24e6dd3SEric Fiselier move_only(const move_only&);
20c24e6dd3SEric Fiselier move_only& operator=(const move_only&);
21c24e6dd3SEric Fiselier public:
move_only(move_only &&)22c24e6dd3SEric Fiselier move_only(move_only&&) {}
operator =(move_only &&)23c24e6dd3SEric Fiselier move_only& operator=(move_only&&) {return *this;}
24c24e6dd3SEric Fiselier
move_only()25c24e6dd3SEric Fiselier move_only() {}
26c24e6dd3SEric Fiselier };
27c24e6dd3SEric Fiselier
source()28c24e6dd3SEric Fiselier move_only source() {return move_only();}
csource()29c24e6dd3SEric Fiselier const move_only csource() {return move_only();}
30c24e6dd3SEric Fiselier
test(move_only)31c24e6dd3SEric Fiselier void test(move_only) {}
32c24e6dd3SEric Fiselier
33c24e6dd3SEric Fiselier int x = 42;
34c24e6dd3SEric Fiselier const int& cx = x;
35c24e6dd3SEric Fiselier
36c24e6dd3SEric Fiselier template <class QualInt>
get()37000f25a3SEric Fiselier QualInt get() TEST_NOEXCEPT { return static_cast<QualInt>(x); }
38c24e6dd3SEric Fiselier
39c24e6dd3SEric Fiselier
40c24e6dd3SEric Fiselier int copy_ctor = 0;
41c24e6dd3SEric Fiselier int move_ctor = 0;
42c24e6dd3SEric Fiselier
43c24e6dd3SEric Fiselier struct A {
AA44c24e6dd3SEric Fiselier A() {}
AA45c24e6dd3SEric Fiselier A(const A&) {++copy_ctor;}
AA46c24e6dd3SEric Fiselier A(A&&) {++move_ctor;}
47c24e6dd3SEric Fiselier A& operator=(const A&) = delete;
48c24e6dd3SEric Fiselier };
49c24e6dd3SEric Fiselier
50c24e6dd3SEric Fiselier #if TEST_STD_VER > 11
test_constexpr_move()51000f25a3SEric Fiselier constexpr bool test_constexpr_move() {
52609e669eSEric Fiselier int y = 42;
53609e669eSEric Fiselier const int cy = y;
54609e669eSEric Fiselier return std::move(y) == 42
55609e669eSEric Fiselier && std::move(cy) == 42
56609e669eSEric Fiselier && std::move(static_cast<int&&>(y)) == 42
57609e669eSEric Fiselier && std::move(static_cast<int const&&>(y)) == 42;
58c24e6dd3SEric Fiselier }
59000f25a3SEric Fiselier #endif
main(int,char **)602df59c50SJF Bastien int main(int, char**)
61c24e6dd3SEric Fiselier {
62c24e6dd3SEric Fiselier { // Test return type and noexcept.
63c24e6dd3SEric Fiselier static_assert(std::is_same<decltype(std::move(x)), int&&>::value, "");
64000f25a3SEric Fiselier ASSERT_NOEXCEPT(std::move(x));
65c24e6dd3SEric Fiselier static_assert(std::is_same<decltype(std::move(cx)), const int&&>::value, "");
66000f25a3SEric Fiselier ASSERT_NOEXCEPT(std::move(cx));
67c24e6dd3SEric Fiselier static_assert(std::is_same<decltype(std::move(42)), int&&>::value, "");
68000f25a3SEric Fiselier ASSERT_NOEXCEPT(std::move(42));
69c24e6dd3SEric Fiselier static_assert(std::is_same<decltype(std::move(get<const int&&>())), const int&&>::value, "");
70000f25a3SEric Fiselier ASSERT_NOEXCEPT(std::move(get<int const&&>()));
71c24e6dd3SEric Fiselier }
72c24e6dd3SEric Fiselier { // test copy and move semantics
73c24e6dd3SEric Fiselier A a;
74c24e6dd3SEric Fiselier const A ca = A();
75c24e6dd3SEric Fiselier
76c24e6dd3SEric Fiselier assert(copy_ctor == 0);
77c24e6dd3SEric Fiselier assert(move_ctor == 0);
78c24e6dd3SEric Fiselier
79*c479e0c9SLouis Dionne A a2 = a; (void)a2;
80c24e6dd3SEric Fiselier assert(copy_ctor == 1);
81c24e6dd3SEric Fiselier assert(move_ctor == 0);
82c24e6dd3SEric Fiselier
83*c479e0c9SLouis Dionne A a3 = std::move(a); (void)a3;
84c24e6dd3SEric Fiselier assert(copy_ctor == 1);
85c24e6dd3SEric Fiselier assert(move_ctor == 1);
86c24e6dd3SEric Fiselier
87*c479e0c9SLouis Dionne A a4 = ca; (void)a4;
88c24e6dd3SEric Fiselier assert(copy_ctor == 2);
89c24e6dd3SEric Fiselier assert(move_ctor == 1);
90c24e6dd3SEric Fiselier
91*c479e0c9SLouis Dionne A a5 = std::move(ca); (void)a5;
92c24e6dd3SEric Fiselier assert(copy_ctor == 3);
93c24e6dd3SEric Fiselier assert(move_ctor == 1);
94c24e6dd3SEric Fiselier }
95c24e6dd3SEric Fiselier { // test on a move only type
96c24e6dd3SEric Fiselier move_only mo;
97c24e6dd3SEric Fiselier test(std::move(mo));
98c24e6dd3SEric Fiselier test(source());
99c24e6dd3SEric Fiselier }
100c24e6dd3SEric Fiselier #if TEST_STD_VER > 11
101c24e6dd3SEric Fiselier {
102609e669eSEric Fiselier constexpr int y = 42;
103609e669eSEric Fiselier static_assert(std::move(y) == 42, "");
104c24e6dd3SEric Fiselier static_assert(test_constexpr_move(), "");
105c24e6dd3SEric Fiselier }
106c24e6dd3SEric Fiselier #endif
107c24e6dd3SEric Fiselier #if TEST_STD_VER == 11 && defined(_LIBCPP_VERSION)
108c24e6dd3SEric Fiselier // Test that std::forward is constexpr in C++11. This is an extension
109c24e6dd3SEric Fiselier // provided by both libc++ and libstdc++.
110c24e6dd3SEric Fiselier {
111609e669eSEric Fiselier constexpr int y = 42;
112609e669eSEric Fiselier static_assert(std::move(y) == 42, "");
113c24e6dd3SEric Fiselier }
114c24e6dd3SEric Fiselier #endif
1152df59c50SJF Bastien
1162df59c50SJF Bastien return 0;
117c24e6dd3SEric Fiselier }
118