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
4 
5 namespace std {
6 #ifndef NO_CONSTEXPR
7 #define CONSTEXPR constexpr
8 #else
9 #define CONSTEXPR
10 #endif
11 
move(T & x)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);
16   }
17 
18   // Unrelated move functions are not the builtin.
move(T,T)19   template<typename T> CONSTEXPR int move(T, T) { return 5; }
20 
21   template<typename T, bool Rref> struct ref { using type = T&; };
22   template<typename T> struct ref<T, true> { using type = T&&; };
23 
move_if_noexcept(T & x)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);
27   }
28 
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; };
32 
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; };
35 
forward(typename remove_reference<T>::type & x)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);
40   }
forward(typename remove_reference<T>::type && 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);
44   }
45 
as_const(T & x)46   template<typename T> CONSTEXPR const T &as_const(T &x) {
47     static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
48     return x;
49   }
50 
addressof(T & x)51   template<typename T> CONSTEXPR T *addressof(T &x) {
52     static_assert(T::moveable, "instantiated addressof"); // expected-error {{no member named 'moveable' in 'B'}}
53     return __builtin_addressof(x);
54   }
55 
__addressof(T & x)56   template<typename T> CONSTEXPR T *__addressof(T &x) {
57     static_assert(T::moveable, "instantiated __addressof"); // expected-error {{no member named 'moveable' in 'B'}}
58     return __builtin_addressof(x);
59   }
60 }
61 
62 // Note: this doesn't have a 'moveable' member. Instantiation of the above
63 // functions will fail if it's attempted.
64 struct A {};
f(A a)65 constexpr bool f(A a) { // #f
66   A &&move = std::move(a); // #call
67   A &&move_if_noexcept = std::move_if_noexcept(a);
68   A &&forward1 = std::forward<A>(a);
69   A &forward2 = std::forward<A&>(a);
70   const A &as_const = std::as_const(a);
71   A *addressof = std::addressof(a);
72   A *addressof2 = std::__addressof(a);
73   return &move == &a && &move_if_noexcept == &a &&
74          &forward1 == &a && &forward2 == &a &&
75          &as_const == &a && addressof == &a &&
76          addressof2 == &a && std::move(a, a) == 5;
77 }
78 
79 #ifndef NO_CONSTEXPR
80 static_assert(f({}), "should be constexpr");
81 #else
82 // expected-error@#f {{never produces a constant expression}}
83 // expected-note@#call {{}}
84 #endif
85 
forward_rval_as_lval()86 A &forward_rval_as_lval() {
87   std::forward<A&&>(A()); // expected-warning {{const attribute}}
88   return std::forward<A&>(A()); // expected-note {{instantiation of}}
89 }
90 
91 struct B {};
92 B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
93 B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // #2 expected-note {{instantiation of}}
94 B &&(*pForward)(B&) = &std::forward<B>; // #3 expected-note {{instantiation of}}
95 const B &(*pAsConst)(B&) = &std::as_const; // #4 expected-note {{instantiation of}}
96 B *(*pAddressof)(B&) = &std::addressof; // #5 expected-note {{instantiation of}}
97 B *(*pUnderUnderAddressof)(B&) = &std::__addressof; // #6 expected-note {{instantiation of}}
98 int (*pUnrelatedMove)(B, B) = std::move;
99 
100 struct C {};
101 C &&(&rMove)(C&) = std::move; // #7 expected-note {{instantiation of}}
102 C &&(&rForward)(C&) = std::forward<C>; // #8 expected-note {{instantiation of}}
103 int (&rUnrelatedMove)(B, B) = std::move;
104 
105 #if __cplusplus <= 201703L
106 // expected-warning@#1 {{non-addressable}}
107 // expected-warning@#2 {{non-addressable}}
108 // expected-warning@#3 {{non-addressable}}
109 // expected-warning@#4 {{non-addressable}}
110 // expected-warning@#5 {{non-addressable}}
111 // expected-warning@#6 {{non-addressable}}
112 // expected-warning@#7 {{non-addressable}}
113 // expected-warning@#8 {{non-addressable}}
114 #else
115 // expected-error@#1 {{non-addressable}}
116 // expected-error@#2 {{non-addressable}}
117 // expected-error@#3 {{non-addressable}}
118 // expected-error@#4 {{non-addressable}}
119 // expected-error@#5 {{non-addressable}}
120 // expected-error@#6 {{non-addressable}}
121 // expected-error@#7 {{non-addressable}}
122 // expected-error@#8 {{non-addressable}}
123 #endif
124 
attribute_const()125 void attribute_const() {
126   int n;
127   std::move(n); // expected-warning {{ignoring return value}}
128   std::move_if_noexcept(n); // expected-warning {{ignoring return value}}
129   std::forward<int>(n); // expected-warning {{ignoring return value}}
130   std::addressof(n); // expected-warning {{ignoring return value}}
131   std::__addressof(n); // expected-warning {{ignoring return value}}
132   std::as_const(n); // expected-warning {{ignoring return value}}
133 }
134 
135 namespace std {
136   template<typename T> int &move(T);
137 }
138 int bad_signature = std::move(0); // expected-error {{unsupported signature for 'std::move<int>'}}
139