Re: [PATCH] c++: Don't cache calls which rethrow etc. [PR126508]

Jason Merrill <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
On 7/30/26 8:49 AM, Jakub Jelinek wrote:
> Hi!
> 
> The first 3 testcase below are miscompiled, we happily cache
> calls during constant evaluation which don't depend just on their
> arguments, but also on the current exceptions (uncaught or caught).
> If we decide to cache such functions and then try to evaluate them
> with different uncaught/caught exceptions (or none), we can get wrong
> results.
> We already don't cache calls which allocate and don't free all heap
> allocations, or free some heap allocations they haven't allocated,
> or which call (right now any) metafunctions, or have exited through
> exception, or aren't constant.
> This patch just adds the rethrow/__builtin_uncaught_exceptions/
> __builtin_current_exception calls to the set of non-cacheable operations
> (to be precise, e.g. rethrow would be safe to cache if we can prove
> that the current exception was always thrown from within that function,
> ditto __builtin_current_exception, but it is hard to figure out).
> The last testcase attempts to check if we don't need something similar
> also for __builtin_eh_ptr_adjust_ref, but the call to foo for some reason
> isn't cached and so I don't have a proof we need to handle it too.
> 
> So far lightly tested, ok for trunk/16.2 if it passes full
> bootstrap/regtest?

OK, though we might rename metafns_called to something like 
state_dependent and mention EH in its comment.  That can be a trunk-only 
followup.
> 2026-07-30  Jakub Jelinek  <[email protected]>
> 
> 	PR c++/126508
> 	* constexpr.cc (cxx_eval_cxa_builtin_fn): Avoid caching
> 	calls which rethrow or call __builtin_uncaught_exceptions
> 	or __builtin_current_exception.
> 
> 	* g++.dg/cpp26/constexpr-eh20.C: New test.
> 	* g++.dg/cpp26/constexpr-eh21.C: New test.
> 	* g++.dg/cpp26/constexpr-eh22.C: New test.
> 	* g++.dg/cpp26/constexpr-eh23.C: New test.
> 
> --- gcc/cp/constexpr.cc.jj	2026-07-27 18:51:44.636642818 +0200
> +++ gcc/cp/constexpr.cc	2026-07-30 14:03:20.410583194 +0200
> @@ -2118,6 +2118,9 @@ cxx_eval_cxa_builtin_fn (const constexpr
>         DECL_EXCEPTION_REFCOUNT (arg)
>   	= size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), size_one_node);
>         ++ctx->global->uncaught_exceptions;
> +      /* Don't cache calls which rethrow, they depend on the current
> +	 exception which might be caught in the caller.  */
> +      ctx->global->metafns_called = true;
>         *jump_target = arg;
>         return void_node;
>       case CXA_BAD_CAST:
> @@ -2196,6 +2199,10 @@ cxx_eval_cxa_builtin_fn (const constexpr
>   	  *non_constant_p = true;
>   	  return call;
>   	}
> +      /* Don't cache calls which call __builtin_uncaught_exceptions (),
> +	 they depend on the current uncaught exceptions which might
> +	 be the state from their caller.  */
> +      ctx->global->metafns_called = true;
>         return build_int_cst (integer_type_node,
>   			    ctx->global->uncaught_exceptions);
>       case BUILTIN_CURRENT_EXCEPTION:
> @@ -2247,6 +2254,10 @@ cxx_eval_cxa_builtin_fn (const constexpr
>   			      size_one_node);
>   	      arg = fold_convert (ptr_type_node, build_address (arg));
>   	    }
> +	  /* Don't cache calls which call __builtin_current_exception (),
> +	     they depend on the current exception which might be caught
> +	     in the caller.  */
> +	  ctx->global->metafns_called = true;
>   	  return build_constructor_single (TREE_TYPE (decl), fld, arg);
>   	}
>       case STD_RETHROW_EXCEPTION:
> --- gcc/testsuite/g++.dg/cpp26/constexpr-eh20.C.jj	2026-07-30 13:04:03.278524380 +0200
> +++ gcc/testsuite/g++.dg/cpp26/constexpr-eh20.C	2026-07-30 13:03:39.287820983 +0200
> @@ -0,0 +1,31 @@
> +// PR c++/126508
> +// { dg-do compile { target c++26 } }
> +
> +constexpr int
> +foo ()
> +{
> +  try
> +    {
> +      throw;
> +    }
> +  catch (const int x)
> +    {
> +      return x;
> +    }
> +}
> +
> +constexpr int
> +bar (int x)
> +{
> +  try
> +    {
> +      throw x;
> +    }
> +  catch (...)
> +    {
> +      return foo ();
> +    }
> +}
> +
> +static_assert (bar (42) == 42);
> +static_assert (bar (43) == 43);
> --- gcc/testsuite/g++.dg/cpp26/constexpr-eh21.C.jj	2026-07-30 13:05:39.040340448 +0200
> +++ gcc/testsuite/g++.dg/cpp26/constexpr-eh21.C	2026-07-30 13:09:35.632415397 +0200
> @@ -0,0 +1,43 @@
> +// PR c++/126508
> +// { dg-do compile { target c++26 } }
> +
> +constexpr int
> +foo ()
> +{
> +  return __builtin_uncaught_exceptions ();
> +}
> +
> +constexpr int
> +bar ()
> +{
> +  return __builtin_uncaught_exceptions ();
> +}
> +
> +struct A { constexpr A () : a (0) {} constexpr ~A () { if (foo () != a) asm (""); } int a; };
> +struct B { constexpr B () : b (0) {} constexpr ~B () { if (bar () != b) asm (""); } int b; };
> +
> +constexpr bool
> +baz ()
> +{
> +  {
> +    A a;
> +  }
> +  try
> +    {
> +      A a;
> +      B b;
> +      a.a = 1;
> +      b.b = 1;
> +      throw 42;
> +    }
> +  catch (...)
> +    {
> +    }
> +  {
> +    A a;
> +    B b;
> +  }
> +  return true;
> +}
> +
> +static_assert (baz ());
> --- gcc/testsuite/g++.dg/cpp26/constexpr-eh22.C.jj	2026-07-30 13:15:19.463164518 +0200
> +++ gcc/testsuite/g++.dg/cpp26/constexpr-eh22.C	2026-07-30 13:17:06.057846657 +0200
> @@ -0,0 +1,41 @@
> +// PR c++/126508
> +// { dg-do compile { target c++26 } }
> +
> +#include <exception>
> +
> +constexpr bool
> +foo ()
> +{
> +  return __builtin_current_exception () != nullptr;
> +}
> +
> +constexpr int
> +bar ()
> +{
> +  return __builtin_current_exception () != nullptr;
> +}
> +
> +constexpr bool
> +baz ()
> +{
> +  if (foo ())
> +    return false;
> +  try
> +    {
> +      throw 42;
> +    }
> +  catch (...)
> +    {
> +      if (!foo ())
> +	return false;
> +      if (!bar ())
> +	return false;
> +    }
> +  if (foo ())
> +    return false;
> +  if (bar ())
> +    return false;
> +  return true;
> +}
> +
> +static_assert (baz ());
> --- gcc/testsuite/g++.dg/cpp26/constexpr-eh23.C.jj	2026-07-30 13:28:07.676488300 +0200
> +++ gcc/testsuite/g++.dg/cpp26/constexpr-eh23.C	2026-07-30 13:28:03.177545200 +0200
> @@ -0,0 +1,22 @@
> +// PR c++/126508
> +// { dg-do compile { target c++26 } }
> +
> +#include <exception>
> +
> +constexpr std::exception_ptr
> +foo (const std::exception_ptr &x)
> +{
> +  return x;
> +}
> +
> +constexpr bool
> +baz ()
> +{
> +  std::exception_ptr a = std::make_exception_ptr (42);
> +  auto b = foo (a);
> +  auto c = foo (a);
> +  auto d = foo (a);
> +  return true;
> +}
> +
> +static_assert (baz ());
> 
> 	Jakub
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.