[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / SemaCXX / diagnose_if.cpp
blob21897c5184b73860e04cf69c8bb614d1c03cd52f
1 // RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14
3 #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__)))
5 using size_t = decltype(sizeof(int));
7 namespace type_dependent {
8 template <typename T>
9 void neverok() _diagnose_if(!T(), "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}}
11 template <typename T>
12 void alwaysok() _diagnose_if(T(), "oh no", "error") {}
14 template <typename T>
15 void alwayswarn() _diagnose_if(!T(), "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}}
17 template <typename T>
18 void neverwarn() _diagnose_if(T(), "oh no", "warning") {}
20 void runAll() {
21 alwaysok<int>();
22 alwaysok<int>();
25 void (*pok)() = alwaysok<int>;
26 pok = &alwaysok<int>;
29 neverok<int>(); // expected-error{{oh no}}
30 neverok<short>(); // expected-error{{oh no}}
33 void (*pok)() = neverok<int>; // expected-error{{oh no}}
36 void (*pok)();
37 pok = &neverok<int>; // expected-error{{oh no}}
40 alwayswarn<int>(); // expected-warning{{oh no}}
41 alwayswarn<short>(); // expected-warning{{oh no}}
43 void (*pok)() = alwayswarn<int>; // expected-warning{{oh no}}
44 pok = &alwayswarn<int>; // expected-warning{{oh no}}
47 neverwarn<int>();
48 neverwarn<short>();
50 void (*pok)() = neverwarn<int>;
51 pok = &neverwarn<int>;
55 template <typename T>
56 void errorIf(T a) _diagnose_if(T() != a, "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
58 template <typename T>
59 void warnIf(T a) _diagnose_if(T() != a, "oh no", "warning") {} // expected-note{{from 'diagnose_if'}}
61 void runIf() {
62 errorIf(0);
63 errorIf(1); // expected-error{{oh no}}
65 warnIf(0);
66 warnIf(1); // expected-warning{{oh no}}
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'}}
74 template <int N>
75 void alwaysok() _diagnose_if(N == 0 && N != 0, "oh no", "error") {}
77 template <int N>
78 void alwayswarn() _diagnose_if(N == 0 || N != 0, "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}}
80 template <int N>
81 void neverwarn() _diagnose_if(N == 0 && N != 0, "oh no", "warning") {}
83 void runAll() {
84 alwaysok<0>();
85 alwaysok<1>();
88 void (*pok)() = alwaysok<0>;
89 pok = &alwaysok<0>;
92 neverok<0>(); // expected-error{{oh no}}
93 neverok<1>(); // expected-error{{oh no}}
96 void (*pok)() = neverok<0>; // expected-error{{oh no}}
99 void (*pok)();
100 pok = &neverok<0>; // expected-error{{oh no}}
103 alwayswarn<0>(); // expected-warning{{oh no}}
104 alwayswarn<1>(); // expected-warning{{oh no}}
106 void (*pok)() = alwayswarn<0>; // expected-warning{{oh no}}
107 pok = &alwayswarn<0>; // expected-warning{{oh no}}
110 neverwarn<0>();
111 neverwarn<1>();
113 void (*pok)() = neverwarn<0>;
114 pok = &neverwarn<0>;
118 template <int N>
119 void errorIf(int a) _diagnose_if(N != a, "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
121 template <int N>
122 void warnIf(int a) _diagnose_if(N != a, "oh no", "warning") {} // expected-note{{from 'diagnose_if'}}
124 void runIf() {
125 errorIf<0>(0);
126 errorIf<0>(1); // expected-error{{oh no}}
128 warnIf<0>(0);
129 warnIf<0>(1); // expected-warning{{oh no}}
133 namespace no_overload_interaction {
134 void foo(int) _diagnose_if(1, "oh no", "error"); // expected-note{{from 'diagnose_if'}}
135 void foo(short);
137 void bar(int);
138 void bar(short) _diagnose_if(1, "oh no", "error");
140 void fooArg(int a) _diagnose_if(a, "oh no", "error"); // expected-note{{from 'diagnose_if'}}
141 void fooArg(short);
143 void barArg(int);
144 void barArg(short a) _diagnose_if(a, "oh no", "error");
146 void runAll() {
147 foo(1); // expected-error{{oh no}}
148 bar(1);
150 fooArg(1); // expected-error{{oh no}}
151 barArg(1);
153 auto p = foo; // expected-error{{incompatible initializer of type '<overloaded function type>'}}
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'}}
161 void runAll() {
162 foo();
163 foo(0);
164 foo(1); // expected-warning{{oh no}}
166 bar(); // expected-warning{{oh no}}
167 bar(0);
168 bar(1); // expected-warning{{oh no}}
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'}}
178 void runFoo() {
179 Foo().foo(0);
180 Foo().foo(1); // expected-warning{{should warn}}
182 Foo().bar(0);
183 Foo().bar(1); // expected-error{{oh no}}
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'}}
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'}}
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'}}
200 void runErrors() {
201 Errors<int>().foo(0);
202 Errors<int>().foo(1); // expected-error{{bad i}}
204 Errors<int>().bar(0);
205 Errors<int>().bar(1); // expected-error{{bad i}}
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}}
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}}
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'}}
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'}}
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'}}
230 void runWarnings() {
231 Warnings<int>().foo(0);
232 Warnings<int>().foo(1); // expected-warning{{bad i}}
234 Warnings<int>().bar(0);
235 Warnings<int>().bar(1); // expected-warning{{bad i}}
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}}
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}}
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);
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'}}
264 void runAll() {
265 Foo<double>().foo(); // expected-error{{override me}}
266 Foo<int>().foo();
268 Foo<double>().bar(1); // expected-error{{bad i}}
269 Foo<int>().bar(1);
271 Foo<double>().baz(1);
272 Foo<int>().baz(1); // expected-error{{bad i}}
276 namespace late_constexpr {
277 constexpr int foo();
278 constexpr int foo(int a);
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'}}
283 void early() {
284 bar();
285 bar(0);
286 bar(1);
289 constexpr int foo() { return 1; }
290 constexpr int foo(int a) { return a; }
292 void late() {
293 bar(); // expected-error{{bad foo}}
294 bar(0);
295 bar(1); // expected-error{{bad foo}}
299 namespace late_parsed {
300 struct Foo {
301 int i;
302 constexpr Foo(int i): i(i) {}
303 constexpr bool isFooable() const { return i; }
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'}}
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") {}
312 constexpr int go3() const _diagnose_if(isFooable(), "oh no", "error")
313 __attribute__((enable_if(true, ""))) {
314 return 1;
317 constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error") {
318 return 1;
320 constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error")
321 __attribute__((enable_if(true, ""))) {
322 return 1;
325 // We hope to support emitting these errors in the future. For now, though...
326 constexpr int runGo() const {
327 return go3() + go4();
331 void go(const Foo &f) _diagnose_if(f.isFooable(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
333 void run() {
334 Foo(0).go();
335 Foo(1).go(); // expected-error{{oh no}}
337 (void)int(Foo(0));
338 (void)int(Foo(1)); // expected-error{{oh no}}
340 Foo(0).go2();
341 Foo(1).go2(); // expected-error{{oh no}}
343 go(Foo(0));
344 go(Foo(1)); // expected-error{{oh no}}
348 namespace member_templates {
349 struct Foo {
350 int i;
351 constexpr Foo(int i): i(i) {}
352 constexpr bool bad() const { return i; }
354 template <typename T> T getVal() _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}}
355 return T();
358 template <typename T>
359 constexpr T getVal2() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}}
360 return T();
363 template <typename T>
364 constexpr operator T() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{from 'diagnose_if'}}
365 return T();
368 // We hope to support emitting these errors in the future.
369 int run() { return getVal<int>() + getVal2<int>() + int(*this); }
372 void run() {
373 Foo(0).getVal<int>();
374 Foo(1).getVal<int>(); // expected-error{{oh no}}
376 Foo(0).getVal2<int>();
377 Foo(1).getVal2<int>(); // expected-error{{oh no}}
379 (void)int(Foo(0));
380 (void)int(Foo(1)); // expected-error{{oh no}}
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;
393 void operator()() const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}}
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'}}
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'}}
412 void run() {
413 (void)Foo(0)->j;
414 (void)Foo(1)->j; // expected-error{{oh no}}
416 Foo(0)();
417 Foo(1)(); // expected-error{{oh no}}
419 ParenOverload(0)(1);
420 ParenOverload(0)(1.);
422 ParenOverload(1)(1); // expected-error{{oh no}}
423 ParenOverload(1)(1.); // expected-error{{oh no}}
425 ParenTemplate(0)(1);
426 ParenTemplate(0)(1.);
428 ParenTemplate(1)(1); // expected-error{{oh no}}
429 ParenTemplate(1)(1.); // expected-error{{oh no}}
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}}
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'}}
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}}
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'}}
458 void runUnary() {
459 +Unary{0};
460 +Unary{1}; // expected-warning{{oh no}}
461 +Unary{2}; // expected-error{{oh no}}
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'}}
469 void runPostInc() {
470 PostInc{}++;
471 PostInc{}.operator++(1); // expected-warning{{oh no}}
472 PostInc{}.operator++(2); // expected-error{{oh no}}
476 namespace ctors {
477 struct Foo {
478 int I;
479 constexpr Foo(int I): I(I) {}
481 constexpr const Foo &operator=(const Foo &) const
482 _diagnose_if(I, "oh no", "error") { // expected-note{{from 'diagnose_if'}}
483 return *this;
486 constexpr const Foo &operator=(const Foo &&) const
487 _diagnose_if(I, "oh no", "error") { // expected-note{{from 'diagnose_if'}}
488 return *this;
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'}}
498 void run() {
499 constexpr Foo F{0};
500 constexpr Foo F2{1};
502 F2 = F; // expected-error{{oh no}}
503 F2 = Foo{2}; // expected-error{{oh no}}
505 Bar{0};
506 Bar{1}; // expected-warning{{oh no}}
507 Bar{2}; // expected-error{{oh no}}
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'}}
520 void fooBar(const Bar &b);
521 void fooBaz(const Baz &b);
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}}
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'}}
535 void run() {
536 '\0'_fn;
537 '\1'_fn; // expected-warning{{oh no}}
538 '\2'_fn; // expected-error{{oh no}}
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'}}
548 void run() {
549 String s(nullptr); // expected-warning{{oh no ptr}}
550 String ss(42); // expected-warning{{oh no int}}
554 namespace PR31639 {
555 struct Foo {
556 Foo(int I) __attribute__((diagnose_if(I, "oh no", "error"))); // expected-note{{from 'diagnose_if'}}
559 void bar() { Foo f(1); } // expected-error{{oh no}}
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'}}
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}}
580 namespace std {
581 template <typename T>
582 struct initializer_list {
583 const T *ptr;
584 size_t elems;
586 constexpr size_t size() const { return elems; }
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'}}
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}};
605 namespace range_for_loop {
606 namespace adl {
607 struct Foo {
608 int i;
609 constexpr Foo(int i): i(i) {}
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");
614 struct Bar {
615 int i;
616 constexpr Bar(int i): i(i) {}
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");
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)) {}
628 for (void *p : adl::Bar(0)) {}
629 // FIXME: Same thing.
630 for (void *p : adl::Bar(1)) {}
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'}}
640 struct Bar {
641 int j;
642 static void *operator new(size_t i) _diagnose_if(!i, "oh no", "warning");
645 void run() {
646 new Foo(); // expected-warning{{oh no}}
647 new Bar();
651 namespace contextual_implicit_conv {
652 struct Foo {
653 int i;
654 constexpr Foo(int i): i(i) {}
655 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;
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}}