1893d53d1SChris Cotter // RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
2893d53d1SChris Cotter
3893d53d1SChris Cotter // NOLINTBEGIN
4893d53d1SChris Cotter namespace std {
5893d53d1SChris Cotter template <bool B, class T = void> struct enable_if { };
6893d53d1SChris Cotter
7893d53d1SChris Cotter template <class T> struct enable_if<true, T> { typedef T type; };
8893d53d1SChris Cotter
9893d53d1SChris Cotter template <bool B, class T = void>
10893d53d1SChris Cotter using enable_if_t = typename enable_if<B, T>::type;
11893d53d1SChris Cotter
12893d53d1SChris Cotter } // namespace std
13893d53d1SChris Cotter // NOLINTEND
14893d53d1SChris Cotter
15893d53d1SChris Cotter template <typename...>
16893d53d1SChris Cotter struct ConsumeVariadic;
17893d53d1SChris Cotter
18893d53d1SChris Cotter struct Obj {
19893d53d1SChris Cotter };
20893d53d1SChris Cotter
21893d53d1SChris Cotter namespace enable_if_in_return_type {
22893d53d1SChris Cotter
23893d53d1SChris Cotter ////////////////////////////////
24893d53d1SChris Cotter // Section 1: enable_if in return type of function
25893d53d1SChris Cotter ////////////////////////////////
26893d53d1SChris Cotter
27893d53d1SChris Cotter ////////////////////////////////
28893d53d1SChris Cotter // General tests
29893d53d1SChris Cotter ////////////////////////////////
30893d53d1SChris Cotter
31893d53d1SChris Cotter template <typename T>
basic()32893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type basic() {
33893d53d1SChris Cotter return Obj{};
34893d53d1SChris Cotter }
35893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
36893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj basic() requires T::some_value {{{$}}
37893d53d1SChris Cotter
38893d53d1SChris Cotter template <typename T>
basic_t()39893d53d1SChris Cotter std::enable_if_t<T::some_value, Obj> basic_t() {
40893d53d1SChris Cotter return Obj{};
41893d53d1SChris Cotter }
42893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
43893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj basic_t() requires T::some_value {{{$}}
44893d53d1SChris Cotter
45893d53d1SChris Cotter template <typename T>
basic_trailing()46893d53d1SChris Cotter auto basic_trailing() -> typename std::enable_if<T::some_value, Obj>::type {
47893d53d1SChris Cotter return Obj{};
48893d53d1SChris Cotter }
49893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:26: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
50893d53d1SChris Cotter // CHECK-FIXES: {{^}}auto basic_trailing() -> Obj requires T::some_value {{{$}}
51893d53d1SChris Cotter
52893d53d1SChris Cotter template <typename T>
existing_constraint()53893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type existing_constraint() requires (T::another_value) {
54893d53d1SChris Cotter return Obj{};
55893d53d1SChris Cotter }
56893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
57893d53d1SChris Cotter // CHECK-FIXES: {{^}}typename std::enable_if<T::some_value, Obj>::type existing_constraint() requires (T::another_value) {{{$}}
58893d53d1SChris Cotter
59893d53d1SChris Cotter template <typename U>
60893d53d1SChris Cotter typename std::enable_if<U::some_value, Obj>::type decl_without_def();
61893d53d1SChris Cotter
62893d53d1SChris Cotter template <typename U>
63893d53d1SChris Cotter typename std::enable_if<U::some_value, Obj>::type decl_with_separate_def();
64893d53d1SChris Cotter
65893d53d1SChris Cotter template <typename U>
decl_with_separate_def()66893d53d1SChris Cotter typename std::enable_if<U::some_value, Obj>::type decl_with_separate_def() {
67893d53d1SChris Cotter return Obj{};
68893d53d1SChris Cotter }
69893d53d1SChris Cotter // FIXME - Support definitions with separate decls
70893d53d1SChris Cotter
71893d53d1SChris Cotter template <typename U>
no_dependent_type(U)72893d53d1SChris Cotter std::enable_if_t<true, Obj> no_dependent_type(U) {
73893d53d1SChris Cotter return Obj{};
74893d53d1SChris Cotter }
75893d53d1SChris Cotter // FIXME - Support non-dependent enable_ifs. Low priority though...
76893d53d1SChris Cotter
77893d53d1SChris Cotter template <typename T>
pointer_of_enable_if()78893d53d1SChris Cotter typename std::enable_if<T::some_value, int>::type* pointer_of_enable_if() {
79893d53d1SChris Cotter return nullptr;
80893d53d1SChris Cotter }
81893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
82893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
83893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if() requires T::some_value {{{$}}
84893d53d1SChris Cotter
85893d53d1SChris Cotter template <typename T>
pointer_of_enable_if_t()86893d53d1SChris Cotter std::enable_if_t<T::some_value, int>* pointer_of_enable_if_t() {
87893d53d1SChris Cotter return nullptr;
88893d53d1SChris Cotter }
89893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
90893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
91893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t() requires T::some_value {{{$}}
92893d53d1SChris Cotter
93893d53d1SChris Cotter template <typename T>
const_pointer_of_enable_if_t()94893d53d1SChris Cotter const std::enable_if_t<T::some_value, int>* const_pointer_of_enable_if_t() {
95893d53d1SChris Cotter return nullptr;
96893d53d1SChris Cotter }
97893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
98893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
99893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}const int* const_pointer_of_enable_if_t() requires T::some_value {{{$}}
100893d53d1SChris Cotter
101893d53d1SChris Cotter template <typename T>
const_pointer_of_enable_if_t2()102893d53d1SChris Cotter std::enable_if_t<T::some_value, int> const * const_pointer_of_enable_if_t2() {
103893d53d1SChris Cotter return nullptr;
104893d53d1SChris Cotter }
105893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
106893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
107893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int const * const_pointer_of_enable_if_t2() requires T::some_value {{{$}}
108893d53d1SChris Cotter
109893d53d1SChris Cotter
110893d53d1SChris Cotter template <typename T>
reference_of_enable_if_t()111893d53d1SChris Cotter std::enable_if_t<T::some_value, int>& reference_of_enable_if_t() {
112893d53d1SChris Cotter static int x; return x;
113893d53d1SChris Cotter }
114893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
115893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
116893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int& reference_of_enable_if_t() requires T::some_value {{{$}}
117893d53d1SChris Cotter
118893d53d1SChris Cotter template <typename T>
const_reference_of_enable_if_t()119893d53d1SChris Cotter const std::enable_if_t<T::some_value, int>& const_reference_of_enable_if_t() {
120893d53d1SChris Cotter static int x; return x;
121893d53d1SChris Cotter }
122893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
123893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
124893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}const int& const_reference_of_enable_if_t() requires T::some_value {{{$}}
125893d53d1SChris Cotter
126893d53d1SChris Cotter template <typename T>
enable_if_default_void()127893d53d1SChris Cotter typename std::enable_if<T::some_value>::type enable_if_default_void() {
128893d53d1SChris Cotter }
129893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
130893d53d1SChris Cotter // CHECK-FIXES: {{^}}void enable_if_default_void() requires T::some_value {{{$}}
131893d53d1SChris Cotter
132893d53d1SChris Cotter template <typename T>
enable_if_t_default_void()133893d53d1SChris Cotter std::enable_if_t<T::some_value> enable_if_t_default_void() {
134893d53d1SChris Cotter }
135893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
136893d53d1SChris Cotter // CHECK-FIXES: {{^}}void enable_if_t_default_void() requires T::some_value {{{$}}
137893d53d1SChris Cotter
138893d53d1SChris Cotter template <typename T>
enable_if_t_default_void_pointer()139893d53d1SChris Cotter std::enable_if_t<T::some_value>* enable_if_t_default_void_pointer() {
140893d53d1SChris Cotter }
141893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
142893d53d1SChris Cotter // CHECK-FIXES: {{^}}void* enable_if_t_default_void_pointer() requires T::some_value {{{$}}
143893d53d1SChris Cotter
144893d53d1SChris Cotter namespace using_namespace_std {
145893d53d1SChris Cotter
146893d53d1SChris Cotter using namespace std;
147893d53d1SChris Cotter
148893d53d1SChris Cotter template <typename T>
with_typename()149893d53d1SChris Cotter typename enable_if<T::some_value>::type with_typename() {
150893d53d1SChris Cotter }
151893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
152893d53d1SChris Cotter // CHECK-FIXES: {{^}}void with_typename() requires T::some_value {{{$}}
153893d53d1SChris Cotter
154893d53d1SChris Cotter template <typename T>
with_t()155893d53d1SChris Cotter enable_if_t<T::some_value> with_t() {
156893d53d1SChris Cotter }
157893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
158893d53d1SChris Cotter // CHECK-FIXES: {{^}}void with_t() requires T::some_value {{{$}}
159893d53d1SChris Cotter
160893d53d1SChris Cotter template <typename T>
with_typename_and_type()161893d53d1SChris Cotter typename enable_if<T::some_value, int>::type with_typename_and_type() {
162893d53d1SChris Cotter }
163893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
164893d53d1SChris Cotter // CHECK-FIXES: {{^}}int with_typename_and_type() requires T::some_value {{{$}}
165893d53d1SChris Cotter
166893d53d1SChris Cotter template <typename T>
with_t_and_type()167893d53d1SChris Cotter enable_if_t<T::some_value, int> with_t_and_type() {
168893d53d1SChris Cotter }
169893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
170893d53d1SChris Cotter // CHECK-FIXES: {{^}}int with_t_and_type() requires T::some_value {{{$}}
171893d53d1SChris Cotter
172893d53d1SChris Cotter } // namespace using_namespace_std
173893d53d1SChris Cotter
174893d53d1SChris Cotter
175893d53d1SChris Cotter ////////////////////////////////
176893d53d1SChris Cotter // Negative tests - incorrect uses of enable_if
177893d53d1SChris Cotter ////////////////////////////////
178893d53d1SChris Cotter template <typename U>
not_enable_if()179893d53d1SChris Cotter std::enable_if<U::some_value, Obj> not_enable_if() {
180893d53d1SChris Cotter return {};
181893d53d1SChris Cotter }
182893d53d1SChris Cotter template <typename U>
not_enable_if_wrong_type()183893d53d1SChris Cotter typename std::enable_if<U::some_value, Obj>::type123 not_enable_if_wrong_type() {
184893d53d1SChris Cotter return {};
185893d53d1SChris Cotter }
186893d53d1SChris Cotter template <typename U>
not_enable_if_t()187893d53d1SChris Cotter typename std::enable_if_t<U::some_value, Obj>::type not_enable_if_t() {
188893d53d1SChris Cotter return {};
189893d53d1SChris Cotter }
190893d53d1SChris Cotter template <typename U>
not_enable_if_t_again()191893d53d1SChris Cotter typename std::enable_if_t<U::some_value, Obj>::type123 not_enable_if_t_again() {
192893d53d1SChris Cotter return {};
193893d53d1SChris Cotter }
194893d53d1SChris Cotter template <typename U>
not_pointer_of_enable_if()195893d53d1SChris Cotter std::enable_if<U::some_value, int>* not_pointer_of_enable_if() {
196893d53d1SChris Cotter return nullptr;
197893d53d1SChris Cotter }
198893d53d1SChris Cotter template <typename U>
not_pointer_of_enable_if_t()199893d53d1SChris Cotter typename std::enable_if<U::some_value, int>::type123 * not_pointer_of_enable_if_t() {
200893d53d1SChris Cotter return nullptr;
201893d53d1SChris Cotter }
202893d53d1SChris Cotter
203893d53d1SChris Cotter
204893d53d1SChris Cotter namespace primary_expression_tests {
205893d53d1SChris Cotter
206893d53d1SChris Cotter ////////////////////////////////
207893d53d1SChris Cotter // Primary/non-primary expression tests
208893d53d1SChris Cotter ////////////////////////////////
209893d53d1SChris Cotter
210893d53d1SChris Cotter template <typename T> struct Traits;
211893d53d1SChris Cotter
212893d53d1SChris Cotter template <typename T>
type_trait_value()213893d53d1SChris Cotter std::enable_if_t<Traits<T>::value> type_trait_value() {
214893d53d1SChris Cotter }
215893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
216893d53d1SChris Cotter // CHECK-FIXES: {{^}}void type_trait_value() requires Traits<T>::value {{{$}}
217893d53d1SChris Cotter
218893d53d1SChris Cotter template <typename T>
type_trait_member_call()219893d53d1SChris Cotter std::enable_if_t<Traits<T>::member()> type_trait_member_call() {
220893d53d1SChris Cotter }
221893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
222893d53d1SChris Cotter // CHECK-FIXES: {{^}}void type_trait_member_call() requires (Traits<T>::member()) {{{$}}
223893d53d1SChris Cotter
224893d53d1SChris Cotter template <typename T>
negate()225893d53d1SChris Cotter std::enable_if_t<!Traits<T>::value> negate() {
226893d53d1SChris Cotter }
227893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
228893d53d1SChris Cotter // CHECK-FIXES: {{^}}void negate() requires (!Traits<T>::value) {{{$}}
229893d53d1SChris Cotter
230893d53d1SChris Cotter template <typename T>
conjunction()231893d53d1SChris Cotter std::enable_if_t<Traits<T>::value1 && Traits<T>::value2> conjunction() {
232893d53d1SChris Cotter }
233893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
234893d53d1SChris Cotter // CHECK-FIXES: {{^}}void conjunction() requires (Traits<T>::value1 && Traits<T>::value2) {{{$}}
235893d53d1SChris Cotter
236893d53d1SChris Cotter template <typename T>
disjunction()237893d53d1SChris Cotter std::enable_if_t<Traits<T>::value1 || Traits<T>::value2> disjunction() {
238893d53d1SChris Cotter }
239893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
240893d53d1SChris Cotter // CHECK-FIXES: {{^}}void disjunction() requires (Traits<T>::value1 || Traits<T>::value2) {{{$}}
241893d53d1SChris Cotter
242893d53d1SChris Cotter template <typename T>
conjunction_with_negate()243893d53d1SChris Cotter std::enable_if_t<Traits<T>::value1 && !Traits<T>::value2> conjunction_with_negate() {
244893d53d1SChris Cotter }
245893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
246893d53d1SChris Cotter // CHECK-FIXES: {{^}}void conjunction_with_negate() requires (Traits<T>::value1 && !Traits<T>::value2) {{{$}}
247893d53d1SChris Cotter
248893d53d1SChris Cotter template <typename T>
complex_operators()249893d53d1SChris Cotter std::enable_if_t<Traits<T>::value1 == (Traits<T>::value2 + 5)> complex_operators() {
250893d53d1SChris Cotter }
251893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
252893d53d1SChris Cotter // CHECK-FIXES: {{^}}void complex_operators() requires (Traits<T>::value1 == (Traits<T>::value2 + 5)) {{{$}}
253893d53d1SChris Cotter
254893d53d1SChris Cotter } // namespace primary_expression_tests
255893d53d1SChris Cotter
256893d53d1SChris Cotter
257893d53d1SChris Cotter ////////////////////////////////
258893d53d1SChris Cotter // Functions with specifier
259893d53d1SChris Cotter ////////////////////////////////
260893d53d1SChris Cotter
261893d53d1SChris Cotter template <typename T>
constexpr_decl()262893d53d1SChris Cotter constexpr typename std::enable_if<T::some_value, int>::type constexpr_decl() {
263893d53d1SChris Cotter return 10;
264893d53d1SChris Cotter }
265893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
266893d53d1SChris Cotter // CHECK-FIXES: {{^}}constexpr int constexpr_decl() requires T::some_value {{{$}}
267893d53d1SChris Cotter
268893d53d1SChris Cotter template <typename T>
static_inline_constexpr_decl()269893d53d1SChris Cotter static inline constexpr typename std::enable_if<T::some_value, int>::type static_inline_constexpr_decl() {
270893d53d1SChris Cotter return 10;
271893d53d1SChris Cotter }
272893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
273893d53d1SChris Cotter // CHECK-FIXES: {{^}}static inline constexpr int static_inline_constexpr_decl() requires T::some_value {{{$}}
274893d53d1SChris Cotter
275893d53d1SChris Cotter template <typename T>
276893d53d1SChris Cotter static
277893d53d1SChris Cotter typename std::enable_if<T::some_value, int>::type
static_decl()278893d53d1SChris Cotter static_decl() {
279893d53d1SChris Cotter return 10;
280893d53d1SChris Cotter }
281893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-4]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
282893d53d1SChris Cotter // CHECK-FIXES: {{^}}static{{$}}
283893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int{{$}}
284893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}static_decl() requires T::some_value {{{$}}
285893d53d1SChris Cotter
286893d53d1SChris Cotter template <typename T>
constexpr_comment_decl()287893d53d1SChris Cotter constexpr /* comment */ typename std::enable_if<T::some_value, int>::type constexpr_comment_decl() {
288893d53d1SChris Cotter return 10;
289893d53d1SChris Cotter }
290893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
291893d53d1SChris Cotter // CHECK-FIXES: {{^}}constexpr /* comment */ int constexpr_comment_decl() requires T::some_value {{{$}}
292893d53d1SChris Cotter
293893d53d1SChris Cotter
294893d53d1SChris Cotter ////////////////////////////////
295893d53d1SChris Cotter // Class definition tests
296893d53d1SChris Cotter ////////////////////////////////
297893d53d1SChris Cotter
298893d53d1SChris Cotter struct AClass {
299893d53d1SChris Cotter
300893d53d1SChris Cotter template <typename T>
static_methodenable_if_in_return_type::AClass301893d53d1SChris Cotter static typename std::enable_if<T::some_value, Obj>::type static_method() {
302893d53d1SChris Cotter return Obj{};
303893d53d1SChris Cotter }
304893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:10: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
305893d53d1SChris Cotter // CHECK-FIXES: {{^}} static Obj static_method() requires T::some_value {{{$}}
306893d53d1SChris Cotter
307893d53d1SChris Cotter template <typename T>
memberenable_if_in_return_type::AClass308893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type member() {
309893d53d1SChris Cotter return Obj{};
310893d53d1SChris Cotter }
311893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
312893d53d1SChris Cotter // CHECK-FIXES: {{^}} Obj member() requires T::some_value {{{$}}
313893d53d1SChris Cotter
314893d53d1SChris Cotter template <typename T>
const_qualifierenable_if_in_return_type::AClass315893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type const_qualifier() const {
316893d53d1SChris Cotter return Obj{};
317893d53d1SChris Cotter }
318893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
319893d53d1SChris Cotter // CHECK-FIXES: {{^}} Obj const_qualifier() const requires T::some_value {{{$}}
320893d53d1SChris Cotter
321893d53d1SChris Cotter template <typename T>
rvalue_ref_qualifierenable_if_in_return_type::AClass322893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type rvalue_ref_qualifier() && {
323893d53d1SChris Cotter return Obj{};
324893d53d1SChris Cotter }
325893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
326893d53d1SChris Cotter // CHECK-FIXES: {{^}} Obj rvalue_ref_qualifier() && requires T::some_value {{{$}}
327893d53d1SChris Cotter
328893d53d1SChris Cotter template <typename T>
rvalue_ref_qualifier_commentenable_if_in_return_type::AClass329893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type rvalue_ref_qualifier_comment() /* c1 */ && /* c2 */ {
330893d53d1SChris Cotter return Obj{};
331893d53d1SChris Cotter }
332893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
333893d53d1SChris Cotter // CHECK-FIXES: {{^}} Obj rvalue_ref_qualifier_comment() /* c1 */ && /* c2 */ requires T::some_value {{{$}}
334893d53d1SChris Cotter
335893d53d1SChris Cotter template <typename T>
336893d53d1SChris Cotter std::enable_if_t<T::some_value, AClass&> operator=(T&&) = delete;
337893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
338893d53d1SChris Cotter // CHECK-FIXES: {{^}} AClass& operator=(T&&) requires T::some_value = delete;
339893d53d1SChris Cotter
340893d53d1SChris Cotter template<typename T>
341893d53d1SChris Cotter std::enable_if_t<T::some_value, AClass&> operator=(ConsumeVariadic<T>) noexcept(requires (T t) { t = 4; }) = delete;
342893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
343893d53d1SChris Cotter // CHECK-FIXES: {{^}} AClass& operator=(ConsumeVariadic<T>) noexcept(requires (T t) { t = 4; }) requires T::some_value = delete;
344893d53d1SChris Cotter
345893d53d1SChris Cotter };
346893d53d1SChris Cotter
347893d53d1SChris Cotter
348893d53d1SChris Cotter ////////////////////////////////
349893d53d1SChris Cotter // Comments and whitespace tests
350893d53d1SChris Cotter ////////////////////////////////
351893d53d1SChris Cotter
352893d53d1SChris Cotter template <typename T>
leading_comment()353893d53d1SChris Cotter typename std::enable_if</* check1 */ T::some_value, Obj>::type leading_comment() {
354893d53d1SChris Cotter return Obj{};
355893d53d1SChris Cotter }
356893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
357893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj leading_comment() requires /* check1 */ T::some_value {{{$}}
358893d53d1SChris Cotter
359893d53d1SChris Cotter template <typename T>
body_on_next_line()360893d53d1SChris Cotter typename std::enable_if<T::some_value, Obj>::type body_on_next_line()
361893d53d1SChris Cotter {
362893d53d1SChris Cotter return Obj{};
363893d53d1SChris Cotter }
364893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-4]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
365893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj body_on_next_line(){{$}}
366893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}requires T::some_value {{{$}}
367893d53d1SChris Cotter
368893d53d1SChris Cotter template <typename T>
leading_comment_whitespace()369893d53d1SChris Cotter typename std::enable_if< /* check1 */ T::some_value, Obj>::type leading_comment_whitespace() {
370893d53d1SChris Cotter return Obj{};
371893d53d1SChris Cotter }
372893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
373893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj leading_comment_whitespace() requires /* check1 */ T::some_value {{{$}}
374893d53d1SChris Cotter
375893d53d1SChris Cotter template <typename T>
leading_and_trailing_comment()376893d53d1SChris Cotter typename std::enable_if</* check1 */ T::some_value /* check2 */, Obj>::type leading_and_trailing_comment() {
377893d53d1SChris Cotter return Obj{};
378893d53d1SChris Cotter }
379893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
380893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj leading_and_trailing_comment() requires /* check1 */ T::some_value /* check2 */ {{{$}}
381893d53d1SChris Cotter
382893d53d1SChris Cotter template <typename T, typename U>
383893d53d1SChris Cotter typename std::enable_if<T::some_value &&
condition_on_two_lines()384893d53d1SChris Cotter U::another_value, Obj>::type condition_on_two_lines() {
385893d53d1SChris Cotter return Obj{};
386893d53d1SChris Cotter }
387893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-4]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
388893d53d1SChris Cotter // CHECK-FIXES: {{^}}Obj condition_on_two_lines() requires (T::some_value &&{{$}}
389893d53d1SChris Cotter // CHECK-FIXES-NEXT: U::another_value) {{{$}}
390893d53d1SChris Cotter
391893d53d1SChris Cotter template <typename T>
pointer_of_enable_if_t_with_spaces()392893d53d1SChris Cotter typename std::enable_if<T::some_value, int> :: type* pointer_of_enable_if_t_with_spaces() {
393893d53d1SChris Cotter }
394893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
395893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
396893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t_with_spaces() requires T::some_value {{{$}}
397893d53d1SChris Cotter
398893d53d1SChris Cotter template <typename T>
pointer_of_enable_if_t_with_comment()399893d53d1SChris Cotter typename std::enable_if<T::some_value, int> :: /*c*/ type* pointer_of_enable_if_t_with_comment() {
400893d53d1SChris Cotter }
401893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
402893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
403893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}int* pointer_of_enable_if_t_with_comment() requires T::some_value {{{$}}
404893d53d1SChris Cotter
405893d53d1SChris Cotter template <typename T>
406893d53d1SChris Cotter std::enable_if_t<T::some_value // comment
trailing_slash_slash_comment()407893d53d1SChris Cotter > trailing_slash_slash_comment() {
408893d53d1SChris Cotter }
409893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
410893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
411893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void trailing_slash_slash_comment() requires T::some_value // comment{{$}}
412893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} {{{$}}
413893d53d1SChris Cotter
414893d53d1SChris Cotter } // namespace enable_if_in_return_type
415893d53d1SChris Cotter
416893d53d1SChris Cotter
417893d53d1SChris Cotter namespace enable_if_trailing_non_type_parameter {
418893d53d1SChris Cotter
419893d53d1SChris Cotter ////////////////////////////////
420893d53d1SChris Cotter // Section 2: enable_if as final template non-type parameter
421893d53d1SChris Cotter ////////////////////////////////
422893d53d1SChris Cotter
423893d53d1SChris Cotter template <typename T, typename std::enable_if<T::some_value, int>::type = 0>
basic()424893d53d1SChris Cotter void basic() {
425893d53d1SChris Cotter }
426893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
427893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
428893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void basic() requires T::some_value {{{$}}
429893d53d1SChris Cotter
430893d53d1SChris Cotter template <typename T, std::enable_if_t<T::some_value, int> = 0>
basic_t()431893d53d1SChris Cotter void basic_t() {
432893d53d1SChris Cotter }
433893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
434893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
435893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void basic_t() requires T::some_value {{{$}}
436893d53d1SChris Cotter
437893d53d1SChris Cotter template <typename T, template <typename> class U, class V, std::enable_if_t<T::some_value, int> = 0>
basic_many_template_params()438893d53d1SChris Cotter void basic_many_template_params() {
439893d53d1SChris Cotter }
440893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:61: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
441893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T, template <typename> class U, class V>{{$}}
442893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void basic_many_template_params() requires T::some_value {{{$}}
443893d53d1SChris Cotter
444893d53d1SChris Cotter template <std::enable_if_t<true, int> = 0>
no_dependent_type()445893d53d1SChris Cotter void no_dependent_type() {
446893d53d1SChris Cotter }
447893d53d1SChris Cotter // FIXME - Support non-dependent enable_ifs. Low priority though...
448893d53d1SChris Cotter
449893d53d1SChris Cotter struct ABaseClass {
450893d53d1SChris Cotter ABaseClass();
451893d53d1SChris Cotter ABaseClass(int);
452893d53d1SChris Cotter };
453893d53d1SChris Cotter
454893d53d1SChris Cotter template <typename T>
455893d53d1SChris Cotter struct AClass : ABaseClass {
456893d53d1SChris Cotter template <std::enable_if_t<T::some_value, int> = 0>
no_other_template_paramsenable_if_trailing_non_type_parameter::AClass457893d53d1SChris Cotter void no_other_template_params() {
458893d53d1SChris Cotter }
459893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
460893d53d1SChris Cotter // CHECK-FIXES: {{^}} {{$}}
461893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} void no_other_template_params() requires T::some_value {{{$}}
462893d53d1SChris Cotter
463893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClassenable_if_trailing_non_type_parameter::AClass464893d53d1SChris Cotter AClass() {}
465893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
466893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
467893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass() requires U::some_value {}{{$}}
468893d53d1SChris Cotter
469893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClassenable_if_trailing_non_type_parameter::AClass470893d53d1SChris Cotter AClass(int) : data(0) {}
471893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
472893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
473893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int) requires U::some_value : data(0) {}{{$}}
474893d53d1SChris Cotter
475893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClassenable_if_trailing_non_type_parameter::AClass476893d53d1SChris Cotter AClass(int, int) : AClass(0) {}
477893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
478893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
479893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int, int) requires U::some_value : AClass(0) {}{{$}}
480893d53d1SChris Cotter
481893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClassenable_if_trailing_non_type_parameter::AClass482893d53d1SChris Cotter AClass(int, int, int) : ABaseClass(0) {}
483893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
484893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
485893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int, int, int) requires U::some_value : ABaseClass(0) {}{{$}}
486893d53d1SChris Cotter
487893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClassenable_if_trailing_non_type_parameter::AClass488893d53d1SChris Cotter AClass(int, int, int, int) : data2(), data() {}
489893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
490893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
491893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int, int, int, int) requires U::some_value : data2(), data() {}{{$}}
492893d53d1SChris Cotter
493893d53d1SChris Cotter int data;
494893d53d1SChris Cotter int data2;
495893d53d1SChris Cotter };
496893d53d1SChris Cotter
497893d53d1SChris Cotter template <typename T>
498893d53d1SChris Cotter struct AClass2 : ABaseClass {
499893d53d1SChris Cotter
500893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClass2enable_if_trailing_non_type_parameter::AClass2501893d53d1SChris Cotter AClass2() {}
502893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
503893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
504893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass2() requires U::some_value {}{{$}}
505893d53d1SChris Cotter
506893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0>
AClass2enable_if_trailing_non_type_parameter::AClass2507893d53d1SChris Cotter AClass2(int) : data2(0) {}
508893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
509893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
510893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass2(int) requires U::some_value : data2(0) {}{{$}}
511893d53d1SChris Cotter
512893d53d1SChris Cotter int data = 10;
513893d53d1SChris Cotter int data2;
514893d53d1SChris Cotter int data3;
515893d53d1SChris Cotter };
516893d53d1SChris Cotter
517893d53d1SChris Cotter template <typename T, std::enable_if_t<T::some_value, T>* = 0>
pointer_type()518893d53d1SChris Cotter void pointer_type() {
519893d53d1SChris Cotter }
520893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
521893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
522893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void pointer_type() requires T::some_value {{{$}}
523893d53d1SChris Cotter
524893d53d1SChris Cotter template <typename T,
525893d53d1SChris Cotter std::enable_if_t<T::some_value, T>* = nullptr>
param_on_newline()526893d53d1SChris Cotter void param_on_newline() {
527893d53d1SChris Cotter }
528893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
529893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
530893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void param_on_newline() requires T::some_value {{{$}}
531893d53d1SChris Cotter
532893d53d1SChris Cotter template <typename T,
533893d53d1SChris Cotter typename U,
534893d53d1SChris Cotter std::enable_if_t<
535893d53d1SChris Cotter ConsumeVariadic<T,
536893d53d1SChris Cotter U>::value, T>* = nullptr>
param_split_on_two_lines()537893d53d1SChris Cotter void param_split_on_two_lines() {
538893d53d1SChris Cotter }
539893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-5]]:11: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
540893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T,{{$}}
541893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} typename U>{{$}}
542893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void param_split_on_two_lines() requires ConsumeVariadic<T,{{$}}
543893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} U>::value {{{$}}
544893d53d1SChris Cotter
545893d53d1SChris Cotter template <typename T, std::enable_if_t<T::some_value // comment
546893d53d1SChris Cotter >* = nullptr>
trailing_slash_slash_comment()547893d53d1SChris Cotter void trailing_slash_slash_comment() {
548893d53d1SChris Cotter }
549893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-4]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
550893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
551893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void trailing_slash_slash_comment() requires T::some_value // comment{{$}}
552893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} {{{$}}
553893d53d1SChris Cotter
554893d53d1SChris Cotter template <typename T, std::enable_if_t<T::some_value>* = nullptr, std::enable_if_t<T::another_value>* = nullptr>
two_enable_ifs()555893d53d1SChris Cotter void two_enable_ifs() {
556893d53d1SChris Cotter }
557893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:67: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
558893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T, std::enable_if_t<T::some_value>* = nullptr>{{$}}
559893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void two_enable_ifs() requires T::another_value {{{$}}
560893d53d1SChris Cotter
561893d53d1SChris Cotter ////////////////////////////////
562893d53d1SChris Cotter // Negative tests
563893d53d1SChris Cotter ////////////////////////////////
564893d53d1SChris Cotter
565893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> V = 0>
non_type_param_has_name()566893d53d1SChris Cotter void non_type_param_has_name() {
567893d53d1SChris Cotter }
568893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int>>
non_type_param_has_no_default()569893d53d1SChris Cotter void non_type_param_has_no_default() {
570893d53d1SChris Cotter }
571893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> V>
non_type_param_has_name_and_no_default()572893d53d1SChris Cotter void non_type_param_has_name_and_no_default() {
573893d53d1SChris Cotter }
574893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int>...>
non_type_variadic()575893d53d1SChris Cotter void non_type_variadic() {
576893d53d1SChris Cotter }
577893d53d1SChris Cotter template <typename U, std::enable_if_t<U::some_value, int> = 0, int = 0>
non_type_not_last()578893d53d1SChris Cotter void non_type_not_last() {
579893d53d1SChris Cotter }
580893d53d1SChris Cotter
581893d53d1SChris Cotter #define TEMPLATE_REQUIRES(U, IF) template <typename U, std::enable_if_t<IF, int> = 0>
TEMPLATE_REQUIRES(U,U::some_value)582893d53d1SChris Cotter TEMPLATE_REQUIRES(U, U::some_value)
583893d53d1SChris Cotter void macro_entire_enable_if() {
584893d53d1SChris Cotter }
585893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
586893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-5]]:56: note: expanded from macro 'TEMPLATE_REQUIRES'
587893d53d1SChris Cotter // CHECK-FIXES: {{^}}TEMPLATE_REQUIRES(U, U::some_value)
588893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void macro_entire_enable_if() {{{$}}
589893d53d1SChris Cotter
590893d53d1SChris Cotter #define CONDITION U::some_value
591893d53d1SChris Cotter template <typename U, std::enable_if_t<CONDITION, int> = 0>
macro_condition()592893d53d1SChris Cotter void macro_condition() {
593893d53d1SChris Cotter }
594893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
595893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename U>{{$}}
596893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void macro_condition() requires CONDITION {{{$}}
597893d53d1SChris Cotter
598893d53d1SChris Cotter #undef CONDITION
599893d53d1SChris Cotter #define CONDITION !U::some_value
600893d53d1SChris Cotter template <typename U, std::enable_if_t<CONDITION, int> = 0>
macro_condition_not_primary()601893d53d1SChris Cotter void macro_condition_not_primary() {
602893d53d1SChris Cotter }
603893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
604893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename U>{{$}}
605893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void macro_condition_not_primary() requires (CONDITION) {{{$}}
606893d53d1SChris Cotter
607893d53d1SChris Cotter } // namespace enable_if_trailing_non_type_parameter
608893d53d1SChris Cotter
609893d53d1SChris Cotter
610893d53d1SChris Cotter namespace enable_if_trailing_type_parameter {
611893d53d1SChris Cotter
612893d53d1SChris Cotter ////////////////////////////////
613893d53d1SChris Cotter // Section 3: enable_if as final template nameless defaulted type parameter
614893d53d1SChris Cotter ////////////////////////////////
615893d53d1SChris Cotter
616893d53d1SChris Cotter template <typename T, typename = std::enable_if<T::some_value>::type>
basic()617893d53d1SChris Cotter void basic() {
618893d53d1SChris Cotter }
619893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
620893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
621893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void basic() requires T::some_value {{{$}}
622893d53d1SChris Cotter
623893d53d1SChris Cotter template <typename T, typename = std::enable_if_t<T::some_value>>
basic_t()624893d53d1SChris Cotter void basic_t() {
625893d53d1SChris Cotter }
626893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
627893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
628893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void basic_t() requires T::some_value {{{$}}
629893d53d1SChris Cotter
630893d53d1SChris Cotter template <typename T, template <typename> class U, class V, typename = std::enable_if_t<T::some_value>>
basic_many_template_params()631893d53d1SChris Cotter void basic_many_template_params() {
632893d53d1SChris Cotter }
633893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:61: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
634893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T, template <typename> class U, class V>{{$}}
635893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void basic_many_template_params() requires T::some_value {{{$}}
636893d53d1SChris Cotter
637893d53d1SChris Cotter struct ABaseClass {
638893d53d1SChris Cotter ABaseClass();
639893d53d1SChris Cotter ABaseClass(int);
640893d53d1SChris Cotter };
641893d53d1SChris Cotter
642893d53d1SChris Cotter template <typename T>
643893d53d1SChris Cotter struct AClass : ABaseClass {
644893d53d1SChris Cotter template <typename = std::enable_if_t<T::some_value>>
no_other_template_paramsenable_if_trailing_type_parameter::AClass645893d53d1SChris Cotter void no_other_template_params() {
646893d53d1SChris Cotter }
647893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
648893d53d1SChris Cotter // CHECK-FIXES: {{^}} {{$}}
649893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} void no_other_template_params() requires T::some_value {{{$}}
650893d53d1SChris Cotter
651893d53d1SChris Cotter template <typename U, typename = std::enable_if_t<U::some_value>>
AClassenable_if_trailing_type_parameter::AClass652893d53d1SChris Cotter AClass() {}
653893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
654893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
655893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass() requires U::some_value {}{{$}}
656893d53d1SChris Cotter
657893d53d1SChris Cotter template <typename U, typename = std::enable_if_t<U::some_value>>
AClassenable_if_trailing_type_parameter::AClass658893d53d1SChris Cotter AClass(int) : data(0) {}
659893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
660893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
661893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int) requires U::some_value : data(0) {}{{$}}
662893d53d1SChris Cotter
663893d53d1SChris Cotter template <typename U, typename = std::enable_if_t<U::some_value>>
AClassenable_if_trailing_type_parameter::AClass664893d53d1SChris Cotter AClass(int, int) : AClass(0) {}
665893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
666893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
667893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int, int) requires U::some_value : AClass(0) {}{{$}}
668893d53d1SChris Cotter
669893d53d1SChris Cotter template <typename U, typename = std::enable_if_t<U::some_value>>
AClassenable_if_trailing_type_parameter::AClass670893d53d1SChris Cotter AClass(int, int, int) : ABaseClass(0) {}
671893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
672893d53d1SChris Cotter // CHECK-FIXES: {{^}} template <typename U>{{$}}
673893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} AClass(int, int, int) requires U::some_value : ABaseClass(0) {}{{$}}
674893d53d1SChris Cotter
675893d53d1SChris Cotter int data;
676893d53d1SChris Cotter };
677893d53d1SChris Cotter
678893d53d1SChris Cotter template <typename T, typename = std::enable_if_t<T::some_value>*>
pointer_type()679893d53d1SChris Cotter void pointer_type() {
680893d53d1SChris Cotter }
681893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
682893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
683893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void pointer_type() requires T::some_value {{{$}}
684893d53d1SChris Cotter
685893d53d1SChris Cotter template <typename T, typename = std::enable_if_t<T::some_value>&>
reference_type()686893d53d1SChris Cotter void reference_type() {
687893d53d1SChris Cotter }
688893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
689893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
690893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void reference_type() requires T::some_value {{{$}}
691893d53d1SChris Cotter
692893d53d1SChris Cotter template <typename T,
693893d53d1SChris Cotter typename = std::enable_if_t<T::some_value>*>
param_on_newline()694893d53d1SChris Cotter void param_on_newline() {
695893d53d1SChris Cotter }
696893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
697893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T>{{$}}
698893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void param_on_newline() requires T::some_value {{{$}}
699893d53d1SChris Cotter
700893d53d1SChris Cotter template <typename T,
701893d53d1SChris Cotter typename U,
702893d53d1SChris Cotter typename = std::enable_if_t<
703893d53d1SChris Cotter ConsumeVariadic<T,
704893d53d1SChris Cotter U>::value>>
param_split_on_two_lines()705893d53d1SChris Cotter void param_split_on_two_lines() {
706893d53d1SChris Cotter }
707893d53d1SChris Cotter // CHECK-MESSAGES: :[[@LINE-5]]:11: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
708893d53d1SChris Cotter // CHECK-FIXES: {{^}}template <typename T,{{$}}
709893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} typename U>{{$}}
710893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}}void param_split_on_two_lines() requires ConsumeVariadic<T,{{$}}
711893d53d1SChris Cotter // CHECK-FIXES-NEXT: {{^}} U>::value {{{$}}
712893d53d1SChris Cotter
713893d53d1SChris Cotter
714893d53d1SChris Cotter ////////////////////////////////
715893d53d1SChris Cotter // Negative tests
716893d53d1SChris Cotter ////////////////////////////////
717893d53d1SChris Cotter
718893d53d1SChris Cotter template <typename U, typename Named = std::enable_if_t<U::some_value>>
param_has_name()719893d53d1SChris Cotter void param_has_name() {
720893d53d1SChris Cotter }
721893d53d1SChris Cotter
722893d53d1SChris Cotter template <typename U, typename = std::enable_if_t<U::some_value>, typename = int>
not_last_param()723893d53d1SChris Cotter void not_last_param() {
724893d53d1SChris Cotter }
725893d53d1SChris Cotter
726893d53d1SChris Cotter } // namespace enable_if_trailing_type_parameter
727*ba344760SPiotr Zegar
728*ba344760SPiotr Zegar
729*ba344760SPiotr Zegar // Issue fixes:
730*ba344760SPiotr Zegar
731*ba344760SPiotr Zegar namespace PR91872 {
732*ba344760SPiotr Zegar
733*ba344760SPiotr Zegar enum expression_template_option { value1, value2 };
734*ba344760SPiotr Zegar
735*ba344760SPiotr Zegar template <typename T> struct number_category {
736*ba344760SPiotr Zegar static const int value = 0;
737*ba344760SPiotr Zegar };
738*ba344760SPiotr Zegar
739*ba344760SPiotr Zegar constexpr int number_kind_complex = 1;
740*ba344760SPiotr Zegar
741*ba344760SPiotr Zegar template <typename T, expression_template_option ExpressionTemplates>
742*ba344760SPiotr Zegar struct number {
743*ba344760SPiotr Zegar using type = T;
744*ba344760SPiotr Zegar };
745*ba344760SPiotr Zegar
746*ba344760SPiotr Zegar template <typename T> struct component_type {
747*ba344760SPiotr Zegar using type = T;
748*ba344760SPiotr Zegar };
749*ba344760SPiotr Zegar
750*ba344760SPiotr Zegar template <class T, expression_template_option ExpressionTemplates>
751*ba344760SPiotr Zegar inline typename std::enable_if<
752*ba344760SPiotr Zegar number_category<T>::value == number_kind_complex,
753*ba344760SPiotr Zegar component_type<number<T, ExpressionTemplates>>>::type::type
abs(const number<T,ExpressionTemplates> & v)754*ba344760SPiotr Zegar abs(const number<T, ExpressionTemplates> &v) {
755*ba344760SPiotr Zegar return {};
756*ba344760SPiotr Zegar }
757*ba344760SPiotr Zegar
758*ba344760SPiotr Zegar }
759