[Bug c++/126918] constexpr exceptions and nullptr vs. pointer-to-member
"jakub at gcc dot gnu.org via Gcc-bugs" <[email protected]>
| Newsgroups | gmane.comp.gcc.bugs |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126918
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Hopefully fixed up testcase, http://eel.is/c++draft/except.handle#3.4 says that
the nullptr -> T & case is supported just for const T & (but I don't see
libsupc++ implementing this (nor the current constexpr eh).
// { dg-do compile { target c++26 } }
struct S { int m, n; int foo (int x) { return x + 42; } };
constexpr int S::*
foo (bool x)
{
if (x)
return nullptr;
try
{
throw nullptr;
}
catch (int S::*p)
{
return p;
}
return &S::m;
}
constexpr int S::*const &
bar (bool x)
{
static constexpr int S::*sm = &S::m;
if (x)
return sm;
try
{
throw nullptr;
}
catch (int S::*const &p)
{
return p;
}
return sm;
}
constexpr const int S::*
baz (bool x)
{
if (x)
return nullptr;
try
{
throw &S::m;
}
catch (const int S::*p)
{
return p;
}
return nullptr;
}
constexpr const int S::*const &
qux (bool x)
{
static const int S::*np = nullptr;
if (x)
return np;
try
{
throw &S::m;
}
catch (const int S::*const &p)
{
return p;
}
return np;
}
using F = int (S::*) (int);
constexpr F
corge (bool x)
{
if (x)
return nullptr;
try
{
throw nullptr;
}
catch (F p)
{
return p;
}
return &S::foo;
}
constexpr F const &
garply (bool x)
{
static constexpr F f = &S::foo;
if (x)
return f;
try
{
throw nullptr;
}
catch (F const &p)
{
return p;
}
return f;
}
#if __cpp_constexpr_exceptions >= 202411L
static_assert (foo (false) == nullptr);
static_assert (bar (false) == nullptr);
static_assert (baz (false) == &S::m);
static_assert (qux (false) == &S::m);
static_assert (corge (false) == nullptr);
static_assert (garply (false) == nullptr);
#endif
int
main ()
{
if (foo (false) != nullptr
|| bar (false) != nullptr
|| baz (false) != &S::m
|| qux (false) != &S::m
|| corge (false) != nullptr
|| garply (false) != nullptr)
__builtin_abort ();
}
Anyway, e.g. in gimple dump, the foo case looks in the IL as
D.2698 = __cxa_begin_catch (_1);
p = *D.2698;
while the bar case looks like
D.2712 = __cxa_begin_catch (_1);
p = D.2712;
So, either __cxa_begin_catch in these cases creates a TARGET_EXPR and get it
destroyed when the catch parm goes out of scope, or it pretends to do a new and
associates it with the exception object somehow (e.g. put it somehow into
DECL_EXCEPTION_REFCOUNT)
and let it be deleted when the exception object is deleted.