On Fri, Mar 27, 2026 at 11:25:45AM +0100, Jakub Jelinek wrote:
> 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.

Here is a third version of the patch, no longer RFC PATCH as it has been
voted in.  Testing found a regression in
18_support/exception_ptr/exception_ptr_cast.cc
caused by the earlier version of the patch, so this patch adjusts it to
use __builtin_current_exception() if possible and fall back to not trying
to test test01 during constant evaluation otherwise.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2026-03-28  Jakub Jelinek  <[email protected]>

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.
        * testsuite/18_support/exception_ptr/exception_ptr_cast.cc (test01):
        Use __builtin_current_exception instead of std::current_exception
        if __has_builtin(__builtin_current_exception).  Otherwise don't
        try to constant evaluate test01.

--- 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);
--- libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc.jj    
2026-01-02 22:41:17.694546676 +0100
+++ libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc       
2026-03-28 17:37:27.595719313 +0100
@@ -58,7 +58,11 @@ constexpr bool test01(bool x)
     }
   catch (...)
     {
+#if __has_builtin(__builtin_current_exception)
+      auto h = __builtin_current_exception();
+#else
       auto h = std::current_exception();
+#endif
       auto i = std::exception_ptr_cast<G>(h);
       VERIFY( i != nullptr );
       VERIFY( i->a == 1 && i->e == 2 && i->f == 3 && i->g == 4 );
@@ -78,7 +82,7 @@ constexpr bool test01(bool x)
   return true;
 }
 
-#if _GLIBCXX_USE_CXX11_ABI
+#if _GLIBCXX_USE_CXX11_ABI && __has_builtin(__builtin_current_exception)
 static_assert(test01(false));
 #endif
 


        Jakub

Reply via email to