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.

Reply via email to