// RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14 #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__))) namespace type_dependent { template void neverok() _diagnose_if(!T(), "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}} template void alwaysok() _diagnose_if(T(), "oh no", "error") {} template void alwayswarn() _diagnose_if(!T(), "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}} template void neverwarn() _diagnose_if(T(), "oh no", "warning") {} void runAll() { alwaysok(); alwaysok(); { void (*pok)() = alwaysok; pok = &alwaysok; } neverok(); // expected-error{{oh no}} neverok(); // expected-error{{oh no}} { void (*pok)() = neverok; // expected-error{{oh no}} } { void (*pok)(); pok = &neverok; // expected-error{{oh no}} } alwayswarn(); // expected-warning{{oh no}} alwayswarn(); // expected-warning{{oh no}} { void (*pok)() = alwayswarn; // expected-warning{{oh no}} pok = &alwayswarn; // expected-warning{{oh no}} } neverwarn(); neverwarn(); { void (*pok)() = neverwarn; pok = &neverwarn; } } template void errorIf(T a) _diagnose_if(T() != a, "oh no", "error") {} // expected-note {{candidate disabled: oh no}} template void warnIf(T a) _diagnose_if(T() != a, "oh no", "warning") {} // expected-note {{from 'diagnose_if'}} void runIf() { errorIf(0); errorIf(1); // expected-error{{call to unavailable function}} warnIf(0); warnIf(1); // expected-warning{{oh no}} } } namespace value_dependent { template void neverok() _diagnose_if(N == 0 || N != 0, "oh no", "error") {} // expected-note 4{{from 'diagnose_if'}} template void alwaysok() _diagnose_if(N == 0 && N != 0, "oh no", "error") {} template void alwayswarn() _diagnose_if(N == 0 || N != 0, "oh no", "warning") {} // expected-note 4{{from 'diagnose_if'}} template void neverwarn() _diagnose_if(N == 0 && N != 0, "oh no", "warning") {} void runAll() { alwaysok<0>(); alwaysok<1>(); { void (*pok)() = alwaysok<0>; pok = &alwaysok<0>; } neverok<0>(); // expected-error{{oh no}} neverok<1>(); // expected-error{{oh no}} { void (*pok)() = neverok<0>; // expected-error{{oh no}} } { void (*pok)(); pok = &neverok<0>; // expected-error{{oh no}} } alwayswarn<0>(); // expected-warning{{oh no}} alwayswarn<1>(); // expected-warning{{oh no}} { void (*pok)() = alwayswarn<0>; // expected-warning{{oh no}} pok = &alwayswarn<0>; // expected-warning{{oh no}} } neverwarn<0>(); neverwarn<1>(); { void (*pok)() = neverwarn<0>; pok = &neverwarn<0>; } } template void errorIf(int a) _diagnose_if(N != a, "oh no", "error") {} // expected-note {{candidate disabled: oh no}} template void warnIf(int a) _diagnose_if(N != a, "oh no", "warning") {} // expected-note {{from 'diagnose_if'}} void runIf() { errorIf<0>(0); errorIf<0>(1); // expected-error{{call to unavailable function}} warnIf<0>(0); warnIf<0>(1); // expected-warning{{oh no}} } } namespace no_overload_interaction { void foo(int) _diagnose_if(1, "oh no", "error"); // expected-note{{from 'diagnose_if'}} void foo(short); void bar(int); void bar(short) _diagnose_if(1, "oh no", "error"); void fooArg(int a) _diagnose_if(a, "oh no", "error"); // expected-note{{candidate disabled: oh no}} void fooArg(short); // expected-note{{candidate function}} void barArg(int); void barArg(short a) _diagnose_if(a, "oh no", "error"); void runAll() { foo(1); // expected-error{{oh no}} bar(1); fooArg(1); // expected-error{{call to unavailable function}} barArg(1); auto p = foo; // expected-error{{incompatible initializer of type ''}} } } namespace with_default_args { void foo(int a = 0) _diagnose_if(a, "oh no", "warning"); // expected-note 1{{from 'diagnose_if'}} void bar(int a = 1) _diagnose_if(a, "oh no", "warning"); // expected-note 2{{from 'diagnose_if'}} void runAll() { foo(); foo(0); foo(1); // expected-warning{{oh no}} bar(); // expected-warning{{oh no}} bar(0); bar(1); // expected-warning{{oh no}} } } namespace naked_mem_expr { struct Foo { void foo(int a) _diagnose_if(a, "should warn", "warning"); // expected-note{{from 'diagnose_if'}} void bar(int a) _diagnose_if(a, "oh no", "error"); // expected-note{{from 'diagnose_if'}} }; void runFoo() { Foo().foo(0); Foo().foo(1); // expected-warning{{should warn}} Foo().bar(0); Foo().bar(1); // expected-error{{oh no}} } } namespace class_template { template struct Errors { void foo(int i) _diagnose_if(i, "bad i", "error"); // expected-note{{from 'diagnose_if'}} void bar(int i) _diagnose_if(i != T(), "bad i", "error"); // expected-note{{from 'diagnose_if'}} void fooOvl(int i) _diagnose_if(i, "int bad i", "error"); // expected-note 2{{int bad i}} void fooOvl(short i) _diagnose_if(i, "short bad i", "error"); // expected-note 2{{short bad i}} void barOvl(int i) _diagnose_if(i != T(), "int bad i", "error"); // expected-note 2{{int bad i}} void barOvl(short i) _diagnose_if(i != T(), "short bad i", "error"); // expected-note 2{{short bad i}} }; void runErrors() { Errors().foo(0); Errors().foo(1); // expected-error{{bad i}} Errors().bar(0); Errors().bar(1); // expected-error{{bad i}} Errors().fooOvl(0); Errors().fooOvl(1); // expected-error{{call to unavailable}} Errors().fooOvl(short(0)); Errors().fooOvl(short(1)); // expected-error{{call to unavailable}} Errors().barOvl(0); Errors().barOvl(1); // expected-error{{call to unavailable}} Errors().barOvl(short(0)); Errors().barOvl(short(1)); // expected-error{{call to unavailable}} } template struct Warnings { void foo(int i) _diagnose_if(i, "bad i", "warning"); // expected-note{{from 'diagnose_if'}} void bar(int i) _diagnose_if(i != T(), "bad i", "warning"); // expected-note{{from 'diagnose_if'}} void fooOvl(int i) _diagnose_if(i, "int bad i", "warning"); // expected-note{{from 'diagnose_if'}} void fooOvl(short i) _diagnose_if(i, "short bad i", "warning"); // expected-note{{from 'diagnose_if'}} void barOvl(int i) _diagnose_if(i != T(), "int bad i", "warning"); // expected-note{{from 'diagnose_if'}} void barOvl(short i) _diagnose_if(i != T(), "short bad i", "warning"); // expected-note{{from 'diagnose_if'}} }; void runWarnings() { Warnings().foo(0); Warnings().foo(1); // expected-warning{{bad i}} Warnings().bar(0); Warnings().bar(1); // expected-warning{{bad i}} Warnings().fooOvl(0); Warnings().fooOvl(1); // expected-warning{{int bad i}} Warnings().fooOvl(short(0)); Warnings().fooOvl(short(1)); // expected-warning{{short bad i}} Warnings().barOvl(0); Warnings().barOvl(1); // expected-warning{{int bad i}} Warnings().barOvl(short(0)); Warnings().barOvl(short(1)); // expected-warning{{short bad i}} } } namespace template_specialization { template struct Foo { void foo() _diagnose_if(1, "override me", "error"); // expected-note{{from 'diagnose_if'}} void bar(int i) _diagnose_if(i, "bad i", "error"); // expected-note{{from 'diagnose_if'}} void baz(int i); }; template <> struct Foo { void foo(); void bar(int i); void baz(int i) _diagnose_if(i, "bad i", "error"); // expected-note{{from 'diagnose_if'}} }; void runAll() { Foo().foo(); // expected-error{{override me}} Foo().foo(); Foo().bar(1); // expected-error{{bad i}} Foo().bar(1); Foo().baz(1); Foo().baz(1); // expected-error{{bad i}} } } namespace late_constexpr { constexpr int foo(); constexpr int foo(int a); void bar() _diagnose_if(foo(), "bad foo", "error"); // expected-note{{from 'diagnose_if'}} expected-note{{not viable: requires 0 arguments}} void bar(int a) _diagnose_if(foo(a), "bad foo", "error"); // expected-note{{bad foo}} void early() { bar(); bar(0); bar(1); } constexpr int foo() { return 1; } constexpr int foo(int a) { return a; } void late() { bar(); // expected-error{{bad foo}} bar(0); bar(1); // expected-error{{call to unavailable function}} } } namespace late_parsed { struct Foo { int i; constexpr Foo(int i): i(i) {} constexpr bool isFooable() const { return i; } void go() const _diagnose_if(isFooable(), "oh no", "error") {} // expected-note{{from 'diagnose_if'}} operator int() const _diagnose_if(isFooable(), "oh no", "error") { return 1; } // expected-note{{oh no}} void go2() const _diagnose_if(isFooable(), "oh no", "error") // expected-note{{oh no}} __attribute__((enable_if(true, ""))) {} void go2() const _diagnose_if(isFooable(), "oh no", "error") {} // expected-note{{oh no}} constexpr int go3() const _diagnose_if(isFooable(), "oh no", "error") __attribute__((enable_if(true, ""))) { return 1; } constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error") { return 1; } constexpr int go4() const _diagnose_if(isFooable(), "oh no", "error") __attribute__((enable_if(true, ""))) { return 1; } // We hope to support emitting these errors in the future. For now, though... constexpr int runGo() const { return go3() + go4(); } }; void go(const Foo &f) _diagnose_if(f.isFooable(), "oh no", "error") {} // expected-note{{oh no}} void run() { Foo(0).go(); Foo(1).go(); // expected-error{{oh no}} (void)int(Foo(0)); (void)int(Foo(1)); // expected-error{{uses deleted function}} Foo(0).go2(); Foo(1).go2(); // expected-error{{call to unavailable member function}} go(Foo(0)); go(Foo(1)); // expected-error{{call to unavailable function}} } } namespace member_templates { struct Foo { int i; constexpr Foo(int i): i(i) {} constexpr bool bad() const { return i; } template T getVal() _diagnose_if(bad(), "oh no", "error") { // expected-note{{oh no}} return T(); } template constexpr T getVal2() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{oh no}} return T(); } template constexpr operator T() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{oh no}} return T(); } // We hope to support emitting these errors in the future. int run() { return getVal() + getVal2() + int(*this); } }; void run() { Foo(0).getVal(); Foo(1).getVal(); // expected-error{{call to unavailable member function}} Foo(0).getVal2(); Foo(1).getVal2(); // expected-error{{call to unavailable member function}} (void)int(Foo(0)); (void)int(Foo(1)); // expected-error{{uses deleted function}} } } namespace special_member_operators { struct Bar { int j; }; struct Foo { int i; constexpr Foo(int i): i(i) {} constexpr bool bad() const { return i; } const Bar *operator->() const _diagnose_if(bad(), "oh no", "error") { // expected-note{{oh no}} return nullptr; } void operator()() const _diagnose_if(bad(), "oh no", "error") {} // expected-note{{oh no}} }; struct ParenOverload { int i; constexpr ParenOverload(int i): i(i) {} constexpr bool bad() const { return i; } void operator()(double) const _diagnose_if(bad(), "oh no", "error") {} // expected-note 2{{oh no}} void operator()(int) const _diagnose_if(bad(), "oh no", "error") {} // expected-note 2{{oh no}} }; struct ParenTemplate { int i; constexpr ParenTemplate(int i): i(i) {} constexpr bool bad() const { return i; } template void operator()(T) const _diagnose_if(bad(), "oh no", "error") {} // expected-note 2{{oh no}} }; void run() { (void)Foo(0)->j; (void)Foo(1)->j; // expected-error{{selected unavailable operator '->'}} Foo(0)(); Foo(1)(); // expected-error{{unavailable function call operator}} ParenOverload(0)(1); ParenOverload(0)(1.); ParenOverload(1)(1); // expected-error{{unavailable function call operator}} ParenOverload(1)(1.); // expected-error{{unavailable function call operator}} ParenTemplate(0)(1); ParenTemplate(0)(1.); ParenTemplate(1)(1); // expected-error{{unavailable function call operator}} ParenTemplate(1)(1.); // expected-error{{unavailable function call operator}} } void runLambda() { auto L1 = [](int i) _diagnose_if(i, "oh no", "error") {}; // expected-note{{oh no}} expected-note{{conversion candidate}} L1(0); L1(1); // expected-error{{call to unavailable function call}} } } namespace ctors { struct Foo { int I; constexpr Foo(int I): I(I) {} constexpr const Foo &operator=(const Foo &) const // expected-note 2{{disabled: oh no}} _diagnose_if(I, "oh no", "error") { return *this; } constexpr const Foo &operator=(const Foo &&) const // expected-note{{disabled: oh no}} expected-note{{no known conversion}} _diagnose_if(I, "oh no", "error") { return *this; } }; void run() { constexpr Foo F{0}; constexpr Foo F2{1}; F2 = F; // expected-error{{selected unavailable operator}} F2 = Foo{2}; // expected-error{{selected unavailable operator}} } }