1 // RUN: %clang_cc1 -std=c++2a -x c++ %s -verify
2
3 static_assert(requires { { 0 }; });
4 static_assert(requires { { "aaaa" }; });
5 static_assert(requires { { (0).da }; }); // expected-error{{member reference base type 'int' is not a structure or union}}
6
foo()7 void foo() {}
8 static_assert(requires { { foo() }; });
9
10 // Substitution failure in expression
11
12 struct A {};
13 struct B {
operator +B14 B operator+(const B &other) const { return other; }
15 };
16 struct C {
operator +C17 C operator+(C &other) const { return other; }
18 };
19
20 template<typename T> requires requires (T a, const T& b) { { a + b }; } // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}}
21 struct r1 {};
22
23 using r1i1 = r1<int>;
24 using r1i2 = r1<A>; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}}
25 using r1i3 = r1<B>;
26 using r1i4 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}}
27
fooD28 struct D { void foo() {} };
29
30 template<typename T> requires requires (T a) { { a.foo() }; } // expected-note{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} expected-note{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} expected-note{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}}
31 struct r2 {};
32
33 using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
34 using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}}
35 using r2i3 = r2<D>;
36 using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}}
37
38 template<typename T> requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}}
39 struct r3 {};
40
41 using r3i1 = r3<int>;
42 using r3i2 = r3<A>;
43 using r3i3 = r3<A &>;
44 using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}}
45 using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}}
46
47 // Non-dependent expressions
48
49 template<typename T> requires requires (T t) { { 0 }; { "a" }; { (void)'a' }; }
50 struct r4 {};
51
52 using r4i1 = r4<int>;
53 using r4i2 = r4<int[10]>;
54 using r4i3 = r4<int(int)>;
55
56 // Noexcept requirement
maythrow()57 void maythrow() { }
58 static_assert(!requires { { maythrow() } noexcept; });
59 static_assert(requires { { 1 } noexcept; });
60
61 struct E { void operator++(int) noexcept; };
62 struct F { void operator++(int); };
63
64 template<typename T> requires requires (T t) { { t++ } noexcept; } // expected-note{{because 't ++' may throw an exception}}
65 struct r5 {};
66
67 using r5i1 = r5<int>;
68 using r5i2 = r5<E>;
69 using r5i2 = r5<F>; // expected-error{{constraints not satisfied for class template 'r5' [with T = F]}}
70
71 template<typename T> requires requires (T t) { { t.foo() } noexcept; } // expected-note{{because 't.foo()' would be invalid: no member named 'foo' in 'E'}}
72 struct r6 {};
73
74 using r6i = r6<E>; // expected-error{{constraints not satisfied for class template 'r6' [with T = E]}}
75
76 template<typename T, typename U>
77 constexpr bool is_same_v = false;
78
79 template<typename T>
80 constexpr bool is_same_v<T, T> = true;
81
82 template<typename T> struct remove_reference { using type = T; };
83 template<typename T> struct remove_reference<T&> { using type = T; };
84
85 template<typename T, typename U>
86 concept Same = is_same_v<T, U>;
87
88 template<typename T>
89 concept Large = sizeof(typename remove_reference<T>::type) >= 4;
90 // expected-note@-1{{because 'sizeof(typename remove_reference<short &>::type) >= 4' (2 >= 4) evaluated to false}}
91
92 template<typename T> requires requires (T t) { { t } -> Large; } // expected-note{{because 'short &' does not satisfy 'Large':}}
93 struct r7 {};
94
95 using r7i1 = r7<int>;
96 using r7i2 = r7<short>; // expected-error{{constraints not satisfied for class template 'r7' [with T = short]}}
97
98 template<typename T> requires requires (T t) { { t } -> Same<T&>; }
99 struct r8 {};
100
101 using r8i1 = r8<int>;
102 using r8i2 = r8<short*>;
103
104 // Substitution failure in type constraint
105
106 template<typename T> requires requires (T t) { { t } -> Same<typename T::type&>; }
107 // expected-note@-1{{because 'Same<expr-type, typename T::type &>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
108 struct r9 {};
109
110 struct M { using type = M; };
111
112 using r9i1 = r9<M>;
113 using r9i2 = r9<int>; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}}
114
115 // Substitution failure in both expression and return type requirement
116
117 template<typename T> requires requires (T t) { { t.foo() } -> Same<typename T::type>; } // expected-note{{because 't.foo()' would be invalid: member reference base type 'int' is not a structure or union}}
118 struct r10 {};
119
120 using r10i = r10<int>; // expected-error{{constraints not satisfied for class template 'r10' [with T = int]}}
121
122 // Non-type concept in type constraint
123
124 template<int T>
125 concept IsEven = (T % 2) == 0;
126
127 template<typename T> requires requires (T t) { { t } -> IsEven; } // expected-error{{concept named in type constraint is not a type concept}}
128 struct r11 {};
129
130 // Value categories
131
132 template<auto a = 0>
133 requires requires (int b) {
134 { a } -> Same<int>;
135 { b } -> Same<int&>;
136 { 0 } -> Same<int>;
137 { static_cast<int&&>(a) } -> Same<int&&>;
f1()138 } void f1() {}
139 template void f1<>();
140
141 // C++ [expr.prim.req.compound] Example
142 namespace std_example {
143 template<typename T> concept C1 =
144 requires(T x) {
145 {x++};
146 };
147
148 template<typename T, typename U> constexpr bool is_same_v = false;
149 template<typename T> constexpr bool is_same_v<T, T> = true;
150
151 template<typename T, typename U> concept same_as = is_same_v<T, U>;
152 // expected-note@-1 {{because 'is_same_v<int, int *>' evaluated to false}}
153
154 static_assert(C1<int>);
155 static_assert(C1<int*>);
156 template<C1 T> struct C1_check {};
157 using c1c1 = C1_check<int>;
158 using c1c2 = C1_check<int[10]>;
159
160 template<typename T> concept C2 =
161 requires(T x) {
162 {*x} -> same_as<typename T::inner>;
163 // expected-note@-1{{because type constraint 'same_as<int, typename T2::inner>' was not satisfied:}}
164 // expected-note@-2{{because '*x' would be invalid: indirection requires pointer operand ('int' invalid)}}
165 };
166
167 struct T1 {
168 using inner = int;
operator *std_example::T1169 inner operator *() { return 0; }
170 };
171 struct T2 {
172 using inner = int *;
operator *std_example::T2173 int operator *() { return 0; }
174 };
175 static_assert(C2<T1>);
176 template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}}
177 using c2c1 = C2_check<int>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}}
178 using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}}
179
180 template<typename T>
g(T t)181 void g(T t) noexcept(sizeof(T) == 1) {}
182
183 template<typename T> concept C5 =
184 requires(T x) {
185 {g(x)} noexcept; // expected-note{{because 'g(x)' may throw an exception}}
186 };
187
188 static_assert(C5<char>);
189 template<C5 T> struct C5_check {}; // expected-note{{because 'short' does not satisfy 'C5'}}
190 using c5 = C5_check<short>; // expected-error{{constraints not satisfied for class template 'C5_check' [with T = short]}}
191 }
192
193 namespace access_checks {
194 namespace in_return_type_requirement {
195
196 // https://github.com/llvm/llvm-project/issues/93788
197 template <typename From, typename To>
198 concept is_assignable = requires(From from, To to) {
199 from = to;
200 };
201
202 template <typename T>
203 class trait {
204 public:
205 using public_type = int;
206 private:
207 using private_type = int;
208 };
209
210 template <typename T>
211 concept has_field = requires(T t) {
212 { t.field } -> is_assignable<typename trait<T>::private_type>; // expected-note {{'private_type' is a private member}}
213 };
214 template <typename T>
215 concept has_field2 = requires(T t) {
216 { t.field } -> is_assignable<typename trait<T>::public_type>;
217 };
218
219 struct A {
220 int field;
221 };
222 static_assert(has_field<A>); // expected-error {{static assertion failed}} \
223 // expected-note {{because 'A' does not satisfy 'has_field'}}
224 static_assert(has_field2<A>);
225
226 } // namespace access_checks
227 } // namespace in_return_type_requirement
228