https://gcc.gnu.org/g:2b6c8467feea5be6082b1f316fb312a9e8042e0e

commit r16-8447-g2b6c8467feea5be6082b1f316fb312a9e8042e0e
Author: Jakub Jelinek <[email protected]>
Date:   Fri Apr 3 20:46:42 2026 +0200

    c++, libstdc++: Attempt to implement P3842R2 - A conservative fix for 
constexpr uncaught_exceptions() and current_exception()
    
    The following patch attempts to implement the
    P3842R2 - 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.
    
    And nested_exception isn't constexpr anymore either.
    
    2026-04-03  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.
    
    Reviewed-by: Jason Merrill <[email protected]>
    Reviewed-by: Jonathan Wakely <[email protected]>

Diff:
---
 gcc/cp/constexpr.cc                                |  87 ++++-----
 gcc/cp/cp-gimplify.cc                              |  26 +++
 gcc/cp/cp-tree.h                                   |   2 +
 gcc/cp/decl.cc                                     |  45 ++++-
 gcc/cp/tree.cc                                     |   2 +
 gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C         | 194 ++-------------------
 gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C         |   2 +-
 libstdc++-v3/libsupc++/exception_ptr.h             |   4 +
 libstdc++-v3/libsupc++/nested_exception.h          |  20 +--
 .../18_support/exception_ptr/exception_ptr_cast.cc |   6 +-
 10 files changed, 150 insertions(+), 238 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 9c32c13ae649..b3d7616628a7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -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_ctx *ctx, tree 
call,
          *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_ctx *ctx, tree 
call,
        }
       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 constexpr_ctx 
*ctx, tree t, tree fun,
       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)
+  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);
+
+      case CP_BUILT_IN_SOURCE_LOCATION:
        {
-         *non_constant_p = true;
-         return t;
+         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);
        }
-      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);
-    }
+      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);
 
-  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);
+      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);
 
-  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_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;
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 0b096ccd7271..5bcf51689700 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -979,6 +979,32 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, 
gimple_seq *post_p)
                          "__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),
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ea3cb049785b..c0822da82835 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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
 };
 
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 8409752aa0c8..feaca1c3f52a 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -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_location 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
@@ -21247,8 +21261,8 @@ require_deduced_type (tree decl, tsubst_flags_t 
complain)
   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 ();
@@ -21263,6 +21277,33 @@ require_deduced_type (tree decl, tsubst_flags_t 
complain)
          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)
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 7296f2b5c0d4..ff2e78cd89cf 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -570,6 +570,8 @@ builtin_valid_in_constant_expr_p (const_tree decl)
          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;
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C 
b/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C
index f844d118ce8b..8dda92dcf90c 100644
--- a/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C
@@ -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);
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C 
b/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C
index 2560364fe55d..7401d137073f 100644
--- a/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C
@@ -13,7 +13,7 @@ foo ()
     }
   catch (...)
     {
-      return std::current_exception ();
+      return __builtin_current_exception ();
     }
 }
 
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h 
b/libstdc++-v3/libsupc++/exception_ptr.h
index b7a2304e121c..61ab0203fa0d 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -342,7 +342,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
        }
       catch(...)
        {
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_current_exception)
+         return __builtin_current_exception();
+#else
          return current_exception();
+#endif
        }
 #endif
       return exception_ptr();
diff --git a/libstdc++-v3/libsupc++/nested_exception.h 
b/libstdc++-v3/libsupc++/nested_exception.h
index 132f51dde60a..9093b4d6d524 100644
--- a/libstdc++-v3/libsupc++/nested_exception.h
+++ b/libstdc++-v3/libsupc++/nested_exception.h
@@ -62,25 +62,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
 
   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(default)
     }
 
     /// 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(default)
   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(default)
    */
   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(default)
 # 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);
diff --git 
a/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc 
b/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
index eebb5cb36e8e..3c40bef36a4a 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
@@ -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

Reply via email to