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