#define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__)))
using size_t = decltype(sizeof(int));
namespace type_dependent {
template <typename T>
void neverok() _diagnose_if(!T(), "oh no", "error") {}
template <typename T>
void alwaysok() _diagnose_if(T(), "oh no", "error") {}
template <typename T>
void alwayswarn() _diagnose_if(!T(), "oh no", "warning") {}
template <typename T>
void neverwarn() _diagnose_if(T(), "oh no", "warning") {}
void runAll() {
alwaysok<int>();
alwaysok<int>();
{
void (*pok)() = alwaysok<int>;
pok = &alwaysok<int>;
}
neverok<int>(); neverok<short>();
{
void (*pok)() = neverok<int>; }
{
void (*pok)();
pok = &neverok<int>; }
alwayswarn<int>(); alwayswarn<short>(); {
void (*pok)() = alwayswarn<int>; pok = &alwayswarn<int>; }
neverwarn<int>();
neverwarn<short>();
{
void (*pok)() = neverwarn<int>;
pok = &neverwarn<int>;
}
}
template <typename T>
void errorIf(T a) _diagnose_if(T() != a, "oh no", "error") {}
template <typename T>
void warnIf(T a) _diagnose_if(T() != a, "oh no", "warning") {}
void runIf() {
errorIf(0);
errorIf(1);
warnIf(0);
warnIf(1); }
}
namespace value_dependent {
template <int N>
void neverok() _diagnose_if(N == 0 || N != 0, "oh no", "error") {}
template <int N>
void alwaysok() _diagnose_if(N == 0 && N != 0, "oh no", "error") {}
template <int N>
void alwayswarn() _diagnose_if(N == 0 || N != 0, "oh no", "warning") {}
template <int N>
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>(); neverok<1>();
{
void (*pok)() = neverok<0>; }
{
void (*pok)();
pok = &neverok<0>; }
alwayswarn<0>(); alwayswarn<1>(); {
void (*pok)() = alwayswarn<0>; pok = &alwayswarn<0>; }
neverwarn<0>();
neverwarn<1>();
{
void (*pok)() = neverwarn<0>;
pok = &neverwarn<0>;
}
}
template <int N>
void errorIf(int a) _diagnose_if(N != a, "oh no", "error") {}
template <int N>
void warnIf(int a) _diagnose_if(N != a, "oh no", "warning") {}
void runIf() {
errorIf<0>(0);
errorIf<0>(1);
warnIf<0>(0);
warnIf<0>(1); }
}
namespace no_overload_interaction {
void foo(int) _diagnose_if(1, "oh no", "error"); 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"); void fooArg(short);
void barArg(int);
void barArg(short a) _diagnose_if(a, "oh no", "error");
void runAll() {
foo(1); bar(1);
fooArg(1); barArg(1);
auto p = foo; }
}
namespace with_default_args {
void foo(int a = 0) _diagnose_if(a, "oh no", "warning"); void bar(int a = 1) _diagnose_if(a, "oh no", "warning");
void runAll() {
foo();
foo(0);
foo(1);
bar(); bar(0);
bar(1); }
}
namespace naked_mem_expr {
struct Foo {
void foo(int a) _diagnose_if(a, "should warn", "warning"); void bar(int a) _diagnose_if(a, "oh no", "error"); };
void runFoo() {
Foo().foo(0);
Foo().foo(1);
Foo().bar(0);
Foo().bar(1); }
}
namespace class_template {
template <typename T>
struct Errors {
void foo(int i) _diagnose_if(i, "bad i", "error"); void bar(int i) _diagnose_if(i != T(), "bad i", "error");
void fooOvl(int i) _diagnose_if(i, "int bad i", "error"); void fooOvl(short i) _diagnose_if(i, "short bad i", "error");
void barOvl(int i) _diagnose_if(i != T(), "int bad i", "error"); void barOvl(short i) _diagnose_if(i != T(), "short bad i", "error"); };
void runErrors() {
Errors<int>().foo(0);
Errors<int>().foo(1);
Errors<int>().bar(0);
Errors<int>().bar(1);
Errors<int>().fooOvl(0);
Errors<int>().fooOvl(1); Errors<int>().fooOvl(short(0));
Errors<int>().fooOvl(short(1));
Errors<int>().barOvl(0);
Errors<int>().barOvl(1); Errors<int>().barOvl(short(0));
Errors<int>().barOvl(short(1)); }
template <typename T>
struct Warnings {
void foo(int i) _diagnose_if(i, "bad i", "warning"); void bar(int i) _diagnose_if(i != T(), "bad i", "warning");
void fooOvl(int i) _diagnose_if(i, "int bad i", "warning"); void fooOvl(short i) _diagnose_if(i, "short bad i", "warning");
void barOvl(int i) _diagnose_if(i != T(), "int bad i", "warning"); void barOvl(short i) _diagnose_if(i != T(), "short bad i", "warning"); };
void runWarnings() {
Warnings<int>().foo(0);
Warnings<int>().foo(1);
Warnings<int>().bar(0);
Warnings<int>().bar(1);
Warnings<int>().fooOvl(0);
Warnings<int>().fooOvl(1); Warnings<int>().fooOvl(short(0));
Warnings<int>().fooOvl(short(1));
Warnings<int>().barOvl(0);
Warnings<int>().barOvl(1); Warnings<int>().barOvl(short(0));
Warnings<int>().barOvl(short(1)); }
}
namespace template_specialization {
template <typename T>
struct Foo {
void foo() _diagnose_if(1, "override me", "error"); void bar(int i) _diagnose_if(i, "bad i", "error"); void baz(int i);
};
template <>
struct Foo<int> {
void foo();
void bar(int i);
void baz(int i) _diagnose_if(i, "bad i", "error"); };
void runAll() {
Foo<double>().foo(); Foo<int>().foo();
Foo<double>().bar(1); Foo<int>().bar(1);
Foo<double>().baz(1);
Foo<int>().baz(1); }
}
namespace late_constexpr {
constexpr int foo();
constexpr int foo(int a);
void bar() _diagnose_if(foo(), "bad foo", "error"); void bar(int a) _diagnose_if(foo(a), "bad foo", "error");
void early() {
bar();
bar(0);
bar(1);
}
constexpr int foo() { return 1; }
constexpr int foo(int a) { return a; }
void late() {
bar(); bar(0);
bar(1); }
}
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") {} operator int() const _diagnose_if(isFooable(), "oh no", "error") { return 1; }
void go2() const _diagnose_if(isFooable(), "oh no", "error") __attribute__((enable_if(true, ""))) {}
void go2() const _diagnose_if(isFooable(), "oh no", "error") {}
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;
}
constexpr int runGo() const {
return go3() + go4();
}
};
void go(const Foo &f) _diagnose_if(f.isFooable(), "oh no", "error") {}
void run() {
Foo(0).go();
Foo(1).go();
(void)int(Foo(0));
(void)int(Foo(1));
Foo(0).go2();
Foo(1).go2();
go(Foo(0));
go(Foo(1)); }
}
namespace member_templates {
struct Foo {
int i;
constexpr Foo(int i): i(i) {}
constexpr bool bad() const { return i; }
template <typename T> T getVal() _diagnose_if(bad(), "oh no", "error") { return T();
}
template <typename T>
constexpr T getVal2() const _diagnose_if(bad(), "oh no", "error") { return T();
}
template <typename T>
constexpr operator T() const _diagnose_if(bad(), "oh no", "error") { return T();
}
int run() { return getVal<int>() + getVal2<int>() + int(*this); }
};
void run() {
Foo(0).getVal<int>();
Foo(1).getVal<int>();
Foo(0).getVal2<int>();
Foo(1).getVal2<int>();
(void)int(Foo(0));
(void)int(Foo(1)); }
}
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") { return nullptr;
}
void operator()() const _diagnose_if(bad(), "oh no", "error") {} };
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") {} void operator()(int) const _diagnose_if(bad(), "oh no", "error") {} };
struct ParenTemplate {
int i;
constexpr ParenTemplate(int i): i(i) {}
constexpr bool bad() const { return i; }
template <typename T>
void operator()(T) const _diagnose_if(bad(), "oh no", "error") {} };
void run() {
(void)Foo(0)->j;
(void)Foo(1)->j;
Foo(0)();
Foo(1)();
ParenOverload(0)(1);
ParenOverload(0)(1.);
ParenOverload(1)(1); ParenOverload(1)(1.);
ParenTemplate(0)(1);
ParenTemplate(0)(1.);
ParenTemplate(1)(1); ParenTemplate(1)(1.); }
void runLambda() {
auto L1 = [](int i) _diagnose_if(i, "oh no", "error") {}; L1(0);
L1(1); }
struct Brackets {
int i;
constexpr Brackets(int i): i(i) {}
void operator[](int) _diagnose_if(i == 1, "oh no", "warning") _diagnose_if(i == 2, "oh no", "error"); };
void runBrackets(int i) {
Brackets{0}[i];
Brackets{1}[i]; Brackets{2}[i]; }
struct Unary {
int i;
constexpr Unary(int i): i(i) {}
void operator+() _diagnose_if(i == 1, "oh no", "warning") _diagnose_if(i == 2, "oh no", "error"); };
void runUnary() {
+Unary{0};
+Unary{1}; +Unary{2}; }
struct PostInc {
void operator++(int i) _diagnose_if(i == 1, "oh no", "warning") _diagnose_if(i == 2, "oh no", "error"); };
void runPostInc() {
PostInc{}++;
PostInc{}.operator++(1); PostInc{}.operator++(2); }
}
namespace ctors {
struct Foo {
int I;
constexpr Foo(int I): I(I) {}
constexpr const Foo &operator=(const Foo &) const
_diagnose_if(I, "oh no", "error") { return *this;
}
constexpr const Foo &operator=(const Foo &&) const
_diagnose_if(I, "oh no", "error") { return *this;
}
};
struct Bar {
int I;
constexpr Bar(int I) _diagnose_if(I == 1, "oh no", "warning") _diagnose_if(I == 2, "oh no", "error"): I(I) {} };
void run() {
constexpr Foo F{0};
constexpr Foo F2{1};
F2 = F; F2 = Foo{2};
Bar{0};
Bar{1}; Bar{2}; }
}
namespace ref_init {
struct Bar {};
struct Baz {};
struct Foo {
int i;
constexpr Foo(int i): i(i) {}
operator const Bar &() const _diagnose_if(i, "oh no", "warning"); operator const Baz &() const _diagnose_if(i, "oh no", "error"); };
void fooBar(const Bar &b);
void fooBaz(const Baz &b);
void run() {
fooBar(Foo{0});
fooBar(Foo{1}); fooBaz(Foo{0});
fooBaz(Foo{1}); }
}
namespace udl {
void operator""_fn(char c)_diagnose_if(c == 1, "oh no", "warning") _diagnose_if(c == 2, "oh no", "error");
void run() {
'\0'_fn;
'\1'_fn; '\2'_fn; }
}
namespace PR31638 {
struct String {
String(char const* __s) _diagnose_if(__s == nullptr, "oh no ptr", "warning"); String(int __s) _diagnose_if(__s != 0, "oh no int", "warning"); };
void run() {
String s(nullptr); String ss(42); }
}
namespace PR31639 {
struct Foo {
Foo(int I) __attribute__((diagnose_if(I, "oh no", "error"))); };
void bar() { Foo f(1); } }
namespace user_defined_conversion {
struct Foo {
int i;
constexpr Foo(int i): i(i) {}
operator size_t() const _diagnose_if(i == 1, "oh no", "warning") _diagnose_if(i == 2, "oh no", "error"); };
void run() {
new int[Foo{0}];
new int[Foo{1}]; new int[Foo{2}]; }
}
namespace std {
template <typename T>
struct initializer_list {
const T *ptr;
size_t elems;
constexpr size_t size() const { return elems; }
};
}
namespace initializer_lists {
struct Foo {
Foo(std::initializer_list<int> l)
_diagnose_if(l.size() == 1, "oh no", "warning") _diagnose_if(l.size() == 2, "oh no", "error") {} };
void run() {
Foo{std::initializer_list<int>{}};
Foo{std::initializer_list<int>{1}}; Foo{std::initializer_list<int>{1, 2}}; Foo{std::initializer_list<int>{1, 2, 3}};
}
}
namespace range_for_loop {
namespace adl {
struct Foo {
int i;
constexpr Foo(int i): i(i) {}
};
void **begin(const Foo &f) _diagnose_if(f.i, "oh no", "warning");
void **end(const Foo &f) _diagnose_if(f.i, "oh no", "warning");
struct Bar {
int i;
constexpr Bar(int i): i(i) {}
};
void **begin(const Bar &b) _diagnose_if(b.i, "oh no", "error");
void **end(const Bar &b) _diagnose_if(b.i, "oh no", "error");
}
void run() {
for (void *p : adl::Foo(0)) {}
for (void *p : adl::Foo(1)) {}
for (void *p : adl::Bar(0)) {}
for (void *p : adl::Bar(1)) {}
}
}
namespace operator_new {
struct Foo {
int j;
static void *operator new(size_t i) _diagnose_if(i, "oh no", "warning"); };
struct Bar {
int j;
static void *operator new(size_t i) _diagnose_if(!i, "oh no", "warning");
};
void run() {
new Foo(); new Bar();
}
}
namespace contextual_implicit_conv {
struct Foo {
int i;
constexpr Foo(int i): i(i) {}
constexpr operator int() const _diagnose_if(i == 1, "oh no", "warning") _diagnose_if(i == 2, "oh no", "error") { return i;
}
};
void run() {
switch (constexpr Foo i = 0) { default: break; }
switch (constexpr Foo i = 1) { default: break; } switch (constexpr Foo i = 2) { default: break; } }
}