1 | // RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14 |
2 | |
3 | #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__))) |
4 | |
5 | using size_t = decltype(sizeof(int)); |
6 | |
7 | namespace type_dependent { |
8 | template <typename T> |
9 | void neverok() _diagnose_if(!T(), "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}} |
10 | |
11 | template <typename T> |
12 | void alwaysok() _diagnose_if(T(), "oh no", "error") {} |
13 | |
14 | template <typename T> |
15 | void alwayswarn() _diagnose_if(!T(), "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}} |
16 | |
17 | template <typename T> |
18 | void neverwarn() _diagnose_if(T(), "oh no", "warning") {} |
19 | |
20 | void runAll() { |
21 | alwaysok<int>(); |
22 | alwaysok<int>(); |
23 | |
24 | { |
25 | void (*pok)() = alwaysok<int>; |
26 | pok = &alwaysok<int>; |
27 | } |
28 | |
29 | neverok<int>(); // expected-error{{oh no}} |
30 | neverok<short>(); // expected-error{{oh no}} |
31 | |
32 | { |
33 | void (*pok)() = neverok<int>; // expected-error{{oh no}} |
34 | } |
35 | { |
36 | void (*pok)(); |
37 | pok = &neverok<int>; // expected-error{{oh no}} |
38 | } |
39 | |
40 | alwayswarn<int>(); // expected-warning{{oh no}} |
41 | alwayswarn<short>(); // expected-warning{{oh no}} |
42 | { |
43 | void (*pok)() = alwayswarn<int>; // expected-warning{{oh no}} |
44 | pok = &alwayswarn<int>; // expected-warning{{oh no}} |
45 | } |
46 | |
47 | neverwarn<int>(); |
48 | neverwarn<short>(); |
49 | { |
50 | void (*pok)() = neverwarn<int>; |
51 | pok = &neverwarn<int>; |
52 | } |
53 | } |
54 | |
55 | template <typename T> |
56 | void errorIf(T a) _diagnose_if(T() != a, "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
57 | |
58 | template <typename T> |
59 | void warnIf(T a) _diagnose_if(T() != a, "oh no", "warning") {} // expected-note{{from 'diagnose_if'}} |
60 | |
61 | void runIf() { |
62 | errorIf(0); |
63 | errorIf(1); // expected-error{{oh no}} |
64 | |
65 | warnIf(0); |
66 | warnIf(1); // expected-warning{{oh no}} |
67 | } |
68 | } |
69 | |
70 | namespace value_dependent { |
71 | template <int N> |
72 | void neverok() _diagnose_if(N == 0 || N != 0, "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}} |
73 | |
74 | template <int N> |
75 | void alwaysok() _diagnose_if(N == 0 && N != 0, "oh no", "error") {} |
76 | |
77 | template <int N> |
78 | void alwayswarn() _diagnose_if(N == 0 || N != 0, "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}} |
79 | |
80 | template <int N> |
81 | void neverwarn() _diagnose_if(N == 0 && N != 0, "oh no", "warning") {} |
82 | |
83 | void runAll() { |
84 | alwaysok<0>(); |
85 | alwaysok<1>(); |
86 | |
87 | { |
88 | void (*pok)() = alwaysok<0>; |
89 | pok = &alwaysok<0>; |
90 | } |
91 | |
92 | neverok<0>(); // expected-error{{oh no}} |
93 | neverok<1>(); // expected-error{{oh no}} |
94 | |
95 | { |
96 | void (*pok)() = neverok<0>; // expected-error{{oh no}} |
97 | } |
98 | { |
99 | void (*pok)(); |
100 | pok = &neverok<0>; // expected-error{{oh no}} |
101 | } |
102 | |
103 | alwayswarn<0>(); // expected-warning{{oh no}} |
104 | alwayswarn<1>(); // expected-warning{{oh no}} |
105 | { |
106 | void (*pok)() = alwayswarn<0>; // expected-warning{{oh no}} |
107 | pok = &alwayswarn<0>; // expected-warning{{oh no}} |
108 | } |
109 | |
110 | neverwarn<0>(); |
111 | neverwarn<1>(); |
112 | { |
113 | void (*pok)() = neverwarn<0>; |
114 | pok = &neverwarn<0>; |
115 | } |
116 | } |
117 | |
118 | template <int N> |
119 | void errorIf(int a) _diagnose_if(N != a, "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
120 | |
121 | template <int N> |
122 | void warnIf(int a) _diagnose_if(N != a, "oh no", "warning") {} // expected-note{{from 'diagnose_if'}} |
123 | |
124 | void runIf() { |
125 | errorIf<0>(0); |
126 | errorIf<0>(1); // expected-error{{oh no}} |
127 | |
128 | warnIf<0>(0); |
129 | warnIf<0>(1); // expected-warning{{oh no}} |
130 | } |
131 | } |
132 | |
133 | namespace no_overload_interaction { |
134 | void foo(int) _diagnose_if(1, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
135 | void foo(short); |
136 | |
137 | void bar(int); |
138 | void bar(short) _diagnose_if(1, "oh no", "error"); |
139 | |
140 | void fooArg(int a) _diagnose_if(a, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
141 | void fooArg(short); |
142 | |
143 | void barArg(int); |
144 | void barArg(short a) _diagnose_if(a, "oh no", "error"); |
145 | |
146 | void runAll() { |
147 | foo(1); // expected-error{{oh no}} |
148 | bar(1); |
149 | |
150 | fooArg(1); // expected-error{{oh no}} |
151 | barArg(1); |
152 | |
153 | auto p = foo; // expected-error{{incompatible initializer of type '<overloaded function type>'}} |
154 | } |
155 | } |
156 | |
157 | namespace with_default_args { |
158 | void foo(int a = 0) _diagnose_if(a, "oh no", "warning"); // expected-note 1{{from 'diagnose_if'}} |
159 | void bar(int a = 1) _diagnose_if(a, "oh no", "warning"); // expected-note 2{{from 'diagnose_if'}} |
160 | |
161 | void runAll() { |
162 | foo(); |
163 | foo(0); |
164 | foo(1); // expected-warning{{oh no}} |
165 | |
166 | bar(); // expected-warning{{oh no}} |
167 | bar(0); |
168 | bar(1); // expected-warning{{oh no}} |
169 | } |
170 | } |
171 | |
172 | namespace naked_mem_expr { |
173 | struct Foo { |
174 | void foo(int a) _diagnose_if(a, "should warn", "warning"); // expected-note{{from 'diagnose_if'}} |
175 | void bar(int a) _diagnose_if(a, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
176 | }; |
177 | |
178 | void runFoo() { |
179 | Foo().foo(0); |
180 | Foo().foo(1); // expected-warning{{should warn}} |
181 | |
182 | Foo().bar(0); |
183 | Foo().bar(1); // expected-error{{oh no}} |
184 | } |
185 | } |
186 | |
187 | namespace class_template { |
188 | template <typename T> |
189 | struct Errors { |
190 | void foo(int i) _diagnose_if(i, "bad i", "error"); // expected-note{{from 'diagnose_if'}} |
191 | void bar(int i) _diagnose_if(i != T(), "bad i", "error"); // expected-note{{from 'diagnose_if'}} |
192 | |
193 | void fooOvl(int i) _diagnose_if(i, "int bad i", "error"); // expected-note{{from 'diagnose_if'}} |
194 | void fooOvl(short i) _diagnose_if(i, "short bad i", "error"); // expected-note{{from 'diagnose_if'}} |
195 | |
196 | void barOvl(int i) _diagnose_if(i != T(), "int bad i", "error"); // expected-note{{from 'diagnose_if'}} |
197 | void barOvl(short i) _diagnose_if(i != T(), "short bad i", "error"); // expected-note{{from 'diagnose_if'}} |
198 | }; |
199 | |
200 | void runErrors() { |
201 | Errors<int>().foo(0); |
202 | Errors<int>().foo(1); // expected-error{{bad i}} |
203 | |
204 | Errors<int>().bar(0); |
205 | Errors<int>().bar(1); // expected-error{{bad i}} |
206 | |
207 | Errors<int>().fooOvl(0); |
208 | Errors<int>().fooOvl(1); // expected-error{{int bad i}} |
209 | Errors<int>().fooOvl(short(0)); |
210 | Errors<int>().fooOvl(short(1)); // expected-error{{short bad i}} |
211 | |
212 | Errors<int>().barOvl(0); |
213 | Errors<int>().barOvl(1); // expected-error{{int bad i}} |
214 | Errors<int>().barOvl(short(0)); |
215 | Errors<int>().barOvl(short(1)); // expected-error{{short bad i}} |
216 | } |
217 | |
218 | template <typename T> |
219 | struct Warnings { |
220 | void foo(int i) _diagnose_if(i, "bad i", "warning"); // expected-note{{from 'diagnose_if'}} |
221 | void bar(int i) _diagnose_if(i != T(), "bad i", "warning"); // expected-note{{from 'diagnose_if'}} |
222 | |
223 | void fooOvl(int i) _diagnose_if(i, "int bad i", "warning"); // expected-note{{from 'diagnose_if'}} |
224 | void fooOvl(short i) _diagnose_if(i, "short bad i", "warning"); // expected-note{{from 'diagnose_if'}} |
225 | |
226 | void barOvl(int i) _diagnose_if(i != T(), "int bad i", "warning"); // expected-note{{from 'diagnose_if'}} |
227 | void barOvl(short i) _diagnose_if(i != T(), "short bad i", "warning"); // expected-note{{from 'diagnose_if'}} |
228 | }; |
229 | |
230 | void runWarnings() { |
231 | Warnings<int>().foo(0); |
232 | Warnings<int>().foo(1); // expected-warning{{bad i}} |
233 | |
234 | Warnings<int>().bar(0); |
235 | Warnings<int>().bar(1); // expected-warning{{bad i}} |
236 | |
237 | Warnings<int>().fooOvl(0); |
238 | Warnings<int>().fooOvl(1); // expected-warning{{int bad i}} |
239 | Warnings<int>().fooOvl(short(0)); |
240 | Warnings<int>().fooOvl(short(1)); // expected-warning{{short bad i}} |
241 | |
242 | Warnings<int>().barOvl(0); |
243 | Warnings<int>().barOvl(1); // expected-warning{{int bad i}} |
244 | Warnings<int>().barOvl(short(0)); |
245 | Warnings<int>().barOvl(short(1)); // expected-warning{{short bad i}} |
246 | } |
247 | } |
248 | |
249 | namespace template_specialization { |
250 | template <typename T> |
251 | struct Foo { |
252 | void foo() _diagnose_if(1, "override me", "error"); // expected-note{{from 'diagnose_if'}} |
253 | void bar(int i) _diagnose_if(i, "bad i", "error"); // expected-note{{from 'diagnose_if'}} |
254 | void baz(int i); |
255 | }; |
256 | |
257 | template <> |
258 | struct Foo<int> { |
259 | void foo(); |
260 | void bar(int i); |
261 | void baz(int i) _diagnose_if(i, "bad i", "error"); // expected-note{{from 'diagnose_if'}} |
262 | }; |
263 | |
264 | void runAll() { |
265 | Foo<double>().foo(); // expected-error{{override me}} |
266 | Foo<int>().foo(); |
267 | |
268 | Foo<double>().bar(1); // expected-error{{bad i}} |
269 | Foo<int>().bar(1); |
270 | |
271 | Foo<double>().baz(1); |
272 | Foo<int>().baz(1); // expected-error{{bad i}} |
273 | } |
274 | } |
275 | |
276 | namespace late_constexpr { |
277 | constexpr int foo(); |
278 | constexpr int foo(int a); |
279 | |
280 | void bar() _diagnose_if(foo(), "bad foo", "error"); // expected-note{{from 'diagnose_if'}} |
281 | void bar(int a) _diagnose_if(foo(a), "bad foo", "error"); // expected-note{{from 'diagnose_if'}} |
282 | |
283 | void early() { |
284 | bar(); |
285 | bar(0); |
286 | bar(1); |
287 | } |
288 | |
289 | constexpr int foo() { return 1; } |
290 | constexpr int foo(int a) { return a; } |
291 | |
292 | void late() { |
293 | bar(); // expected-error{{bad foo}} |
294 | bar(0); |
295 | bar(1); // expected-error{{bad foo}} |
296 | } |
297 | } |
298 | |
299 | namespace late_parsed { |
300 | struct Foo { |
301 | int i; |
302 | constexpr Foo(int i): i(i) {} |
303 | constexpr bool isFooable() const { return i; } |
304 | |
305 | void go() const _diagnose_if(isFooable(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
306 | operator int() const _diagnose_if(isFooable(), "oh no", "error") { return 1; } // expected-note{{from 'diagnose_if'}} |
307 | |
308 | void go2() const _diagnose_if(isFooable(), "oh no", "error") // expected-note{{from 'diagnose_if'}} |
309 | __attribute__((enable_if(true, ""))) {} |
310 | void go2() const _diagnose_if(isFooable(), "oh no", "error") {} |
311 | |
312 | constexpr int go3() const _diagnose_if(isFooable(), "oh no", "error") |
313 | __attribute__((enable_if(true, ""))) { |
314 | return 1; |
315 | } |
316 | |
317 | constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error") { |
318 | return 1; |
319 | } |
320 | constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error") |
321 | __attribute__((enable_if(true, ""))) { |
322 | return 1; |
323 | } |
324 | |
325 | // We hope to support emitting these errors in the future. For now, though... |
326 | constexpr int runGo() const { |
327 | return go3() + go4(); |
328 | } |
329 | }; |
330 | |
331 | void go(const Foo &f) _diagnose_if(f.isFooable(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
332 | |
333 | void run() { |
334 | Foo(0).go(); |
335 | Foo(1).go(); // expected-error{{oh no}} |
336 | |
337 | (void)int(Foo(0)); |
338 | (void)int(Foo(1)); // expected-error{{oh no}} |
339 | |
340 | Foo(0).go2(); |
341 | Foo(1).go2(); // expected-error{{oh no}} |
342 | |
343 | go(Foo(0)); |
344 | go(Foo(1)); // expected-error{{oh no}} |
345 | } |
346 | } |
347 | |
348 | namespace member_templates { |
349 | struct Foo { |
350 | int i; |
351 | constexpr Foo(int i): i(i) {} |
352 | constexpr bool bad() const { return i; } |
353 | |
354 | template <typename T> T getVal() _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
355 | return T(); |
356 | } |
357 | |
358 | template <typename T> |
359 | constexpr T getVal2() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
360 | return T(); |
361 | } |
362 | |
363 | template <typename T> |
364 | constexpr operator T() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
365 | return T(); |
366 | } |
367 | |
368 | // We hope to support emitting these errors in the future. |
369 | int run() { return getVal<int>() + getVal2<int>() + int(*this); } |
370 | }; |
371 | |
372 | void run() { |
373 | Foo(0).getVal<int>(); |
374 | Foo(1).getVal<int>(); // expected-error{{oh no}} |
375 | |
376 | Foo(0).getVal2<int>(); |
377 | Foo(1).getVal2<int>(); // expected-error{{oh no}} |
378 | |
379 | (void)int(Foo(0)); |
380 | (void)int(Foo(1)); // expected-error{{oh no}} |
381 | } |
382 | } |
383 | |
384 | namespace special_member_operators { |
385 | struct Bar { int j; }; |
386 | struct Foo { |
387 | int i; |
388 | constexpr Foo(int i): i(i) {} |
389 | constexpr bool bad() const { return i; } |
390 | const Bar *operator->() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
391 | return nullptr; |
392 | } |
393 | void operator()() const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
394 | }; |
395 | |
396 | struct ParenOverload { |
397 | int i; |
398 | constexpr ParenOverload(int i): i(i) {} |
399 | constexpr bool bad() const { return i; } |
400 | void operator()(double) const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
401 | void operator()(int) const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
402 | }; |
403 | |
404 | struct ParenTemplate { |
405 | int i; |
406 | constexpr ParenTemplate(int i): i(i) {} |
407 | constexpr bool bad() const { return i; } |
408 | template <typename T> |
409 | void operator()(T) const _diagnose_if(bad(), "oh no", "error") {} // expected-note 2{{from 'diagnose_if'}} |
410 | }; |
411 | |
412 | void run() { |
413 | (void)Foo(0)->j; |
414 | (void)Foo(1)->j; // expected-error{{oh no}} |
415 | |
416 | Foo(0)(); |
417 | Foo(1)(); // expected-error{{oh no}} |
418 | |
419 | ParenOverload(0)(1); |
420 | ParenOverload(0)(1.); |
421 | |
422 | ParenOverload(1)(1); // expected-error{{oh no}} |
423 | ParenOverload(1)(1.); // expected-error{{oh no}} |
424 | |
425 | ParenTemplate(0)(1); |
426 | ParenTemplate(0)(1.); |
427 | |
428 | ParenTemplate(1)(1); // expected-error{{oh no}} |
429 | ParenTemplate(1)(1.); // expected-error{{oh no}} |
430 | } |
431 | |
432 | void runLambda() { |
433 | auto L1 = [](int i) _diagnose_if(i, "oh no", "error") {}; // expected-note{{from 'diagnose_if'}} |
434 | L1(0); |
435 | L1(1); // expected-error{{oh no}} |
436 | } |
437 | |
438 | struct Brackets { |
439 | int i; |
440 | constexpr Brackets(int i): i(i) {} |
441 | void operator[](int) _diagnose_if(i == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
442 | _diagnose_if(i == 2, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
443 | }; |
444 | |
445 | void runBrackets(int i) { |
446 | Brackets{0}[i]; |
447 | Brackets{1}[i]; // expected-warning{{oh no}} |
448 | Brackets{2}[i]; // expected-error{{oh no}} |
449 | } |
450 | |
451 | struct Unary { |
452 | int i; |
453 | constexpr Unary(int i): i(i) {} |
454 | void operator+() _diagnose_if(i == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
455 | _diagnose_if(i == 2, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
456 | }; |
457 | |
458 | void runUnary() { |
459 | +Unary{0}; |
460 | +Unary{1}; // expected-warning{{oh no}} |
461 | +Unary{2}; // expected-error{{oh no}} |
462 | } |
463 | |
464 | struct PostInc { |
465 | void operator++(int i) _diagnose_if(i == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
466 | _diagnose_if(i == 2, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
467 | }; |
468 | |
469 | void runPostInc() { |
470 | PostInc{}++; |
471 | PostInc{}.operator++(1); // expected-warning{{oh no}} |
472 | PostInc{}.operator++(2); // expected-error{{oh no}} |
473 | } |
474 | } |
475 | |
476 | namespace ctors { |
477 | struct Foo { |
478 | int I; |
479 | constexpr Foo(int I): I(I) {} |
480 | |
481 | constexpr const Foo &operator=(const Foo &) const |
482 | _diagnose_if(I, "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
483 | return *this; |
484 | } |
485 | |
486 | constexpr const Foo &operator=(const Foo &&) const |
487 | _diagnose_if(I, "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
488 | return *this; |
489 | } |
490 | }; |
491 | |
492 | struct Bar { |
493 | int I; |
494 | constexpr Bar(int I) _diagnose_if(I == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
495 | _diagnose_if(I == 2, "oh no", "error"): I(I) {} // expected-note{{from 'diagnose_if'}} |
496 | }; |
497 | |
498 | void run() { |
499 | constexpr Foo F{0}; |
500 | constexpr Foo F2{1}; |
501 | |
502 | F2 = F; // expected-error{{oh no}} |
503 | F2 = Foo{2}; // expected-error{{oh no}} |
504 | |
505 | Bar{0}; |
506 | Bar{1}; // expected-warning{{oh no}} |
507 | Bar{2}; // expected-error{{oh no}} |
508 | } |
509 | } |
510 | |
511 | namespace ref_init { |
512 | struct Bar {}; |
513 | struct Baz {}; |
514 | struct Foo { |
515 | int i; |
516 | constexpr Foo(int i): i(i) {} |
517 | operator const Bar &() const _diagnose_if(i, "oh no", "warning"); // expected-note{{from 'diagnose_if'}} |
518 | operator const Baz &() const _diagnose_if(i, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
519 | }; |
520 | void fooBar(const Bar &b); |
521 | void fooBaz(const Baz &b); |
522 | |
523 | void run() { |
524 | fooBar(Foo{0}); |
525 | fooBar(Foo{1}); // expected-warning{{oh no}} |
526 | fooBaz(Foo{0}); |
527 | fooBaz(Foo{1}); // expected-error{{oh no}} |
528 | } |
529 | } |
530 | |
531 | namespace udl { |
532 | void operator""_fn(char c)_diagnose_if(c == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
533 | _diagnose_if(c == 2, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
534 | |
535 | void run() { |
536 | '\0'_fn; |
537 | '\1'_fn; // expected-warning{{oh no}} |
538 | '\2'_fn; // expected-error{{oh no}} |
539 | } |
540 | } |
541 | |
542 | namespace PR31638 { |
543 | struct String { |
544 | String(char const* __s) _diagnose_if(__s == nullptr, "oh no ptr", "warning"); // expected-note{{from 'diagnose_if'}} |
545 | String(int __s) _diagnose_if(__s != 0, "oh no int", "warning"); // expected-note{{from 'diagnose_if'}} |
546 | }; |
547 | |
548 | void run() { |
549 | String s(nullptr); // expected-warning{{oh no ptr}} |
550 | String ss(42); // expected-warning{{oh no int}} |
551 | } |
552 | } |
553 | |
554 | namespace PR31639 { |
555 | struct Foo { |
556 | Foo(int I) __attribute__((diagnose_if(I, "oh no", "error"))); // expected-note{{from 'diagnose_if'}} |
557 | }; |
558 | |
559 | void bar() { Foo f(1); } // expected-error{{oh no}} |
560 | } |
561 | |
562 | namespace user_defined_conversion { |
563 | struct Foo { |
564 | int i; |
565 | constexpr Foo(int i): i(i) {} |
566 | operator size_t() const _diagnose_if(i == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
567 | _diagnose_if(i == 2, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
568 | }; |
569 | |
570 | void run() { |
571 | // `new T[N]`, where N is implicitly convertible to size_t, calls |
572 | // PerformImplicitConversion directly. This lets us test the diagnostic logic |
573 | // in PerformImplicitConversion. |
574 | new int[Foo{0}]; |
575 | new int[Foo{1}]; // expected-warning{{oh no}} |
576 | new int[Foo{2}]; // expected-error{{oh no}} |
577 | } |
578 | } |
579 | |
580 | namespace std { |
581 | template <typename T> |
582 | struct initializer_list { |
583 | const T *ptr; |
584 | size_t elems; |
585 | |
586 | constexpr size_t size() const { return elems; } |
587 | }; |
588 | } |
589 | |
590 | namespace initializer_lists { |
591 | struct Foo { |
592 | Foo(std::initializer_list<int> l) |
593 | _diagnose_if(l.size() == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
594 | _diagnose_if(l.size() == 2, "oh no", "error") {} // expected-note{{from 'diagnose_if'}} |
595 | }; |
596 | |
597 | void run() { |
598 | Foo{std::initializer_list<int>{}}; |
599 | Foo{std::initializer_list<int>{1}}; // expected-warning{{oh no}} |
600 | Foo{std::initializer_list<int>{1, 2}}; // expected-error{{oh no}} |
601 | Foo{std::initializer_list<int>{1, 2, 3}}; |
602 | } |
603 | } |
604 | |
605 | namespace range_for_loop { |
606 | namespace adl { |
607 | struct Foo { |
608 | int i; |
609 | constexpr Foo(int i): i(i) {} |
610 | }; |
611 | void **begin(const Foo &f) _diagnose_if(f.i, "oh no", "warning"); |
612 | void **end(const Foo &f) _diagnose_if(f.i, "oh no", "warning"); |
613 | |
614 | struct Bar { |
615 | int i; |
616 | constexpr Bar(int i): i(i) {} |
617 | }; |
618 | void **begin(const Bar &b) _diagnose_if(b.i, "oh no", "error"); |
619 | void **end(const Bar &b) _diagnose_if(b.i, "oh no", "error"); |
620 | } |
621 | |
622 | void run() { |
623 | for (void *p : adl::Foo(0)) {} |
624 | // FIXME: This should emit diagnostics. It seems that our constexpr |
625 | // evaluator isn't able to evaluate `adl::Foo(1)` as a constant, though. |
626 | for (void *p : adl::Foo(1)) {} |
627 | |
628 | for (void *p : adl::Bar(0)) {} |
629 | // FIXME: Same thing. |
630 | for (void *p : adl::Bar(1)) {} |
631 | } |
632 | } |
633 | |
634 | namespace operator_new { |
635 | struct Foo { |
636 | int j; |
637 | static void *operator new(size_t i) _diagnose_if(i, "oh no", "warning"); |
638 | }; |
639 | |
640 | struct Bar { |
641 | int j; |
642 | static void *operator new(size_t i) _diagnose_if(!i, "oh no", "warning"); |
643 | }; |
644 | |
645 | void run() { |
646 | // FIXME: This should emit a diagnostic. |
647 | new Foo(); |
648 | // This is here because we sometimes pass a dummy argument `operator new`. We |
649 | // should ignore this, rather than complaining about it. |
650 | new Bar(); |
651 | } |
652 | } |
653 | |
654 | namespace contextual_implicit_conv { |
655 | struct Foo { |
656 | int i; |
657 | constexpr Foo(int i): i(i) {} |
658 | constexpr operator int() const _diagnose_if(i == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}} |
659 | _diagnose_if(i == 2, "oh no", "error") { // expected-note{{from 'diagnose_if'}} |
660 | return i; |
661 | } |
662 | }; |
663 | |
664 | void run() { |
665 | switch (constexpr Foo i = 0) { default: break; } |
666 | switch (constexpr Foo i = 1) { default: break; } // expected-warning{{oh no}} |
667 | switch (constexpr Foo i = 2) { default: break; } // expected-error{{oh no}} |
668 | } |
669 | } |
670 | |