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