xref: /llvm-project/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp (revision 12cb1cb3720de8d164196010123ce1a8901d8122)
1 // RUN: %clang_cc1 %s -I%S -std=c++2a -verify
2 
3 namespace std { struct type_info; }
4 
5 static_assert(requires { 0; });
6 static_assert(requires { "aaaa"; });
7 static_assert(requires { (0).da; }); // expected-error{{member reference base type 'int' is not a structure or union}}
8 
9 struct A {};
10 struct B {
operator +B11     B operator+(const B &other) const { return other; }
12 };
13 struct C {
operator +C14     C operator+(C &other) const { return other; }
15 };
16 
17 template<typename T> requires requires (T a, const T& b) { a + b; }
18 // expected-note@-1{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}}
19 // expected-note@-2{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}}
20 struct r1 {};
21 
22 using r1i1 = r1<int>;
23 using r1i2 = r1<A>; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}}
24 using r1i3 = r1<B>;
25 using r1i4 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}}
26 
fooD27 struct D { void foo() {} };
28 
29 template<typename T> requires requires (T a) { a.foo(); }
30 // expected-note@-1{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}}
31 // expected-note@-2{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}}
32 // expected-note@-3{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}}
33 struct r2 {};
34 
35 using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
36 using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}}
37 using r2i3 = r2<D>;
38 using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}}
39 
40 template<typename T> requires requires { sizeof(T); }
41 // expected-note@-1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}}
42 // expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}}
43 struct r3 {};
44 
45 using r3i1 = r3<int>;
46 using r3i2 = r3<A>;
47 using r3i3 = r3<A &>;
48 using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}}
49 using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}}
50 
51 template<typename T> requires requires (T t) { 0; "a"; (void)'a'; }
52 struct r4 {};
53 
54 using r4i1 = r4<int>;
55 using r4i2 = r4<int[10]>;
56 using r4i3 = r4<int(int)>;
57 
58 template<class T> void f(T) = delete;
f(T)59 template<class T> requires (sizeof(T) == 1) void f(T) { }
60 
61 template<typename T> requires requires(T t) { f(t); }
62 // expected-note@-1{{because 'f(t)' would be invalid: call to deleted function 'f'}}
63 struct r5 {};
64 
65 using r5i1 = r5<int>;
66 // expected-error@-1 {{constraints not satisfied for class template 'r5' [with T = int]}}
67 using r5i2 = r5<char>;
68 
69 template<typename T>
70 struct E {
non_default_constructibleE::non_default_constructible71   struct non_default_constructible { non_default_constructible(T t) { } };
72 };
73 
74 template<typename T> requires requires(T t) { typename E<T>::non_default_constructible{}; }
75 // expected-note@-1 {{because 'typename E<T>::non_default_constructible{}' would be invalid: no matching constructor for initialization of 'typename E<int>::non_default_constructible'}}
76 struct r6 {};
77 
78 using r6i1 = r6<int>;
79 // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}
80 
81 template<typename T> requires requires(T t) { typename E<T>::non_default_constructible(); }
82 // expected-note@-1 {{because 'typename E<T>::non_default_constructible()' would be invalid: no matching constructor for initialization of 'typename E<int>::non_default_constructible'}}
83 struct r7 {};
84 
85 using r7i1 = r7<int>;
86 // expected-error@-1 {{constraints not satisfied for class template 'r7' [with T = int]}}
87 
88 // C++ [expr.prim.req.simple] Example
89 namespace std_example {
90   template<typename T> concept C =
91     requires (T a, T b) { // expected-note{{because 'a' would be invalid: argument may not have 'void' type}}
92       a + b; // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('int *' and 'int *')}}
93     };
94 
95   static_assert(C<int>);
96   template<C T> struct C_check {}; // expected-note{{because 'void' does not satisfy 'C'}} expected-note{{because 'int *' does not satisfy 'C'}}
97   using c1c1 = C_check<void>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = void]}}
98   using c1c2 = C_check<int *>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = int *]}}
99 }
100 
101 // typeid() of an expression becomes potentially evaluated if the expression is
102 // of a polymorphic type.
103 class X { virtual ~X(); };
104 constexpr bool b = requires (X &x) { static_cast<int(*)[(typeid(x), 0)]>(nullptr); };
105 // expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}}
106 // expected-note@-2{{'x' declared here}}
107 
108 namespace access_checks {
109 namespace in_requires_expression {
110 template<auto>
111 struct A {
112     static constexpr bool foo();
113     static constexpr bool bar();
114     static constexpr bool baz();
115     static constexpr bool faz();
116 };
117 
118 class C{};
119 
120 class B {
p()121     void p() {}
122     bool data_member = true;
123     static const bool static_member = true;
124     friend struct A<0>;
125 };
126 
127 template<auto x>
foo()128 constexpr bool A<x>::foo() {
129     return requires(B b) { b.p(); };
130 }
131 static_assert(!A<1>::foo());
132 static_assert(A<0>::foo());
133 
134 template<auto x>
bar()135 constexpr bool A<x>::bar() {
136     return requires() { B::static_member; };
137 }
138 static_assert(!A<1>::bar());
139 static_assert(A<0>::bar());
140 
141 template<auto x>
baz()142 constexpr bool A<x>::baz() {
143     return requires(B b) { b.data_member; };
144 }
145 static_assert(!A<1>::baz());
146 static_assert(A<0>::baz());
147 
148 template<auto x>
faz()149 constexpr bool A<x>::faz() {
150     return requires(B a, B b) {
151       a.p();
152       b.data_member;
153       B::static_member;
154     };
155 }
156 static_assert(!A<1>::faz());
157 static_assert(A<0>::faz());
158 } // namespace in_requires_expression
159 
160 namespace in_concepts {
161 // Dependent access does not cause hard errors.
162 template<int N> class A;
163 
164 template <> class A<0> {
f()165   static void f() {}
166 };
167 template<int N>
168 concept C1 = requires() { A<N>::f(); };
169 static_assert(!C1<0>);
170 
171 template <> class A<1> {
172 public:
f()173   static void f() {}
174 };
175 static_assert(C1<1>);
176 
177 // Non-dependent access to private member is a hard error.
178 class B{
f()179    static void f() {} // expected-note 2{{implicitly declared private here}}
180 };
181 template<class T>
182 concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private member}}
183 
non_template_func()184 constexpr bool non_template_func() {
185   return requires() {
186       B::f(); // expected-error {{'f' is a private member}}
187   };
188 }
189 template<int x>
template_func()190 constexpr bool template_func() {
191   return requires() {
192       A<x>::f();
193   };
194 }
195 static_assert(!template_func<0>());
196 static_assert(template_func<1>());
197 } // namespace in_concepts
198 
199 namespace in_trailing_requires {
200 template <class> struct B;
201 class A {
202    static void f();
203    friend struct B<short>;
204 };
205 
206 template <class T> struct B {
indexaccess_checks::in_trailing_requires::B207   static constexpr int index() requires requires{ A::f(); } {
208     return 1;
209   }
indexaccess_checks::in_trailing_requires::B210   static constexpr int index() {
211     return 2;
212   }
213 };
214 
215 static_assert(B<short>::index() == 1);
216 static_assert(B<int>::index() == 2);
217 
218 namespace missing_member_function {
219 template <class T> struct Use;
220 class X {
221   int a;
222   static int B;
223   friend struct Use<short>;
224 };
225 template <class T> struct Use {
fooaccess_checks::in_trailing_requires::missing_member_function::Use226   constexpr static int foo() requires requires(X x) { x.a; } {
227     return 1;
228   }
baraccess_checks::in_trailing_requires::missing_member_function::Use229   constexpr static int bar() requires requires { X::B; } {
230     return 1;
231   }
232 };
233 
test()234 void test() {
235   // FIXME: Propagate diagnostic.
236   Use<int>::foo(); //expected-error {{invalid reference to function 'foo': constraints not satisfied}}
237   static_assert(Use<short>::foo() == 1);
238 }
239 } // namespace missing_member_function
240 } // namespace in_trailing_requires
241 } // namespace access_check
242