blob: 9eed3aa2cf1c59f9bb63c3d22b2eb7d731bdacde [file] [log] [blame]
// C++26 P3068R5 - Allowing exception throwing in constant-evaluation
// { dg-do compile { target c++26 } }
// { dg-require-effective-target exceptions_enabled }
struct S {
constexpr S () : s (new int (0)) {}
constexpr S (int x) : s (new int (x)) {}
constexpr S (const S &x) : s (new int (*x.s)) {}
constexpr ~S () { delete s; }
int *s;
};
struct T : public S {
constexpr T () : S () {}
constexpr T (int x) : S (x) {}
constexpr T (const T &x) : S (*x.s) {}
constexpr ~T () {}
};
struct U : public T {
constexpr U () : T () {}
constexpr U (int x) : T (x) {}
constexpr U (const U &x) : T (*x.s) {}
constexpr ~U () {}
};
struct V : public T {
constexpr V () : T () {}
constexpr V (int x) : T (x) {}
constexpr V (const U &x) : T (*x.s) {}
constexpr ~V () {}
};
template <typename X>
constexpr int
foo (X x)
{
try { throw x; }
catch (int &a) { return 42 + a; }
catch (const unsigned b) { return 43 + b; }
catch (const long &c) { return 44 + c; }
catch (bool d) { return 45 + d; }
catch (const U &e) { return 46 + *e.s; }
catch (const T &f) { return 47 + *f.s; }
catch (S g) { return 48 + *g.s; }
catch (int *const &h) { return 49; }
catch (long long *) { return 50; }
catch (const S *const &) { return 51; }
catch (...) { return 52; }
}
template <typename X>
constexpr int
bar (const X &x)
{
throw x;
}
template <typename X>
constexpr int
baz (const X &x)
{
try
{
try { bar (x); }
catch (int &a) { a += 80; throw; }
catch (long b) { b += 80; throw; }
catch (U &c) { c.s[0] += 82; throw; }
catch (V d) { d.s[0] += 83; throw; }
}
catch (int a) { return 42 + a; }
catch (const long &b) { return 43 + b; }
catch (S &c) { return 44 + c.s[0]; }
catch (long long d) { return 45 + d; }
catch (...) { return -1; }
}
constexpr int
qux (int x, bool y = true)
{
try
{
switch (x)
{
case 0: throw 42; break;
case 1: x = y ? throw 43 : 5; break;
case 2: x = -(throw 44, 6); break;
case 3: x = x + (throw 45, 7); break;
case 4: x = (throw 46, 8) + x; break;
case 5: x = (throw 47, y) ? 4 : 5; break;
case 6: x += (throw 48, y); break;
case 7: x = (double) (throw 49, y); break;
case 8: x = foo ((throw 50, x)); break;
default: break;
}
}
catch (int a) { return a; }
return -1;
}
constexpr int
corge ()
{
try { throw 0; }
catch (int *const &h) { return 49; }
catch (long long *) { return 50; }
catch (const S *const &) { return 51; }
catch (...) { return 52; }
}
static_assert (foo (12) == 54);
static_assert (foo (12U) == 55);
static_assert (foo (12L) == 56);
static_assert (foo (false) == 45);
static_assert (foo (true) == 46);
static_assert (foo (U (12)) == 58);
static_assert (foo (T (20)) == 67);
static_assert (foo (S (30)) == 78);
static_assert (foo (nullptr) == 49);
static_assert (foo ((int *)nullptr) == 49);
static_assert (foo ((long long *)nullptr) == 50);
static_assert (foo ((const S *)nullptr) == 51);
static_assert (foo ((const T *)nullptr) == 51);
static_assert (foo ((const U *)nullptr) == 51);
static_assert (foo (12ULL) == 52);
static_assert (baz (5) == 127);
static_assert (baz (6L) == 49);
static_assert (baz (U (25)) == 151);
static_assert (baz (V (26)) == 70);
static_assert (baz (T (27)) == 71);
static_assert (baz (S (28)) == 72);
static_assert (baz (7LL) == 52);
static_assert (baz (8ULL) == -1);
static_assert (qux (0) == 42);
static_assert (qux (1) == 43);
static_assert (qux (2) == 44);
static_assert (qux (3) == 45);
static_assert (qux (4) == 46);
static_assert (qux (5) == 47);
static_assert (qux (6) == 48);
static_assert (qux (7) == 49);
static_assert (qux (8) == 50);
static_assert (corge () == 52);