1 // { dg-do compile { target c++20 } }
2 
3 template<typename T>
4 concept Class = __is_class(T);
5 
6 // Allow a requires-expression with no parms.
7 template<typename T>
8 concept C = requires { typename T::type; };
9 
10 void f1(int a) requires true;         // { dg-error "non-templated" }
11 auto f2(int a) -> bool requires true; // { dg-error "non-templated" }
12 auto f3(int a) requires true -> bool; // { dg-error "" } requires-clause precedes trailing-return-type
13 typedef void fn_t() requires true;    // { dg-error "typedef" }
14 void (*pf)() requires true;           // { dg-error "non-function" }
15 void (*fn(int))() requires false;     // { dg-error "return type" }
16 void g(int (*)() requires true);      // { dg-error "parameter|non-function" }
17 auto* p = new (void(*)(char) requires true); // { dg-error "type-id" }
f4(auto a)18 void f4(auto a) requires Class<decltype(a)> { }
f5(auto a)19 void f5(auto a) requires requires (decltype(a) x) { -x; } { } // { dg-message "in requirements" }
20 
21 struct Test {
22   void f(auto a) requires Class<decltype(a)>;
23 } test;
24 
driver_1()25 void driver_1() {
26   struct S { } s;
27   f4(s);
28   f5(0);
29   f5((void*)0); // { dg-error "" }
30   test.f(s);
31 }
32 
f(auto a)33 void Test::f(auto a) requires Class<decltype(a)> { }
34 
35 template<bool B> requires B struct S0; // OK
36 
37 template<int N> requires N struct S1 { }; // { dg-error "does not have type" }
38 S1<1> x0; // { dg-error "template constraint failure|does not have type" }
39 
40 template<int N> requires N == 0 struct S2 { }; // { dg-error "does not have type|must be enclosed" }
41 
42 template<int N> requires (N == 0) struct S3 { }; // OK
43 
44 template<typename T, T X> requires X struct S4 { }; // { dg-error "bool" }
45 S4<int, 0> x1;      // { dg-error "template constraint failure" }
46 S4<bool, true> x2; // OK
47 S4<bool, false> x3; // { dg-error "template constraint failure" }
48 
49 
50 // req11.C
51 template<typename T>
requires(T t)52 concept Streamable = requires (T t) { t; };
53 
54 template<typename T>
requires(T t)55 concept Range = requires (T t) { t; };
56 
57 // FIXME: There are two syntax errors here when there should be
58 // just one.Note that !Range<T> is not a primary-expression and needs to
59 // be wrapped in parens to be syntactically valid.
60 template<class T>
61   requires Streamable<T> && !Range<T> // { dg-error "must be enclosed" }
62 void print1(const T& x) { }
63 
64 template<class T>
65   requires Streamable<T> && (!Range<T>)
print2(const T & x)66 void print2(const T& x) { }
67 
driver_3()68 void driver_3()
69 {
70   print2("hello"); // { dg-error "" }
71 }
72