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
7 #define CONSTEXPR constexpr
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
,
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'}}
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.
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;
107 static_assert(f({}), "should be constexpr");
109 // expected-error@#f {{never produces a constant expression}}
110 // expected-note@#call {{}}
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}}
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
;
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}}
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}}
155 void attribute_const() {
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}}
167 template<typename T
> int &move(T
);
169 int bad_signature
= std::move(0); // expected-error {{unsupported signature for 'std::move<int>'}}