https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126918

            Bug ID: 126918
           Summary: constexpr exceptions and nullptr vs. pointer-to-member
           Product: gcc
           Version: 16.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

// { 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::*&
bar (bool x)
{
  static int S::*sm = &S::m;
  if (x)
    return sm;
  try
    {
      throw nullptr;
    }
  catch (int S::*&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::*&
qux (bool x)
{
  static const int S::*np = nullptr;
  if (x)
    return np;
  try
    {
      throw &S::m;
    }
  catch (const int S::*&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 &
garply (bool x)
{
  static F f = &S::foo;
  if (x)
    return f;
  try
    {
      throw nullptr;
    }
  catch (F &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 ();
}

should succeed but fails (if the baz/qux uses in static_assert/main are
commented out) or ICEs.

Reply via email to