blob: 287e066644027bfdac237de54c864622df754692 [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 A {
explicit constexpr A (int x) noexcept : a (x) {}
constexpr virtual int foo () const noexcept { return a; }
constexpr virtual ~A () {}
int a;
};
struct B : public A {
explicit constexpr B (int x) noexcept : A (x) {}
constexpr int foo () const noexcept override { return a | 0x10; }
};
struct C : public A {
explicit constexpr C (int x) noexcept : A (x) {}
};
struct D : public A {
explicit constexpr D (int x) noexcept : A (x) {}
};
struct E {
constexpr E () noexcept : e (0) {}
explicit constexpr E (int x) noexcept : e (x) {}
int e;
};
struct F : public E, public B {
explicit constexpr F (int x) noexcept : B (x) {}
};
struct G : public E, public C {
explicit constexpr G (int x) noexcept : C (x) {}
};
struct H : public E, public D {
explicit constexpr H (int x) noexcept : D (x) {}
};
consteval int
bar (void (*fn) ())
{
try
{
fn ();
}
catch (C &a)
{
return a.foo () | 0x20;
}
catch (const C &b) // { dg-warning "exception of type 'C' will be caught by earlier handler" }
{
return b.foo () | 0x60;
}
catch (A &c)
{
return c.foo ();
}
catch (const A &d) // { dg-warning "exception of type 'A' will be caught by earlier handler" }
{
return d.foo () | 0x40;
}
return -1;
}
static_assert (bar ([] { throw A { 1 }; }) == 1);
static_assert (bar ([] { throw B { 2 }; }) == 0x12);
static_assert (bar ([] { throw C { 3 }; }) == 0x23);
static_assert (bar ([] { throw D { 4 }; }) == 4);
constexpr int a = bar ([] { throw E { 5 }; }); // { dg-error "uncaught exception 'E\\\{5\\\}'" }
static_assert (bar ([] { throw F { 6 }; }) == 0x16);
static_assert (bar ([] { throw G { 7 }; }) == 0x27);
static_assert (bar ([] { throw H { 8 }; }) == 8);