xref: /llvm-project/clang/test/Parser/cxx-concepts-requires-clause.cpp (revision 84bc0a9e02bbcfc0f1e1333f642be37e687fb429)
1 // RUN: %clang_cc1 -std=c++20 -x c++ %s -verify
2 // RUN: %clang_cc1 -std=c++23 -x c++ %s -verify
3 
4 // Test parsing of the optional requires-clause in a template-declaration.
5 
6 template <typename T> requires true
7 void foo() { }
8 
9 template <typename T> requires (!0)
10 struct A {
11   void foo();
12   struct AA;
13   enum E : int;
14   static int x;
15   static constexpr int z = 16;
16 
17   template <typename> requires true
18   void Mfoo();
19 
20   template <typename> requires true
21   struct M;
22 
23   template <typename> requires true
24   static int Mx;
25 
26   template <typename TT> requires true
27   using MQ = M<TT>;
28 
29   constexpr int bazz() requires (z == 16);
30 };
31 
32 template <typename T> requires (!0)
33 void A<T>::foo() { }
34 
35 template <typename T> requires (!0)
36 struct A<T>::AA { };
37 
38 template <typename T> requires (!0)
39 enum A<T>::E : int { E0 };
40 
41 template <typename T> requires (!0)
42 int A<T>::x = 0;
43 
44 template <typename T> requires (!0)
45 template <typename> requires true
46 void A<T>::Mfoo() { }
47 
48 template <typename T> requires (!0)
49 template <typename> requires true
50 struct A<T>::M { };
51 
52 template <typename T> requires (!0)
53 template <typename> requires true
54 int A<T>::Mx = 0;
55 
56 template <typename T> requires true
57 int x = 0;
58 
59 template <typename T> requires true
60 using Q = A<T>;
61 
62 template<typename T> requires (!0)
63 constexpr int A<T>::bazz() requires (z == 16) { return z; }
64 
65 struct C {
66   template <typename> requires true
67   void Mfoo();
68 
69   template <typename> requires true
70   struct M;
71 
72   template <typename> requires true
73   static int Mx;
74 
75   template <typename T> requires true
76   using MQ = M<T>;
77 };
78 
79 template <typename> requires true
80 void C::Mfoo() { }
81 
82 template <typename> requires true
83 struct C::M { };
84 
85 template <typename> requires true
86 int C::Mx = 0;
87 
88 // Test behavior with non-primary-expression requires clauses
89 
90 template<typename T> requires foo<T>()
91 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
92 struct B1 { };
93 
94 int func() { }
95 
96 template<typename T> requires func()
97 // expected-error@-1{{atomic constraint must be of type 'bool' (found '<overloaded function type>')}}
98 // expected-note@-2{{parentheses are required around this expression in a requires clause}}
99 struct B2 { };
100 
101 template<typename T> requires (foo<T>())
102 struct B3 { };
103 
104 template<typename T> requires T{}
105 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
106 struct B4 { };
107 
108 template<typename T> requires sizeof(T) == 0
109 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
110 struct B5 { };
111 
112 template<typename T> requires (sizeof(T)) == 0
113 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
114 struct B6 { };
115 
116 template<typename T> requires 0
117 // expected-error@-1{{atomic constraint must be of type 'bool' (found 'int')}}
118 (int) bar() { };
119 
120 template<typename T> requires foo<T>
121 (int) bar() { };
122 // expected-error@-1{{expected '(' for function-style cast or type construction}}
123 
124 template<typename T>
125 void bar() requires foo<T>();
126 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
127 
128 template<typename T>
129 void bar() requires (foo<T>());
130 
131 template<typename T>
132 void bar() requires func();
133 // expected-error@-1{{atomic constraint must be of type 'bool' (found '<overloaded function type>')}}
134 // expected-note@-2{{parentheses are required around this expression in a requires clause}}
135 
136 template<typename T>
137 void bar() requires T{};
138 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
139 
140 template<typename T>
141 void bar() requires sizeof(T) == 0;
142 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
143 
144 template<typename T>
145 void bar() requires (sizeof(T)) == 0;
146 // expected-error@-1{{parentheses are required around this expression in a requires clause}}
147 
148 template<typename T>
149 void bar(int x, int y) requires (x, y, true);
150 
151 template<typename T>
152 struct B {
153   int x;
154   void foo(int y) requires (x, this, this->x, y, true);
155   static void bar(int y) requires (x, true);
156   // expected-error@-1{{'this' cannot be implicitly used in a static member function declaration}}
157   static void baz(int y) requires (this, true);
158   // expected-error@-1{{'this' cannot be used in a static member function declaration}}
159 };
160 
161 auto lambda1 = [] (auto x) requires (sizeof(decltype(x)) == 1) { };
162 
163 auto lambda2 = [] (auto x) constexpr -> int requires (sizeof(decltype(x)) == 1) { return 0; };
164 
165 auto lambda3 = []<auto> requires(sizeof(char) == 1){};
166 
167 auto lambda4 = [] requires(sizeof(char) == 1){}; // expected-error {{expected body of lambda expression}}
168 #if __cplusplus <= 202002L
169 // expected-warning@-2{{lambda without a parameter clause is a C++23 extension}}
170 #endif
171 
172 namespace GH78524 {
173 
174 template <typename T> T Foo;
175 
176 template <typename T> auto C(Foo<T>);
177 
178 template <typename T> struct D {
179   decltype(T()(C<T>)) Type;
180 };
181 
182 template <typename T, typename U> D<T> G(T, U) { return {}; }
183 
184 struct E {};
185 
186 void F() {
187   G([]<typename T>
188 //     ~~~~~~~~~~ T: Depth: 0, Index: 0
189       requires requires { [](auto...) {}; }(T)
190 //                           ~~~~ auto: Depth: 1, Index: 0
191     { return T(); },
192     E{});
193 }
194 
195 int a = []<int=0> requires requires { [](auto){}; } { return 0; }();
196 
197 } // namespace GH78524
198 
199 
200 namespace GH51868 {
201 template<auto L>
202 concept C = requires {
203   typename decltype(L)::template operator()<int>;
204   // expected-error@-1 {{template name refers to non-type template 'decltype(L)::template operator ()'}}
205 };
206 }
207