Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaCXX / builtin-std-move.cpp
blobadad66afc2cbd9577d58b4c16c16847b3ae42d50
1 // RUN: %clang_cc1 -std=c++17 -verify %s
2 // RUN: %clang_cc1 -std=c++17 -verify %s -DNO_CONSTEXPR
3 // RUN: %clang_cc1 -std=c++20 -verify %s
5 namespace std {
6 #ifndef NO_CONSTEXPR
7 #define CONSTEXPR constexpr
8 #else
9 #define CONSTEXPR
10 #endif
12 template<typename T> CONSTEXPR T &&move(T &x) {
13 static_assert(T::moveable, "instantiated move"); // expected-error {{no member named 'moveable' in 'B'}}
14 // expected-error@-1 {{no member named 'moveable' in 'C'}}
15 return static_cast<T&&>(x);
18 // Unrelated move functions are not the builtin.
19 template<typename T> CONSTEXPR int move(T, T) { return 5; }
21 template<typename T, bool Rref> struct ref { using type = T&; };
22 template<typename T> struct ref<T, true> { using type = T&&; };
24 template<typename T> CONSTEXPR auto move_if_noexcept(T &x) -> typename ref<T, noexcept(T(static_cast<T&&>(x)))>::type {
25 static_assert(T::moveable, "instantiated move_if_noexcept"); // expected-error {{no member named 'moveable' in 'B'}}
26 return static_cast<typename ref<T, noexcept(T(static_cast<T&&>(x)))>::type>(x);
29 template<typename T> struct remove_reference { using type = T; };
30 template<typename T> struct remove_reference<T&> { using type = T; };
31 template<typename T> struct remove_reference<T&&> { using type = T; };
33 template<typename T> struct is_lvalue_reference { static constexpr bool value = false; };
34 template<typename T> struct is_lvalue_reference<T&> { static constexpr bool value = true; };
36 template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &x) {
37 static_assert(T::moveable, "instantiated forward"); // expected-error {{no member named 'moveable' in 'B'}}
38 // expected-error@-1 {{no member named 'moveable' in 'C'}}
39 return static_cast<T&&>(x);
41 template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &&x) {
42 static_assert(!is_lvalue_reference<T>::value, "should not forward rval as lval"); // expected-error {{static assertion failed}}
43 return static_cast<T&&>(x);
46 template <class T> struct is_const { static constexpr bool value = false; };
47 template <class T> struct is_const<const T> { static constexpr bool value = true; };
49 template <bool B, class T, class F> struct conditional { using type = T; };
50 template <class T, class F> struct conditional<false, T, F> { using type = F; };
52 template <class U, class T>
53 using CopyConst = typename conditional<
54 is_const<remove_reference<U>>::value,
55 const T, T>::type;
57 template <class U, class T>
58 using OverrideRef = typename conditional<
59 is_lvalue_reference<U &&>::value,
60 typename remove_reference<T>::type &,
61 typename remove_reference<T>::type &&>::type;
63 template <class U, class T>
64 using ForwardLikeRetType = OverrideRef<U &&, CopyConst<U, T>>;
66 template <class U, class T>
67 CONSTEXPR auto forward_like(T &&t) -> ForwardLikeRetType<U, T> {
68 using TT = typename remove_reference<T>::type;
69 static_assert(TT::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
70 return static_cast<ForwardLikeRetType<U, T>>(t);
73 template<typename T> CONSTEXPR const T &as_const(T &x) {
74 static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
75 return x;
78 template<typename T> CONSTEXPR T *addressof(T &x) {
79 static_assert(T::moveable, "instantiated addressof"); // expected-error {{no member named 'moveable' in 'B'}}
80 return __builtin_addressof(x);
83 template<typename T> CONSTEXPR T *__addressof(T &x) {
84 static_assert(T::moveable, "instantiated __addressof"); // expected-error {{no member named 'moveable' in 'B'}}
85 return __builtin_addressof(x);
89 // Note: this doesn't have a 'moveable' member. Instantiation of the above
90 // functions will fail if it's attempted.
91 struct A {};
92 constexpr bool f(A a) { // #f
93 A &&move = std::move(a); // #call
94 A &&move_if_noexcept = std::move_if_noexcept(a);
95 A &&forward1 = std::forward<A>(a);
96 A &forward2 = std::forward<A&>(a);
97 const A &as_const = std::as_const(a);
98 A *addressof = std::addressof(a);
99 A *addressof2 = std::__addressof(a);
100 return &move == &a && &move_if_noexcept == &a &&
101 &forward1 == &a && &forward2 == &a &&
102 &as_const == &a && addressof == &a &&
103 addressof2 == &a && std::move(a, a) == 5;
106 #ifndef NO_CONSTEXPR
107 static_assert(f({}), "should be constexpr");
108 #else
109 // expected-error@#f {{never produces a constant expression}}
110 // expected-note@#call {{}}
111 #endif
113 A &forward_rval_as_lval() {
114 std::forward<A&&>(A()); // expected-warning {{const attribute}}
115 return std::forward<A&>(A()); // expected-note {{instantiation of}} expected-warning {{returning reference}}
118 struct B {};
119 B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
120 B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // #2 expected-note {{instantiation of}}
121 B &&(*pForward)(B&) = &std::forward<B>; // #3 expected-note {{instantiation of}}
122 B &&(*pForwardLike)(B&) = &std::forward_like<int&&, B&>; // #4 expected-note {{instantiation of}}
123 const B &(*pAsConst)(B&) = &std::as_const; // #5 expected-note {{instantiation of}}
124 B *(*pAddressof)(B&) = &std::addressof; // #6 expected-note {{instantiation of}}
125 B *(*pUnderUnderAddressof)(B&) = &std::__addressof; // #7 expected-note {{instantiation of}}
126 int (*pUnrelatedMove)(B, B) = std::move;
128 struct C {};
129 C &&(&rMove)(C&) = std::move; // #8 expected-note {{instantiation of}}
130 C &&(&rForward)(C&) = std::forward<C>; // #9 expected-note {{instantiation of}}
131 int (&rUnrelatedMove)(B, B) = std::move;
133 #if __cplusplus <= 201703L
134 // expected-warning@#1 {{non-addressable}}
135 // expected-warning@#2 {{non-addressable}}
136 // expected-warning@#3 {{non-addressable}}
137 // expected-warning@#4 {{non-addressable}}
138 // expected-warning@#5 {{non-addressable}}
139 // expected-warning@#6 {{non-addressable}}
140 // expected-warning@#7 {{non-addressable}}
141 // expected-warning@#8 {{non-addressable}}
142 // expected-warning@#9 {{non-addressable}}
143 #else
144 // expected-error@#1 {{non-addressable}}
145 // expected-error@#2 {{non-addressable}}
146 // expected-error@#3 {{non-addressable}}
147 // expected-error@#4 {{non-addressable}}
148 // expected-error@#5 {{non-addressable}}
149 // expected-error@#6 {{non-addressable}}
150 // expected-error@#7 {{non-addressable}}
151 // expected-error@#8 {{non-addressable}}
152 // expected-error@#9 {{non-addressable}}
153 #endif
155 void attribute_const() {
156 int n;
157 std::move(n); // expected-warning {{ignoring return value}}
158 std::move_if_noexcept(n); // expected-warning {{ignoring return value}}
159 std::forward<int>(n); // expected-warning {{ignoring return value}}
160 std::forward_like<float&&>(n); // expected-warning {{ignoring return value}}
161 std::addressof(n); // expected-warning {{ignoring return value}}
162 std::__addressof(n); // expected-warning {{ignoring return value}}
163 std::as_const(n); // expected-warning {{ignoring return value}}
166 namespace std {
167 template<typename T> int &move(T);
169 int bad_signature = std::move(0); // expected-error {{unsupported signature for 'std::move<int>'}}