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>
neverok()9 void neverok() _diagnose_if(!T(), "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}}
10
11 template <typename T>
alwaysok()12 void alwaysok() _diagnose_if(T(), "oh no", "error") {}
13
14 template <typename T>
alwayswarn()15 void alwayswarn() _diagnose_if(!T(), "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}}
16
17 template <typename T>
neverwarn()18 void neverwarn() _diagnose_if(T(), "oh no", "warning") {}
19
runAll()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>
errorIf(T a)56 void errorIf(T a) _diagnose_if(T() != a, "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
57
58 template <typename T>
warnIf(T a)59 void warnIf(T a) _diagnose_if(T() != a, "oh no", "warning") {} // expected-note{{from 'diagnose_if'}}
60
runIf()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>
neverok()72 void neverok() _diagnose_if(N == 0 || N != 0, "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}}
73
74 template <int N>
alwaysok()75 void alwaysok() _diagnose_if(N == 0 && N != 0, "oh no", "error") {}
76
77 template <int N>
alwayswarn()78 void alwayswarn() _diagnose_if(N == 0 || N != 0, "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}}
79
80 template <int N>
neverwarn()81 void neverwarn() _diagnose_if(N == 0 && N != 0, "oh no", "warning") {}
82
runAll()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>
errorIf(int a)119 void errorIf(int a) _diagnose_if(N != a, "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
120
121 template <int N>
warnIf(int a)122 void warnIf(int a) _diagnose_if(N != a, "oh no", "warning") {} // expected-note{{from 'diagnose_if'}}
123
runIf()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
runAll()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
runAll()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
runFoo()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
runErrors()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
runWarnings()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
runAll()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
early()283 void early() {
284 bar();
285 bar(0);
286 bar(1);
287 }
288
foo()289 constexpr int foo() { return 1; }
foo(int a)290 constexpr int foo(int a) { return a; }
291
late()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;
Foolate_parsed::Foo302 constexpr Foo(int i): i(i) {}
isFooablelate_parsed::Foo303 constexpr bool isFooable() const { return i; }
304
golate_parsed::Foo305 void go() const _diagnose_if(isFooable(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
operator intlate_parsed::Foo306 operator int() const _diagnose_if(isFooable(), "oh no", "error") { return 1; } // expected-note{{from 'diagnose_if'}}
307
go2late_parsed::Foo308 void go2() const _diagnose_if(isFooable(), "oh no", "error") // expected-note{{from 'diagnose_if'}}
309 __attribute__((enable_if(true, ""))) {}
go2late_parsed::Foo310 void go2() const _diagnose_if(isFooable(), "oh no", "error") {}
311
go3late_parsed::Foo312 constexpr int go3() const _diagnose_if(isFooable(), "oh no", "error")
313 __attribute__((enable_if(true, ""))) {
314 return 1;
315 }
316
go4late_parsed::Foo317 constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error") {
318 return 1;
319 }
go4late_parsed::Foo320 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...
runGolate_parsed::Foo326 constexpr int runGo() const {
327 return go3() + go4();
328 }
329 };
330
go(const Foo & f)331 void go(const Foo &f) _diagnose_if(f.isFooable(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
332
run()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;
Foomember_templates::Foo351 constexpr Foo(int i): i(i) {}
badmember_templates::Foo352 constexpr bool bad() const { return i; }
353
getValmember_templates::Foo354 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>
getVal2member_templates::Foo359 constexpr T getVal2() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}}
360 return T();
361 }
362
363 template <typename T>
operator Tmember_templates::Foo364 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.
runmember_templates::Foo369 int run() { return getVal<int>() + getVal2<int>() + int(*this); }
370 };
371
run()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;
Foospecial_member_operators::Foo388 constexpr Foo(int i): i(i) {}
badspecial_member_operators::Foo389 constexpr bool bad() const { return i; }
operator ->special_member_operators::Foo390 const Bar *operator->() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}}
391 return nullptr;
392 }
operator ()special_member_operators::Foo393 void operator()() const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
394 };
395
396 struct ParenOverload {
397 int i;
ParenOverloadspecial_member_operators::ParenOverload398 constexpr ParenOverload(int i): i(i) {}
badspecial_member_operators::ParenOverload399 constexpr bool bad() const { return i; }
operator ()special_member_operators::ParenOverload400 void operator()(double) const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
operator ()special_member_operators::ParenOverload401 void operator()(int) const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
402 };
403
404 struct ParenTemplate {
405 int i;
ParenTemplatespecial_member_operators::ParenTemplate406 constexpr ParenTemplate(int i): i(i) {}
badspecial_member_operators::ParenTemplate407 constexpr bool bad() const { return i; }
408 template <typename T>
operator ()special_member_operators::ParenTemplate409 void operator()(T) const _diagnose_if(bad(), "oh no", "error") {} // expected-note 2{{from 'diagnose_if'}}
410 };
411
run()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
runLambda()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;
Bracketsspecial_member_operators::Brackets440 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
runBrackets(int i)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;
Unaryspecial_member_operators::Unary453 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
runUnary()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
runPostInc()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;
Fooctors::Foo479 constexpr Foo(int I): I(I) {}
480
operator =ctors::Foo481 constexpr const Foo &operator=(const Foo &) const
482 _diagnose_if(I, "oh no", "error") { // expected-note{{from 'diagnose_if'}}
483 return *this;
484 }
485
operator =ctors::Foo486 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;
Barctors::Bar494 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
run()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;
Fooref_init::Foo516 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
run()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
run()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
run()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
bar()559 void bar() { Foo f(1); } // expected-error{{oh no}}
560 }
561
562 namespace user_defined_conversion {
563 struct Foo {
564 int i;
Foouser_defined_conversion::Foo565 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
run()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
sizestd::initializer_list586 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
run()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;
Foorange_for_loop::adl::Foo609 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;
Barrange_for_loop::adl::Bar616 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
run()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"); // expected-note{{from 'diagnose_if'}}
638 };
639
640 struct Bar {
641 int j;
642 static void *operator new(size_t i) _diagnose_if(!i, "oh no", "warning");
643 };
644
run()645 void run() {
646 new Foo(); // expected-warning{{oh no}}
647 new Bar();
648 }
649 }
650
651 namespace contextual_implicit_conv {
652 struct Foo {
653 int i;
Foocontextual_implicit_conv::Foo654 constexpr Foo(int i): i(i) {}
operator intcontextual_implicit_conv::Foo655 constexpr operator int() const _diagnose_if(i == 1, "oh no", "warning") // expected-note{{from 'diagnose_if'}}
656 _diagnose_if(i == 2, "oh no", "error") { // expected-note{{from 'diagnose_if'}}
657 return i;
658 }
659 };
660
run()661 void run() {
662 switch (constexpr Foo i = 0) { default: break; }
663 switch (constexpr Foo i = 1) { default: break; } // expected-warning{{oh no}}
664 switch (constexpr Foo i = 2) { default: break; } // expected-error{{oh no}}
665 }
666 }
667