[RFC PATCH] c++, libstdc++, v2: Attempt to implement P3842R2 - A conservative fix for constexpr uncaught_exceptions() and current_exception()

Jakub Jelinek jakub@redhat.com
Fri Mar 27 10:25:45 GMT 2026


On Thu, Mar 26, 2026 at 08:40:36AM +0100, Jakub Jelinek wrote:
> The following patch attempts to implement the
> P3842R1 - A conservative fix for constexpr uncaught_exceptions()
> 	  and current_exception()
> paper.  std::current_exception() and std::uncaught_exceptions() aren't
> constexpr anymore (admittedly, they weren't declared that way in the
> headers before either, but the FE magically treated them as such),
> instead two new FE builtins are introduced so that one can get their
> behavior before this patch when needed.  So, at constant evaluation
> time they are constant evaluated and if they are not folded away,
> they are transformed into std::current_exception() or
> std::uncaught_exceptions() runtime calls during gimplification.
> 
> Compared to the paper, I had to also deal with nested_exception default
> ctor which also calls current_exception.
> 
> Lightly tested on x86_64-linux so far.

Here is an updated version of the patch which implements P3842R2.
In particular, reverts all nested_exception.h changes over the last year
and removes it from the constexpr-eh3.C test.  The proposed
__builtin_current_exception() is I believe exactly the
<it>current-exception</i>() in the paper.

2026-03-27  Jakub Jelinek  <jakub@redhat.com>

gcc/cp/
	* cp-tree.h (enum cp_built_in_function): Add
	CP_BUILT_IN_CURRENT_EXCEPTION and CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.
	* tree.cc (builtin_valid_in_constant_expr_p): Handle
	those.
	* decl.cc (cxx_init_decl_processing): Build
	decls for CP_BUILT_IN_CURRENT_EXCEPTION and
	CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.
	(require_deduced_type): Deduce CP_BUILT_IN_CURRENT_EXCEPTION
	return type.
	* cp-gimplify.cc (cp_gimplify_expr): Handle
	CP_BUILT_IN_CURRENT_EXCEPTION and CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.
	* constexpr.cc (enum cxa_builtin): Remove STD_UNCAUGHT_EXCEPTIONS
	and STD_CURRENT_EXCEPTION, add BUILTIN_UNCAUGHT_EXCEPTIONS and
	BUILTIN_CURRENT_EXCEPTION, renumber some enumerators.
	(cxx_cxa_builtin_fn_p): Don't check for std::uncaught_exceptions
	nor std::current_exception.
	(cxx_eval_cxa_builtin_fn): Handle BUILTIN_UNCAUGHT_EXCEPTIONS
	and BUILTIN_CURRENT_EXCEPTION instead of STD_UNCAUGHT_EXCEPTIONS
	and STD_CURRENT_EXCEPTION.
	(cxx_eval_builtin_function_call): Handle
	CP_BUILT_IN_CURRENT_EXCEPTION and CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.
	Do just one fndecl_builtin_p check for BUILT_IN_FRONTEND and
	switch on DECL_FE_FUNCTION_CODE.
gcc/testsuite/
	* g++.dg/cpp26/constexpr-eh3.C: Use __builtin_current_exception()
	instead of std::current_exception() and
	__builttin_uncaught_exceptions() instead of
	std::uncaught_exceptions().  Remove nested_exception related parts
	of the test.
	* g++.dg/cpp26/constexpr-eh8.C: Use __builtin_current_exception()
	instead of std::current_exception().
libstdc++-v3/
	* libsupc++/exception_ptr.h (std::make_exception_ptr): Use
	__builtin_current_exception() instead of current_exception() if
	the builtin exists.
	* libsupc++/nested_exception.h: Revert 2026-01-07 and 2025-07-10
	changes.

--- gcc/cp/cp-tree.h.jj	2026-03-27 10:17:14.017332648 +0100
+++ gcc/cp/cp-tree.h	2026-03-27 10:20:42.997381886 +0100
@@ -7135,6 +7135,8 @@ enum cp_built_in_function {
   CP_BUILT_IN_EH_PTR_ADJUST_REF,
   CP_BUILT_IN_IS_STRING_LITERAL,
   CP_BUILT_IN_CONSTEXPR_DIAG,
+  CP_BUILT_IN_CURRENT_EXCEPTION,
+  CP_BUILT_IN_UNCAUGHT_EXCEPTIONS,
   CP_BUILT_IN_LAST
 };
 
--- gcc/cp/tree.cc.jj	2026-03-27 10:17:14.036332338 +0100
+++ gcc/cp/tree.cc	2026-03-27 10:20:42.998245213 +0100
@@ -570,6 +570,8 @@ builtin_valid_in_constant_expr_p (const_
 	  case CP_BUILT_IN_EH_PTR_ADJUST_REF:
 	  case CP_BUILT_IN_IS_STRING_LITERAL:
 	  case CP_BUILT_IN_CONSTEXPR_DIAG:
+	  case CP_BUILT_IN_CURRENT_EXCEPTION:
+	  case CP_BUILT_IN_UNCAUGHT_EXCEPTIONS:
 	    return true;
 	  default:
 	    break;
--- gcc/cp/decl.cc.jj	2026-03-27 10:17:14.019332616 +0100
+++ gcc/cp/decl.cc	2026-03-27 10:20:42.999379349 +0100
@@ -5627,6 +5627,20 @@ cxx_init_decl_processing (void)
 				   CP_BUILT_IN_EH_PTR_ADJUST_REF,
 				   BUILT_IN_FRONTEND, NULL, NULL_TREE);
       set_call_expr_flags (decl, ECF_NOTHROW | ECF_LEAF);
+
+      /* Similar case to __builtin_source_locaiton above.  The concrete
+	 return type is std::exception_ptr, but we can't form the type
+	 at this point, so it is deduced later.  */
+      decl = add_builtin_function ("__builtin_current_exception",
+				   auto_ftype, CP_BUILT_IN_CURRENT_EXCEPTION,
+				   BUILT_IN_FRONTEND, NULL, NULL_TREE);
+      set_call_expr_flags (decl, ECF_NOTHROW | ECF_LEAF);
+
+      tree int_ftype = build_function_type_list (integer_type_node, NULL_TREE);
+      decl = add_builtin_function ("__builtin_uncaught_exceptions",
+				   int_ftype, CP_BUILT_IN_UNCAUGHT_EXCEPTIONS,
+				   BUILT_IN_FRONTEND, NULL, NULL_TREE);
+      set_call_expr_flags (decl, ECF_PURE | ECF_NOTHROW | ECF_LEAF);
     }
 
   decl
@@ -21226,8 +21240,8 @@ require_deduced_type (tree decl, tsubst_
   if (undeduced_auto_decl (decl))
     {
       if (TREE_CODE (decl) == FUNCTION_DECL
-	  && fndecl_built_in_p (decl, BUILT_IN_FRONTEND)
-	  && DECL_FE_FUNCTION_CODE (decl) == CP_BUILT_IN_SOURCE_LOCATION)
+	  && fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION,
+				BUILT_IN_FRONTEND))
 	{
 	  /* Set the return type of __builtin_source_location.  */
 	  tree type = get_source_location_impl_type ();
@@ -21242,6 +21256,33 @@ require_deduced_type (tree decl, tsubst_
 	  return true;
 	}
 
+      if (TREE_CODE (decl) == FUNCTION_DECL
+	  && fndecl_built_in_p (decl, CP_BUILT_IN_CURRENT_EXCEPTION,
+				BUILT_IN_FRONTEND))
+	{
+	  /* Set the return type of __builtin_current_exception.  */
+	  tree name = get_identifier ("exception_ptr");
+	  tree eptr = lookup_qualified_name (std_node, name);
+	  tree fld;
+	  if (TREE_CODE (eptr) != TYPE_DECL
+	      || !CLASS_TYPE_P (TREE_TYPE (eptr))
+	      || !COMPLETE_TYPE_P (TREE_TYPE (eptr))
+	      || !(fld = next_aggregate_field (TYPE_FIELDS (TREE_TYPE (eptr))))
+	      || DECL_ARTIFICIAL (fld)
+	      || TREE_CODE (TREE_TYPE (fld)) != POINTER_TYPE
+	      || next_aggregate_field (DECL_CHAIN (fld))
+	      || !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (eptr)),
+				      TYPE_SIZE (TREE_TYPE (fld))))
+	    {
+	      error ("%qs used without %qs declaration",
+		     "__builtin_current_exception", "std::exception_ptr");
+	      return false;
+	    }
+
+	  apply_deduced_return_type (decl, TREE_TYPE (eptr));
+	  return true;
+	}
+
       if (warning_suppressed_p (decl) && seen_error ())
 	/* We probably already complained about deduction failure.  */;
       else if (complain & tf_error)
--- gcc/cp/cp-gimplify.cc.jj	2026-03-27 10:17:14.016332665 +0100
+++ gcc/cp/cp-gimplify.cc	2026-03-27 10:20:43.000506227 +0100
@@ -979,6 +979,32 @@ cp_gimplify_expr (tree *expr_p, gimple_s
 			  "__builtin_eh_ptr_adjust_ref");
 		*expr_p = void_node;
 		break;
+	      case CP_BUILT_IN_CURRENT_EXCEPTION:
+	      case CP_BUILT_IN_UNCAUGHT_EXCEPTIONS:
+		{
+		  const char *name
+		    = (DECL_FE_FUNCTION_CODE (decl)
+		       == CP_BUILT_IN_CURRENT_EXCEPTION
+		       ? "current_exception" : "uncaught_exceptions");
+		  tree newdecl = lookup_qualified_name (std_node, name);
+		  if (error_operand_p (newdecl))
+		    *expr_p = build_zero_cst (TREE_TYPE (*expr_p));
+		  else if (TREE_CODE (newdecl) != FUNCTION_DECL
+			   || !same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+					    TREE_TYPE (TREE_TYPE (decl)))
+			   || (TYPE_ARG_TYPES (TREE_TYPE (newdecl))
+			       != void_list_node))
+		    {
+		      error_at (EXPR_LOCATION (*expr_p),
+				"unexpected %<std::%s%> declaration",
+				name);
+		      *expr_p = build_zero_cst (TREE_TYPE (*expr_p));
+		    }
+		  else
+		    *expr_p = build_call_expr_loc (EXPR_LOCATION (*expr_p),
+						   newdecl, 0);
+		  break;
+		}
 	      case CP_BUILT_IN_IS_STRING_LITERAL:
 		*expr_p
 		  = fold_builtin_is_string_literal (EXPR_LOCATION (*expr_p),
--- gcc/cp/constexpr.cc.jj	2026-03-27 10:17:14.014332697 +0100
+++ gcc/cp/constexpr.cc	2026-03-27 10:20:43.001205329 +0100
@@ -1804,10 +1804,10 @@ enum cxa_builtin {
   CXA_BAD_CAST = 8,
   CXA_BAD_TYPEID = 9,
   CXA_THROW_BAD_ARRAY_NEW_LENGTH = 10,
-  STD_UNCAUGHT_EXCEPTIONS = 11,
-  STD_CURRENT_EXCEPTION = 12,
-  STD_RETHROW_EXCEPTION = 13,
-  BUILTIN_EH_PTR_ADJUST_REF = 14
+  STD_RETHROW_EXCEPTION = 11,
+  BUILTIN_EH_PTR_ADJUST_REF = 12,
+  BUILTIN_UNCAUGHT_EXCEPTIONS = 13,
+  BUILTIN_CURRENT_EXCEPTION = 14
 };
 
 /* Return cxa_builtin if FNDECL is a __cxa_* function handled as
@@ -1822,10 +1822,6 @@ cxx_cxa_builtin_fn_p (tree fndecl)
     {
       if (!decl_in_std_namespace_p (fndecl))
 	return CXA_NONE;
-      if (id_equal (DECL_NAME (fndecl), "uncaught_exceptions"))
-	return STD_UNCAUGHT_EXCEPTIONS;
-      if (id_equal (DECL_NAME (fndecl), "current_exception"))
-	return STD_CURRENT_EXCEPTION;
       if (id_equal (DECL_NAME (fndecl), "rethrow_exception"))
 	return STD_RETHROW_EXCEPTION;
       return CXA_NONE;
@@ -2186,7 +2182,7 @@ cxx_eval_cxa_builtin_fn (const constexpr
 	  *jump_target = var;
 	}
       return void_node;
-    case STD_UNCAUGHT_EXCEPTIONS:
+    case BUILTIN_UNCAUGHT_EXCEPTIONS:
       if (nargs != 0)
 	goto invalid_nargs;
       /* Similarly to __builtin_is_constant_evaluated (), we don't
@@ -2202,7 +2198,7 @@ cxx_eval_cxa_builtin_fn (const constexpr
 	}
       return build_int_cst (integer_type_node,
 			    ctx->global->uncaught_exceptions);
-    case STD_CURRENT_EXCEPTION:
+    case BUILTIN_CURRENT_EXCEPTION:
       if (nargs != 0)
 	goto invalid_nargs;
       else
@@ -2489,40 +2485,53 @@ cxx_eval_builtin_function_call (const co
       return t;
     }
 
-  /* For __builtin_is_constant_evaluated, defer it if not
-     ctx->manifestly_const_eval (as sometimes we try to constant evaluate
-     without manifestly_const_eval even expressions or parts thereof which
-     will later be manifestly const_eval evaluated), otherwise fold it to
-     true.  */
-  if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
-			 BUILT_IN_FRONTEND))
-    {
-      if (ctx->manifestly_const_eval == mce_unknown)
-	{
-	  *non_constant_p = true;
-	  return t;
-	}
-      return constant_boolean_node (ctx->manifestly_const_eval == mce_true,
-				    boolean_type_node);
-    }
-
-  if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
-    {
-      temp_override<tree> ovr (current_function_decl);
-      if (ctx->call && ctx->call->fundef)
-	current_function_decl = ctx->call->fundef->decl;
-      return fold_builtin_source_location (t);
-    }
-
-  if (fndecl_built_in_p (fun, CP_BUILT_IN_EH_PTR_ADJUST_REF,
-			 BUILT_IN_FRONTEND))
-    return cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_EH_PTR_ADJUST_REF,
-				    fun, non_constant_p, overflow_p,
-				    jump_target);
+  if (fndecl_built_in_p (fun, BUILT_IN_FRONTEND))
+    switch (DECL_FE_FUNCTION_CODE (fun))
+      {
+      case CP_BUILT_IN_IS_CONSTANT_EVALUATED:
+	/* For __builtin_is_constant_evaluated, defer it if not
+	   ctx->manifestly_const_eval (as sometimes we try to constant evaluate
+	   without manifestly_const_eval even expressions or parts thereof
+	   which will later be manifestly const_eval evaluated), otherwise fold
+	   it to true.  */
+	if (ctx->manifestly_const_eval == mce_unknown)
+	  {
+	    *non_constant_p = true;
+	    return t;
+	  }
+	return constant_boolean_node (ctx->manifestly_const_eval == mce_true,
+				      boolean_type_node);
 
-  if (fndecl_built_in_p (fun, CP_BUILT_IN_CONSTEXPR_DIAG, BUILT_IN_FRONTEND))
-    return cxx_eval_constexpr_diag (ctx, t, non_constant_p, overflow_p,
-				    jump_target);
+      case CP_BUILT_IN_SOURCE_LOCATION:
+	{
+	  temp_override<tree> ovr (current_function_decl);
+	  if (ctx->call && ctx->call->fundef)
+	    current_function_decl = ctx->call->fundef->decl;
+	  return fold_builtin_source_location (t);
+	}
+
+      case CP_BUILT_IN_EH_PTR_ADJUST_REF:
+	return cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_EH_PTR_ADJUST_REF,
+					fun, non_constant_p, overflow_p,
+					jump_target);
+
+      case CP_BUILT_IN_CURRENT_EXCEPTION:
+	return cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_CURRENT_EXCEPTION,
+					fun, non_constant_p, overflow_p,
+					jump_target);
+
+      case CP_BUILT_IN_UNCAUGHT_EXCEPTIONS:
+	return cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_UNCAUGHT_EXCEPTIONS,
+					fun, non_constant_p, overflow_p,
+					jump_target);
+
+      case CP_BUILT_IN_CONSTEXPR_DIAG:
+	return cxx_eval_constexpr_diag (ctx, t, non_constant_p, overflow_p,
+					jump_target);
+
+      default:
+	break;
+      }
 
   int strops = 0;
   int strret = 0;
--- gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C.jj	2026-03-27 10:17:15.649306017 +0100
+++ gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C	2026-03-27 10:25:17.000451093 +0100
@@ -20,12 +20,10 @@ constexpr std::bad_typeid k;
 constexpr const char *l = k.what ();
 constexpr std::exception_ptr m = nullptr;
 static_assert (m == nullptr);
-constexpr std::exception_ptr n = std::current_exception ();
+constexpr std::exception_ptr n = __builtin_current_exception ();
 static_assert (n == nullptr);
 constexpr std::exception_ptr o;
 static_assert (o == nullptr);
-constexpr std::nested_exception p;
-static_assert (p.nested_ptr () == nullptr);
 
 struct A { virtual ~A () {} };
 struct B { virtual void b (); };
@@ -33,20 +31,13 @@ struct C { virtual void c (); };
 struct D : private B { virtual void d (); };
 struct E { virtual void e (); };
 struct F : D, E, private C { virtual void f (); };
-struct G { constexpr G () { if (std::uncaught_exceptions () != 0) asm (""); } };
-struct H { constexpr H () : h (0) {} constexpr ~H () { if (std::uncaught_exceptions () != h) asm (""); } int h; };
-struct I : std::nested_exception { };
-struct J { virtual ~J () noexcept = default; };
-struct K final { };
-struct L : J, std::nested_exception { };
-struct M { };
-struct N : I, L { };
-struct O : private std::nested_exception { };
+struct G { constexpr G () { if (__builtin_uncaught_exceptions () != 0) asm (""); } };
+struct H { constexpr H () : h (0) {} constexpr ~H () { if (__builtin_uncaught_exceptions () != h) asm (""); } int h; };
 
 constexpr int
 foo (int x)
 {
-  if (std::uncaught_exceptions () != 0)
+  if (__builtin_uncaught_exceptions () != 0)
     return -1;
   switch (x)
     {
@@ -58,7 +49,7 @@ foo (int x)
 	}
       catch (const std::bad_typeid &x)
 	{
-	  if (std::uncaught_exceptions () != 0)
+	  if (__builtin_uncaught_exceptions () != 0)
 	    return -1;
 	  const char *p = x.what ();
 	  return 1;
@@ -90,15 +81,15 @@ foo (int x)
 	{
 	  H h;
 	  h.h = 1;
-	  if (std::current_exception () != nullptr)
+	  if (__builtin_current_exception () != nullptr)
 	    return -1;
 	  throw G ();
 	}
       catch (const G &g)
 	{
-	  if (std::uncaught_exceptions () != 0)
+	  if (__builtin_uncaught_exceptions () != 0)
 	    return -1;
-	  if (std::current_exception () == nullptr)
+	  if (__builtin_current_exception () == nullptr)
 	    return -1;
 	  return 3;
 	}
@@ -156,7 +147,7 @@ foo (int x)
 	  {
 	    if (a != 1)
 	      return -1;
-	    b = std::current_exception ();
+	    b = __builtin_current_exception ();
 	    if (b == nullptr)
 	      return -1;
 	    try
@@ -167,14 +158,14 @@ foo (int x)
 	      {
 		if (c != 2L)
 		  return -1;
-		d = std::current_exception ();
+		d = __builtin_current_exception ();
 		if (d == nullptr || b == d)
 		  return -1;
 	      }
-	    if (std::current_exception () != b)
+	    if (__builtin_current_exception () != b)
 	      return -1;
 	  }
-	if (std::current_exception () != nullptr)
+	if (__builtin_current_exception () != nullptr)
 	  return -1;
 	try
 	  {
@@ -266,157 +257,6 @@ foo (int x)
 	  }
 	return 8;
       }
-    case 8:
-      {
-	std::nested_exception a;
-	if (a.nested_ptr () != nullptr)
-	  return -1;
-	try
-	  {
-	    std::nested_exception b;
-	    if (b.nested_ptr () != nullptr)
-	      return -1;
-	    throw 42;
-	  }
-	catch (...)
-	  {
-	    std::nested_exception c;
-	    if (c.nested_ptr () != std::current_exception ())
-	      return -1;
-	    std::nested_exception d = c;
-	    if (d.nested_ptr () != c.nested_ptr ())
-	      return -1;
-	    c = d;
-	    try
-	      {
-		c.rethrow_nested ();
-	      }
-	    catch (const int &e)
-	      {
-		if (e != 42)
-		  return -1;
-	      }
-	  }
-	return 9;
-      }
-    case 9:
-      try
-	{
-	  std::throw_with_nested (I ());
-	}
-      catch (const std::nested_exception &a)
-	{
-	  if (a.nested_ptr () != nullptr)
-	    return -1;
-	  try
-	    {
-	      throw;
-	    }
-	  catch (const I &)
-	    {
-	      return 10;
-	    }
-	}
-      return -1;
-    case 10:
-      try
-	{
-	  std::throw_with_nested (J ());
-	}
-      catch (const std::nested_exception &a)
-	{
-	  if (a.nested_ptr () != nullptr)
-	    return -1;
-	  try
-	    {
-	      throw;
-	    }
-	  catch (const J &)
-	    {
-	      return 11;
-	    }
-	}
-      return -1;
-    case 11:
-      try
-	{
-	  std::throw_with_nested (K ());
-	}
-      catch (const std::nested_exception &)
-	{
-	  return -1;
-	}
-      catch (const K &)
-	{
-	  return 12;
-	}
-      return -1;
-    case 12:
-      try
-	{
-	  throw 42;
-	}
-      catch (...)
-	{
-	  I a;
-	  try
-	    {
-	      std::rethrow_if_nested (a);
-	    }
-	  catch (const int &b)
-	    {
-	      if (b == 42)
-		return 13;
-	    }
-	}
-      return -1;
-    case 13:
-      try
-	{
-	  throw J ();
-	}
-      catch (const J &a)
-	{
-	  std::rethrow_if_nested (a);
-	  return 14;
-	}
-      return -1;
-    case 14:
-      try
-	{
-	  throw 42;
-	}
-      catch (...)
-	{
-	  try
-	    {
-	      throw L ();
-	    }
-	  catch (const J &a)
-	    {
-	      try
-		{
-		  std::rethrow_if_nested (a);
-		}
-	      catch (const int &b)
-		{
-		  if (b == 42)
-		    return 15;
-		}
-	    }
-	}
-      return -1;
-    case 15:
-      {
-	std::rethrow_if_nested (1);
-	M m;
-	std::rethrow_if_nested (m);
-	N n;
-	std::rethrow_if_nested (n);
-	O o;
-	std::rethrow_if_nested (o);
-	return 16;
-      }
     default:
       break;
     }
@@ -431,12 +271,4 @@ static_assert (foo (4) == 5);
 static_assert (foo (5) == 6);
 static_assert (foo (6) == 7);
 static_assert (foo (7) == 8);
-static_assert (foo (8) == 9);
-static_assert (foo (9) == 10);
-static_assert (foo (10) == 11);
-static_assert (foo (11) == 12);
-static_assert (foo (12) == 13);
-static_assert (foo (13) == 14);
-static_assert (foo (14) == 15);
-static_assert (foo (15) == 16);
-static_assert (std::uncaught_exceptions () == 0);
+static_assert (__builtin_uncaught_exceptions () == 0);
--- gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C.jj	2026-03-27 10:17:15.649306017 +0100
+++ gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C	2026-03-27 10:20:43.002066001 +0100
@@ -13,7 +13,7 @@ foo ()
     }
   catch (...)
     {
-      return std::current_exception ();
+      return __builtin_current_exception ();
     }
 }
 
--- libstdc++-v3/libsupc++/exception_ptr.h.jj	2026-03-27 10:17:22.954186813 +0100
+++ libstdc++-v3/libsupc++/exception_ptr.h	2026-03-27 10:20:43.002212856 +0100
@@ -342,7 +342,11 @@ namespace std _GLIBCXX_VISIBILITY(defaul
 	}
       catch(...)
 	{
+#if __has_builtin(__builtin_current_exception)
+	  return __builtin_current_exception();
+#else
 	  return current_exception();
+#endif
 	}
 #endif
       return exception_ptr();
--- libstdc++-v3/libsupc++/nested_exception.h.jj	2026-03-27 10:17:22.955186796 +0100
+++ libstdc++-v3/libsupc++/nested_exception.h	2026-03-27 10:22:08.043534576 +0100
@@ -62,25 +62,17 @@ namespace std _GLIBCXX_VISIBILITY(defaul
 
   public:
     /// The default constructor stores the current exception (if any).
-    _GLIBCXX26_CONSTEXPR
     nested_exception() noexcept : _M_ptr(current_exception()) { }
 
-    _GLIBCXX26_CONSTEXPR
     nested_exception(const nested_exception&) noexcept = default;
 
-    _GLIBCXX26_CONSTEXPR
     nested_exception& operator=(const nested_exception&) noexcept = default;
 
-#if __cplusplus >= 202400L
-    [[__gnu__::__gnu_inline__]]
-    constexpr inline virtual ~nested_exception() noexcept {}
-#else
     virtual ~nested_exception() noexcept;
-#endif
 
     /// Rethrow the stored exception, or terminate if none was stored.
     [[noreturn]]
-    _GLIBCXX26_CONSTEXPR void
+    void
     rethrow_nested() const
     {
       if (_M_ptr)
@@ -89,7 +81,7 @@ namespace std _GLIBCXX_VISIBILITY(defaul
     }
 
     /// Access the stored exception.
-    _GLIBCXX26_CONSTEXPR exception_ptr
+    exception_ptr
     nested_ptr() const noexcept
     { return _M_ptr; }
   };
@@ -99,11 +91,11 @@ namespace std _GLIBCXX_VISIBILITY(defaul
   template<typename _Except>
     struct _Nested_exception : public _Except, public nested_exception
     {
-      _GLIBCXX26_CONSTEXPR explicit _Nested_exception(const _Except& __ex)
+      explicit _Nested_exception(const _Except& __ex)
       : _Except(__ex)
       { }
 
-      _GLIBCXX26_CONSTEXPR explicit _Nested_exception(_Except&& __ex)
+      explicit _Nested_exception(_Except&& __ex)
       : _Except(static_cast<_Except&&>(__ex))
       { }
     };
@@ -152,7 +144,7 @@ namespace std _GLIBCXX_VISIBILITY(defaul
    */
   template<typename _Tp>
     [[noreturn]]
-    _GLIBCXX26_CONSTEXPR inline void
+    inline void
     throw_with_nested(_Tp&& __t)
     {
       using _Up = typename decay<_Tp>::type;
@@ -212,7 +204,7 @@ namespace std _GLIBCXX_VISIBILITY(defaul
 # if ! __cpp_rtti
     [[__gnu__::__always_inline__]]
 #endif
-    _GLIBCXX26_CONSTEXPR inline void
+    inline void
     rethrow_if_nested(const _Ex& __ex)
     {
       const _Ex* __ptr = __builtin_addressof(__ex);


	Jakub



More information about the Libstdc++ mailing list