Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2217405/?format=api
{ "id": 2217405, "url": "http://patchwork.ozlabs.org/api/patches/2217405/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/acgGQLSkd4_mIOQj@tucnak/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<acgGQLSkd4_mIOQj@tucnak>", "list_archive_url": null, "date": "2026-03-28T16:48:01", "name": "c++, libstdc++, v3: Attempt to implement P3842R2 - A conservative fix for constexpr uncaught_exceptions() and current_exception()", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "daf74f8ef67496d44f33e550a7ba015da450b051", "submitter": { "id": 671, "url": "http://patchwork.ozlabs.org/api/people/671/?format=api", "name": "Jakub Jelinek", "email": "jakub@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/acgGQLSkd4_mIOQj@tucnak/mbox/", "series": [ { "id": 497880, "url": "http://patchwork.ozlabs.org/api/series/497880/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497880", "date": "2026-03-28T16:48:01", "name": "c++, libstdc++, v3: Attempt to implement P3842R2 - A conservative fix for constexpr uncaught_exceptions() and current_exception()", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497880/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2217405/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2217405/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=NxczF/5r;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=NxczF/5r", "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "sourceware.org; spf=pass smtp.mailfrom=redhat.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fjkM66q8gz1y1j\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 29 Mar 2026 04:01:54 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id CE0C44BA902C\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 28 Mar 2026 17:01:52 +0000 (GMT)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 11EC84BA9006\n for <gcc-patches@gcc.gnu.org>; Sat, 28 Mar 2026 16:57:47 +0000 (GMT)", "from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-606-MMzfLFWnMginqK1-ZPXOpg-1; Sat,\n 28 Mar 2026 12:57:34 -0400", "from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 7BE83180044D; Sat, 28 Mar 2026 16:57:33 +0000 (UTC)", "from tucnak.zalov.cz (unknown [10.44.32.9])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id CEF2C1800361; Sat, 28 Mar 2026 16:57:32 +0000 (UTC)", "from tucnak.zalov.cz (localhost [127.0.0.1])\n by tucnak.zalov.cz (8.18.1/8.18.1) with ESMTPS id 62SGvUic1667400\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Sat, 28 Mar 2026 17:57:30 +0100", "(from jakub@localhost)\n by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 62SGvUBf1667399;\n Sat, 28 Mar 2026 17:57:30 +0100" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org CE0C44BA902C", "OpenDKIM Filter v2.11.0 sourceware.org 11EC84BA9006" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 11EC84BA9006", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 11EC84BA9006", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774717067; cv=none;\n b=PkTQ8c382GqGo+M/QpR0+frUE38+XCAuk13+w2LiR6buerK8Z0URBJ5ZaFBdnaW38Q1GVbyTK7tX49c6YydpBdgJPUz1FjO/64Zn6xVbqlol9YYbIzf+dPdNU8rGJoKNAqb559HVo/or3Atv1TCjryJdaqN3Ym+v/HqC1oMS9s8=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774717067; c=relaxed/simple;\n bh=DGw0UfZJBxha0thithtG311zXeY20faYkBQ3Pe6yNlg=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=w8DjM07jKKMSOuoj9gcmivtEaX/v74UMYi46Rvdl6cQJURnJVfBRWuLYeqYBU7kmH6qEdPhKnwKFgaX2uRGrumfMUx2hoIrPGsQa1PHfwfiQRKez/vytl6j9PwJfHuulV8ICjwtCWZxNrjNnEWhE8RnunnHgtPdLYiXtM3VtFn0=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1774717066;\n h=from:from:reply-to:reply-to:subject:subject:date:date:\n message-id:message-id:to:to:cc:cc:mime-version:mime-version:\n content-type:content-type:resent-to:resent-from:resent-message-id:\n in-reply-to:in-reply-to:references:references;\n bh=wmxiucpVbheZl6Oacq3CVgYKujabgCWMcqlhPBVM+Eg=;\n b=NxczF/5r8QLqf2w4w1/OJa5hmDzUhTDf7xbpwgMJjzp/eF5sroj7cly+WGlGttY1WoqyEL\n NSXUt6qbKnmu3falqJwfAJvRrsLMx0W8o9U81+TNEJ8oUEf2sk/GEaR2HoqMMXTvzDVwOP\n ApwcYj62fKsnDz8IEzRyxgaaGeD7wSY=", "X-MC-Unique": "MMzfLFWnMginqK1-ZPXOpg-1", "X-Mimecast-MFC-AGG-ID": "MMzfLFWnMginqK1-ZPXOpg_1774717053", "Resent-From": "Jakub Jelinek <jakub@redhat.com>", "Resent-Date": "Sat, 28 Mar 2026 17:57:30 +0100", "Resent-Message-ID": "<acgIeist5z4Jefk_@tucnak>", "Resent-To": "Jason Merrill <jason@redhat.com>,\n Jonathan Wakely <jwakely@redhat.com>, gcc-patches@gcc.gnu.org,\n libstdc++@gcc.gnu.org", "Date": "Sat, 28 Mar 2026 17:48:01 +0100", "From": "Jakub Jelinek <jakub@redhat.com>", "To": "Jason Merrill <jason@redhat.com>, Jonathan Wakely <jwakely@redhat.com>", "Cc": "gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org", "Subject": "[PATCH] c++, libstdc++, v3: Attempt to implement P3842R2 - A\n conservative fix for constexpr uncaught_exceptions() and current_exception()", "Message-ID": "<acgGQLSkd4_mIOQj@tucnak>", "References": "<acTi9ApfgNjpz8TG@tucnak>\n <acZbKawUtKtxBfx0@tucnak>", "MIME-Version": "1.0", "In-Reply-To": "<acZbKawUtKtxBfx0@tucnak>", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.111", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "nwiQO9H4WUMVzK431c1CpEgiCmn0V1_R5HRk-uBOV3Q_1774717053", "X-Mimecast-Originator": "redhat.com", "Content-Type": "text/plain; charset=us-ascii", "Content-Disposition": "inline", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Reply-To": "Jakub Jelinek <jakub@redhat.com>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "On Fri, Mar 27, 2026 at 11:25:45AM +0100, Jakub Jelinek wrote:\n> On Thu, Mar 26, 2026 at 08:40:36AM +0100, Jakub Jelinek wrote:\n> > The following patch attempts to implement the\n> > P3842R1 - A conservative fix for constexpr uncaught_exceptions()\n> > \t and current_exception()\n> > paper. std::current_exception() and std::uncaught_exceptions() aren't\n> > constexpr anymore (admittedly, they weren't declared that way in the\n> > headers before either, but the FE magically treated them as such),\n> > instead two new FE builtins are introduced so that one can get their\n> > behavior before this patch when needed. So, at constant evaluation\n> > time they are constant evaluated and if they are not folded away,\n> > they are transformed into std::current_exception() or\n> > std::uncaught_exceptions() runtime calls during gimplification.\n> > \n> > Compared to the paper, I had to also deal with nested_exception default\n> > ctor which also calls current_exception.\n> > \n> > Lightly tested on x86_64-linux so far.\n> \n> Here is an updated version of the patch which implements P3842R2.\n> In particular, reverts all nested_exception.h changes over the last year\n> and removes it from the constexpr-eh3.C test. The proposed\n> __builtin_current_exception() is I believe exactly the\n> <it>current-exception</i>() in the paper.\n\nHere is a third version of the patch, no longer RFC PATCH as it has been\nvoted in. Testing found a regression in\n18_support/exception_ptr/exception_ptr_cast.cc\ncaused by the earlier version of the patch, so this patch adjusts it to\nuse __builtin_current_exception() if possible and fall back to not trying\nto test test01 during constant evaluation otherwise.\n\nBootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?\n\n2026-03-28 Jakub Jelinek <jakub@redhat.com>\n\ngcc/cp/\n\t* cp-tree.h (enum cp_built_in_function): Add\n\tCP_BUILT_IN_CURRENT_EXCEPTION and CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.\n\t* tree.cc (builtin_valid_in_constant_expr_p): Handle\n\tthose.\n\t* decl.cc (cxx_init_decl_processing): Build\n\tdecls for CP_BUILT_IN_CURRENT_EXCEPTION and\n\tCP_BUILT_IN_UNCAUGHT_EXCEPTIONS.\n\t(require_deduced_type): Deduce CP_BUILT_IN_CURRENT_EXCEPTION\n\treturn type.\n\t* cp-gimplify.cc (cp_gimplify_expr): Handle\n\tCP_BUILT_IN_CURRENT_EXCEPTION and CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.\n\t* constexpr.cc (enum cxa_builtin): Remove STD_UNCAUGHT_EXCEPTIONS\n\tand STD_CURRENT_EXCEPTION, add BUILTIN_UNCAUGHT_EXCEPTIONS and\n\tBUILTIN_CURRENT_EXCEPTION, renumber some enumerators.\n\t(cxx_cxa_builtin_fn_p): Don't check for std::uncaught_exceptions\n\tnor std::current_exception.\n\t(cxx_eval_cxa_builtin_fn): Handle BUILTIN_UNCAUGHT_EXCEPTIONS\n\tand BUILTIN_CURRENT_EXCEPTION instead of STD_UNCAUGHT_EXCEPTIONS\n\tand STD_CURRENT_EXCEPTION.\n\t(cxx_eval_builtin_function_call): Handle\n\tCP_BUILT_IN_CURRENT_EXCEPTION and CP_BUILT_IN_UNCAUGHT_EXCEPTIONS.\n\tDo just one fndecl_builtin_p check for BUILT_IN_FRONTEND and\n\tswitch on DECL_FE_FUNCTION_CODE.\ngcc/testsuite/\n\t* g++.dg/cpp26/constexpr-eh3.C: Use __builtin_current_exception()\n\tinstead of std::current_exception() and\n\t__builttin_uncaught_exceptions() instead of\n\tstd::uncaught_exceptions(). Remove nested_exception related parts\n\tof the test.\n\t* g++.dg/cpp26/constexpr-eh8.C: Use __builtin_current_exception()\n\tinstead of std::current_exception().\nlibstdc++-v3/\n\t* libsupc++/exception_ptr.h (std::make_exception_ptr): Use\n\t__builtin_current_exception() instead of current_exception() if\n\tthe builtin exists.\n\t* libsupc++/nested_exception.h: Revert 2026-01-07 and 2025-07-10\n\tchanges.\n\t* testsuite/18_support/exception_ptr/exception_ptr_cast.cc (test01):\n\tUse __builtin_current_exception instead of std::current_exception\n\tif __has_builtin(__builtin_current_exception). Otherwise don't\n\ttry to constant evaluate test01.\n\n\n\n\tJakub", "diff": "--- gcc/cp/cp-tree.h.jj\t2026-03-27 10:17:14.017332648 +0100\n+++ gcc/cp/cp-tree.h\t2026-03-27 10:20:42.997381886 +0100\n@@ -7135,6 +7135,8 @@ enum cp_built_in_function {\n CP_BUILT_IN_EH_PTR_ADJUST_REF,\n CP_BUILT_IN_IS_STRING_LITERAL,\n CP_BUILT_IN_CONSTEXPR_DIAG,\n+ CP_BUILT_IN_CURRENT_EXCEPTION,\n+ CP_BUILT_IN_UNCAUGHT_EXCEPTIONS,\n CP_BUILT_IN_LAST\n };\n \n--- gcc/cp/tree.cc.jj\t2026-03-27 10:17:14.036332338 +0100\n+++ gcc/cp/tree.cc\t2026-03-27 10:20:42.998245213 +0100\n@@ -570,6 +570,8 @@ builtin_valid_in_constant_expr_p (const_\n \t case CP_BUILT_IN_EH_PTR_ADJUST_REF:\n \t case CP_BUILT_IN_IS_STRING_LITERAL:\n \t case CP_BUILT_IN_CONSTEXPR_DIAG:\n+\t case CP_BUILT_IN_CURRENT_EXCEPTION:\n+\t case CP_BUILT_IN_UNCAUGHT_EXCEPTIONS:\n \t return true;\n \t default:\n \t break;\n--- gcc/cp/decl.cc.jj\t2026-03-27 10:17:14.019332616 +0100\n+++ gcc/cp/decl.cc\t2026-03-27 10:20:42.999379349 +0100\n@@ -5627,6 +5627,20 @@ cxx_init_decl_processing (void)\n \t\t\t\t CP_BUILT_IN_EH_PTR_ADJUST_REF,\n \t\t\t\t BUILT_IN_FRONTEND, NULL, NULL_TREE);\n set_call_expr_flags (decl, ECF_NOTHROW | ECF_LEAF);\n+\n+ /* Similar case to __builtin_source_locaiton above. The concrete\n+\t return type is std::exception_ptr, but we can't form the type\n+\t at this point, so it is deduced later. */\n+ decl = add_builtin_function (\"__builtin_current_exception\",\n+\t\t\t\t auto_ftype, CP_BUILT_IN_CURRENT_EXCEPTION,\n+\t\t\t\t BUILT_IN_FRONTEND, NULL, NULL_TREE);\n+ set_call_expr_flags (decl, ECF_NOTHROW | ECF_LEAF);\n+\n+ tree int_ftype = build_function_type_list (integer_type_node, NULL_TREE);\n+ decl = add_builtin_function (\"__builtin_uncaught_exceptions\",\n+\t\t\t\t int_ftype, CP_BUILT_IN_UNCAUGHT_EXCEPTIONS,\n+\t\t\t\t BUILT_IN_FRONTEND, NULL, NULL_TREE);\n+ set_call_expr_flags (decl, ECF_PURE | ECF_NOTHROW | ECF_LEAF);\n }\n \n decl\n@@ -21226,8 +21240,8 @@ require_deduced_type (tree decl, tsubst_\n if (undeduced_auto_decl (decl))\n {\n if (TREE_CODE (decl) == FUNCTION_DECL\n-\t && fndecl_built_in_p (decl, BUILT_IN_FRONTEND)\n-\t && DECL_FE_FUNCTION_CODE (decl) == CP_BUILT_IN_SOURCE_LOCATION)\n+\t && fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION,\n+\t\t\t\tBUILT_IN_FRONTEND))\n \t{\n \t /* Set the return type of __builtin_source_location. */\n \t tree type = get_source_location_impl_type ();\n@@ -21242,6 +21256,33 @@ require_deduced_type (tree decl, tsubst_\n \t return true;\n \t}\n \n+ if (TREE_CODE (decl) == FUNCTION_DECL\n+\t && fndecl_built_in_p (decl, CP_BUILT_IN_CURRENT_EXCEPTION,\n+\t\t\t\tBUILT_IN_FRONTEND))\n+\t{\n+\t /* Set the return type of __builtin_current_exception. */\n+\t tree name = get_identifier (\"exception_ptr\");\n+\t tree eptr = lookup_qualified_name (std_node, name);\n+\t tree fld;\n+\t if (TREE_CODE (eptr) != TYPE_DECL\n+\t || !CLASS_TYPE_P (TREE_TYPE (eptr))\n+\t || !COMPLETE_TYPE_P (TREE_TYPE (eptr))\n+\t || !(fld = next_aggregate_field (TYPE_FIELDS (TREE_TYPE (eptr))))\n+\t || DECL_ARTIFICIAL (fld)\n+\t || TREE_CODE (TREE_TYPE (fld)) != POINTER_TYPE\n+\t || next_aggregate_field (DECL_CHAIN (fld))\n+\t || !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (eptr)),\n+\t\t\t\t TYPE_SIZE (TREE_TYPE (fld))))\n+\t {\n+\t error (\"%qs used without %qs declaration\",\n+\t\t \"__builtin_current_exception\", \"std::exception_ptr\");\n+\t return false;\n+\t }\n+\n+\t apply_deduced_return_type (decl, TREE_TYPE (eptr));\n+\t return true;\n+\t}\n+\n if (warning_suppressed_p (decl) && seen_error ())\n \t/* We probably already complained about deduction failure. */;\n else if (complain & tf_error)\n--- gcc/cp/cp-gimplify.cc.jj\t2026-03-27 10:17:14.016332665 +0100\n+++ gcc/cp/cp-gimplify.cc\t2026-03-27 10:20:43.000506227 +0100\n@@ -979,6 +979,32 @@ cp_gimplify_expr (tree *expr_p, gimple_s\n \t\t\t \"__builtin_eh_ptr_adjust_ref\");\n \t\t*expr_p = void_node;\n \t\tbreak;\n+\t case CP_BUILT_IN_CURRENT_EXCEPTION:\n+\t case CP_BUILT_IN_UNCAUGHT_EXCEPTIONS:\n+\t\t{\n+\t\t const char *name\n+\t\t = (DECL_FE_FUNCTION_CODE (decl)\n+\t\t == CP_BUILT_IN_CURRENT_EXCEPTION\n+\t\t ? \"current_exception\" : \"uncaught_exceptions\");\n+\t\t tree newdecl = lookup_qualified_name (std_node, name);\n+\t\t if (error_operand_p (newdecl))\n+\t\t *expr_p = build_zero_cst (TREE_TYPE (*expr_p));\n+\t\t else if (TREE_CODE (newdecl) != FUNCTION_DECL\n+\t\t\t || !same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),\n+\t\t\t\t\t TREE_TYPE (TREE_TYPE (decl)))\n+\t\t\t || (TYPE_ARG_TYPES (TREE_TYPE (newdecl))\n+\t\t\t != void_list_node))\n+\t\t {\n+\t\t error_at (EXPR_LOCATION (*expr_p),\n+\t\t\t\t\"unexpected %<std::%s%> declaration\",\n+\t\t\t\tname);\n+\t\t *expr_p = build_zero_cst (TREE_TYPE (*expr_p));\n+\t\t }\n+\t\t else\n+\t\t *expr_p = build_call_expr_loc (EXPR_LOCATION (*expr_p),\n+\t\t\t\t\t\t newdecl, 0);\n+\t\t break;\n+\t\t}\n \t case CP_BUILT_IN_IS_STRING_LITERAL:\n \t\t*expr_p\n \t\t = fold_builtin_is_string_literal (EXPR_LOCATION (*expr_p),\n--- gcc/cp/constexpr.cc.jj\t2026-03-27 10:17:14.014332697 +0100\n+++ gcc/cp/constexpr.cc\t2026-03-27 10:20:43.001205329 +0100\n@@ -1804,10 +1804,10 @@ enum cxa_builtin {\n CXA_BAD_CAST = 8,\n CXA_BAD_TYPEID = 9,\n CXA_THROW_BAD_ARRAY_NEW_LENGTH = 10,\n- STD_UNCAUGHT_EXCEPTIONS = 11,\n- STD_CURRENT_EXCEPTION = 12,\n- STD_RETHROW_EXCEPTION = 13,\n- BUILTIN_EH_PTR_ADJUST_REF = 14\n+ STD_RETHROW_EXCEPTION = 11,\n+ BUILTIN_EH_PTR_ADJUST_REF = 12,\n+ BUILTIN_UNCAUGHT_EXCEPTIONS = 13,\n+ BUILTIN_CURRENT_EXCEPTION = 14\n };\n \n /* Return cxa_builtin if FNDECL is a __cxa_* function handled as\n@@ -1822,10 +1822,6 @@ cxx_cxa_builtin_fn_p (tree fndecl)\n {\n if (!decl_in_std_namespace_p (fndecl))\n \treturn CXA_NONE;\n- if (id_equal (DECL_NAME (fndecl), \"uncaught_exceptions\"))\n-\treturn STD_UNCAUGHT_EXCEPTIONS;\n- if (id_equal (DECL_NAME (fndecl), \"current_exception\"))\n-\treturn STD_CURRENT_EXCEPTION;\n if (id_equal (DECL_NAME (fndecl), \"rethrow_exception\"))\n \treturn STD_RETHROW_EXCEPTION;\n return CXA_NONE;\n@@ -2186,7 +2182,7 @@ cxx_eval_cxa_builtin_fn (const constexpr\n \t *jump_target = var;\n \t}\n return void_node;\n- case STD_UNCAUGHT_EXCEPTIONS:\n+ case BUILTIN_UNCAUGHT_EXCEPTIONS:\n if (nargs != 0)\n \tgoto invalid_nargs;\n /* Similarly to __builtin_is_constant_evaluated (), we don't\n@@ -2202,7 +2198,7 @@ cxx_eval_cxa_builtin_fn (const constexpr\n \t}\n return build_int_cst (integer_type_node,\n \t\t\t ctx->global->uncaught_exceptions);\n- case STD_CURRENT_EXCEPTION:\n+ case BUILTIN_CURRENT_EXCEPTION:\n if (nargs != 0)\n \tgoto invalid_nargs;\n else\n@@ -2489,40 +2485,53 @@ cxx_eval_builtin_function_call (const co\n return t;\n }\n \n- /* For __builtin_is_constant_evaluated, defer it if not\n- ctx->manifestly_const_eval (as sometimes we try to constant evaluate\n- without manifestly_const_eval even expressions or parts thereof which\n- will later be manifestly const_eval evaluated), otherwise fold it to\n- true. */\n- if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,\n-\t\t\t BUILT_IN_FRONTEND))\n- {\n- if (ctx->manifestly_const_eval == mce_unknown)\n-\t{\n-\t *non_constant_p = true;\n-\t return t;\n-\t}\n- return constant_boolean_node (ctx->manifestly_const_eval == mce_true,\n-\t\t\t\t boolean_type_node);\n- }\n-\n- if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))\n- {\n- temp_override<tree> ovr (current_function_decl);\n- if (ctx->call && ctx->call->fundef)\n-\tcurrent_function_decl = ctx->call->fundef->decl;\n- return fold_builtin_source_location (t);\n- }\n-\n- if (fndecl_built_in_p (fun, CP_BUILT_IN_EH_PTR_ADJUST_REF,\n-\t\t\t BUILT_IN_FRONTEND))\n- return cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_EH_PTR_ADJUST_REF,\n-\t\t\t\t fun, non_constant_p, overflow_p,\n-\t\t\t\t jump_target);\n+ if (fndecl_built_in_p (fun, BUILT_IN_FRONTEND))\n+ switch (DECL_FE_FUNCTION_CODE (fun))\n+ {\n+ case CP_BUILT_IN_IS_CONSTANT_EVALUATED:\n+\t/* For __builtin_is_constant_evaluated, defer it if not\n+\t ctx->manifestly_const_eval (as sometimes we try to constant evaluate\n+\t without manifestly_const_eval even expressions or parts thereof\n+\t which will later be manifestly const_eval evaluated), otherwise fold\n+\t it to true. */\n+\tif (ctx->manifestly_const_eval == mce_unknown)\n+\t {\n+\t *non_constant_p = true;\n+\t return t;\n+\t }\n+\treturn constant_boolean_node (ctx->manifestly_const_eval == mce_true,\n+\t\t\t\t boolean_type_node);\n \n- if (fndecl_built_in_p (fun, CP_BUILT_IN_CONSTEXPR_DIAG, BUILT_IN_FRONTEND))\n- return cxx_eval_constexpr_diag (ctx, t, non_constant_p, overflow_p,\n-\t\t\t\t jump_target);\n+ case CP_BUILT_IN_SOURCE_LOCATION:\n+\t{\n+\t temp_override<tree> ovr (current_function_decl);\n+\t if (ctx->call && ctx->call->fundef)\n+\t current_function_decl = ctx->call->fundef->decl;\n+\t return fold_builtin_source_location (t);\n+\t}\n+\n+ case CP_BUILT_IN_EH_PTR_ADJUST_REF:\n+\treturn cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_EH_PTR_ADJUST_REF,\n+\t\t\t\t\tfun, non_constant_p, overflow_p,\n+\t\t\t\t\tjump_target);\n+\n+ case CP_BUILT_IN_CURRENT_EXCEPTION:\n+\treturn cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_CURRENT_EXCEPTION,\n+\t\t\t\t\tfun, non_constant_p, overflow_p,\n+\t\t\t\t\tjump_target);\n+\n+ case CP_BUILT_IN_UNCAUGHT_EXCEPTIONS:\n+\treturn cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_UNCAUGHT_EXCEPTIONS,\n+\t\t\t\t\tfun, non_constant_p, overflow_p,\n+\t\t\t\t\tjump_target);\n+\n+ case CP_BUILT_IN_CONSTEXPR_DIAG:\n+\treturn cxx_eval_constexpr_diag (ctx, t, non_constant_p, overflow_p,\n+\t\t\t\t\tjump_target);\n+\n+ default:\n+\tbreak;\n+ }\n \n int strops = 0;\n int strret = 0;\n--- gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C.jj\t2026-03-27 10:17:15.649306017 +0100\n+++ gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C\t2026-03-27 10:25:17.000451093 +0100\n@@ -20,12 +20,10 @@ constexpr std::bad_typeid k;\n constexpr const char *l = k.what ();\n constexpr std::exception_ptr m = nullptr;\n static_assert (m == nullptr);\n-constexpr std::exception_ptr n = std::current_exception ();\n+constexpr std::exception_ptr n = __builtin_current_exception ();\n static_assert (n == nullptr);\n constexpr std::exception_ptr o;\n static_assert (o == nullptr);\n-constexpr std::nested_exception p;\n-static_assert (p.nested_ptr () == nullptr);\n \n struct A { virtual ~A () {} };\n struct B { virtual void b (); };\n@@ -33,20 +31,13 @@ struct C { virtual void c (); };\n struct D : private B { virtual void d (); };\n struct E { virtual void e (); };\n struct F : D, E, private C { virtual void f (); };\n-struct G { constexpr G () { if (std::uncaught_exceptions () != 0) asm (\"\"); } };\n-struct H { constexpr H () : h (0) {} constexpr ~H () { if (std::uncaught_exceptions () != h) asm (\"\"); } int h; };\n-struct I : std::nested_exception { };\n-struct J { virtual ~J () noexcept = default; };\n-struct K final { };\n-struct L : J, std::nested_exception { };\n-struct M { };\n-struct N : I, L { };\n-struct O : private std::nested_exception { };\n+struct G { constexpr G () { if (__builtin_uncaught_exceptions () != 0) asm (\"\"); } };\n+struct H { constexpr H () : h (0) {} constexpr ~H () { if (__builtin_uncaught_exceptions () != h) asm (\"\"); } int h; };\n \n constexpr int\n foo (int x)\n {\n- if (std::uncaught_exceptions () != 0)\n+ if (__builtin_uncaught_exceptions () != 0)\n return -1;\n switch (x)\n {\n@@ -58,7 +49,7 @@ foo (int x)\n \t}\n catch (const std::bad_typeid &x)\n \t{\n-\t if (std::uncaught_exceptions () != 0)\n+\t if (__builtin_uncaught_exceptions () != 0)\n \t return -1;\n \t const char *p = x.what ();\n \t return 1;\n@@ -90,15 +81,15 @@ foo (int x)\n \t{\n \t H h;\n \t h.h = 1;\n-\t if (std::current_exception () != nullptr)\n+\t if (__builtin_current_exception () != nullptr)\n \t return -1;\n \t throw G ();\n \t}\n catch (const G &g)\n \t{\n-\t if (std::uncaught_exceptions () != 0)\n+\t if (__builtin_uncaught_exceptions () != 0)\n \t return -1;\n-\t if (std::current_exception () == nullptr)\n+\t if (__builtin_current_exception () == nullptr)\n \t return -1;\n \t return 3;\n \t}\n@@ -156,7 +147,7 @@ foo (int x)\n \t {\n \t if (a != 1)\n \t return -1;\n-\t b = std::current_exception ();\n+\t b = __builtin_current_exception ();\n \t if (b == nullptr)\n \t return -1;\n \t try\n@@ -167,14 +158,14 @@ foo (int x)\n \t {\n \t\tif (c != 2L)\n \t\t return -1;\n-\t\td = std::current_exception ();\n+\t\td = __builtin_current_exception ();\n \t\tif (d == nullptr || b == d)\n \t\t return -1;\n \t }\n-\t if (std::current_exception () != b)\n+\t if (__builtin_current_exception () != b)\n \t return -1;\n \t }\n-\tif (std::current_exception () != nullptr)\n+\tif (__builtin_current_exception () != nullptr)\n \t return -1;\n \ttry\n \t {\n@@ -266,157 +257,6 @@ foo (int x)\n \t }\n \treturn 8;\n }\n- case 8:\n- {\n-\tstd::nested_exception a;\n-\tif (a.nested_ptr () != nullptr)\n-\t return -1;\n-\ttry\n-\t {\n-\t std::nested_exception b;\n-\t if (b.nested_ptr () != nullptr)\n-\t return -1;\n-\t throw 42;\n-\t }\n-\tcatch (...)\n-\t {\n-\t std::nested_exception c;\n-\t if (c.nested_ptr () != std::current_exception ())\n-\t return -1;\n-\t std::nested_exception d = c;\n-\t if (d.nested_ptr () != c.nested_ptr ())\n-\t return -1;\n-\t c = d;\n-\t try\n-\t {\n-\t\tc.rethrow_nested ();\n-\t }\n-\t catch (const int &e)\n-\t {\n-\t\tif (e != 42)\n-\t\t return -1;\n-\t }\n-\t }\n-\treturn 9;\n- }\n- case 9:\n- try\n-\t{\n-\t std::throw_with_nested (I ());\n-\t}\n- catch (const std::nested_exception &a)\n-\t{\n-\t if (a.nested_ptr () != nullptr)\n-\t return -1;\n-\t try\n-\t {\n-\t throw;\n-\t }\n-\t catch (const I &)\n-\t {\n-\t return 10;\n-\t }\n-\t}\n- return -1;\n- case 10:\n- try\n-\t{\n-\t std::throw_with_nested (J ());\n-\t}\n- catch (const std::nested_exception &a)\n-\t{\n-\t if (a.nested_ptr () != nullptr)\n-\t return -1;\n-\t try\n-\t {\n-\t throw;\n-\t }\n-\t catch (const J &)\n-\t {\n-\t return 11;\n-\t }\n-\t}\n- return -1;\n- case 11:\n- try\n-\t{\n-\t std::throw_with_nested (K ());\n-\t}\n- catch (const std::nested_exception &)\n-\t{\n-\t return -1;\n-\t}\n- catch (const K &)\n-\t{\n-\t return 12;\n-\t}\n- return -1;\n- case 12:\n- try\n-\t{\n-\t throw 42;\n-\t}\n- catch (...)\n-\t{\n-\t I a;\n-\t try\n-\t {\n-\t std::rethrow_if_nested (a);\n-\t }\n-\t catch (const int &b)\n-\t {\n-\t if (b == 42)\n-\t\treturn 13;\n-\t }\n-\t}\n- return -1;\n- case 13:\n- try\n-\t{\n-\t throw J ();\n-\t}\n- catch (const J &a)\n-\t{\n-\t std::rethrow_if_nested (a);\n-\t return 14;\n-\t}\n- return -1;\n- case 14:\n- try\n-\t{\n-\t throw 42;\n-\t}\n- catch (...)\n-\t{\n-\t try\n-\t {\n-\t throw L ();\n-\t }\n-\t catch (const J &a)\n-\t {\n-\t try\n-\t\t{\n-\t\t std::rethrow_if_nested (a);\n-\t\t}\n-\t catch (const int &b)\n-\t\t{\n-\t\t if (b == 42)\n-\t\t return 15;\n-\t\t}\n-\t }\n-\t}\n- return -1;\n- case 15:\n- {\n-\tstd::rethrow_if_nested (1);\n-\tM m;\n-\tstd::rethrow_if_nested (m);\n-\tN n;\n-\tstd::rethrow_if_nested (n);\n-\tO o;\n-\tstd::rethrow_if_nested (o);\n-\treturn 16;\n- }\n default:\n break;\n }\n@@ -431,12 +271,4 @@ static_assert (foo (4) == 5);\n static_assert (foo (5) == 6);\n static_assert (foo (6) == 7);\n static_assert (foo (7) == 8);\n-static_assert (foo (8) == 9);\n-static_assert (foo (9) == 10);\n-static_assert (foo (10) == 11);\n-static_assert (foo (11) == 12);\n-static_assert (foo (12) == 13);\n-static_assert (foo (13) == 14);\n-static_assert (foo (14) == 15);\n-static_assert (foo (15) == 16);\n-static_assert (std::uncaught_exceptions () == 0);\n+static_assert (__builtin_uncaught_exceptions () == 0);\n--- gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C.jj\t2026-03-27 10:17:15.649306017 +0100\n+++ gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C\t2026-03-27 10:20:43.002066001 +0100\n@@ -13,7 +13,7 @@ foo ()\n }\n catch (...)\n {\n- return std::current_exception ();\n+ return __builtin_current_exception ();\n }\n }\n \n--- libstdc++-v3/libsupc++/exception_ptr.h.jj\t2026-03-27 10:17:22.954186813 +0100\n+++ libstdc++-v3/libsupc++/exception_ptr.h\t2026-03-27 10:20:43.002212856 +0100\n@@ -342,7 +342,11 @@ namespace std _GLIBCXX_VISIBILITY(defaul\n \t}\n catch(...)\n \t{\n+#if __has_builtin(__builtin_current_exception)\n+\t return __builtin_current_exception();\n+#else\n \t return current_exception();\n+#endif\n \t}\n #endif\n return exception_ptr();\n--- libstdc++-v3/libsupc++/nested_exception.h.jj\t2026-03-27 10:17:22.955186796 +0100\n+++ libstdc++-v3/libsupc++/nested_exception.h\t2026-03-27 10:22:08.043534576 +0100\n@@ -62,25 +62,17 @@ namespace std _GLIBCXX_VISIBILITY(defaul\n \n public:\n /// The default constructor stores the current exception (if any).\n- _GLIBCXX26_CONSTEXPR\n nested_exception() noexcept : _M_ptr(current_exception()) { }\n \n- _GLIBCXX26_CONSTEXPR\n nested_exception(const nested_exception&) noexcept = default;\n \n- _GLIBCXX26_CONSTEXPR\n nested_exception& operator=(const nested_exception&) noexcept = default;\n \n-#if __cplusplus >= 202400L\n- [[__gnu__::__gnu_inline__]]\n- constexpr inline virtual ~nested_exception() noexcept {}\n-#else\n virtual ~nested_exception() noexcept;\n-#endif\n \n /// Rethrow the stored exception, or terminate if none was stored.\n [[noreturn]]\n- _GLIBCXX26_CONSTEXPR void\n+ void\n rethrow_nested() const\n {\n if (_M_ptr)\n@@ -89,7 +81,7 @@ namespace std _GLIBCXX_VISIBILITY(defaul\n }\n \n /// Access the stored exception.\n- _GLIBCXX26_CONSTEXPR exception_ptr\n+ exception_ptr\n nested_ptr() const noexcept\n { return _M_ptr; }\n };\n@@ -99,11 +91,11 @@ namespace std _GLIBCXX_VISIBILITY(defaul\n template<typename _Except>\n struct _Nested_exception : public _Except, public nested_exception\n {\n- _GLIBCXX26_CONSTEXPR explicit _Nested_exception(const _Except& __ex)\n+ explicit _Nested_exception(const _Except& __ex)\n : _Except(__ex)\n { }\n \n- _GLIBCXX26_CONSTEXPR explicit _Nested_exception(_Except&& __ex)\n+ explicit _Nested_exception(_Except&& __ex)\n : _Except(static_cast<_Except&&>(__ex))\n { }\n };\n@@ -152,7 +144,7 @@ namespace std _GLIBCXX_VISIBILITY(defaul\n */\n template<typename _Tp>\n [[noreturn]]\n- _GLIBCXX26_CONSTEXPR inline void\n+ inline void\n throw_with_nested(_Tp&& __t)\n {\n using _Up = typename decay<_Tp>::type;\n@@ -212,7 +204,7 @@ namespace std _GLIBCXX_VISIBILITY(defaul\n # if ! __cpp_rtti\n [[__gnu__::__always_inline__]]\n #endif\n- _GLIBCXX26_CONSTEXPR inline void\n+ inline void\n rethrow_if_nested(const _Ex& __ex)\n {\n const _Ex* __ptr = __builtin_addressof(__ex);\n--- libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc.jj\t2026-01-02 22:41:17.694546676 +0100\n+++ libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc\t2026-03-28 17:37:27.595719313 +0100\n@@ -58,7 +58,11 @@ constexpr bool test01(bool x)\n }\n catch (...)\n {\n+#if __has_builtin(__builtin_current_exception)\n+ auto h = __builtin_current_exception();\n+#else\n auto h = std::current_exception();\n+#endif\n auto i = std::exception_ptr_cast<G>(h);\n VERIFY( i != nullptr );\n VERIFY( i->a == 1 && i->e == 2 && i->f == 3 && i->g == 4 );\n@@ -78,7 +82,7 @@ constexpr bool test01(bool x)\n return true;\n }\n \n-#if _GLIBCXX_USE_CXX11_ABI\n+#if _GLIBCXX_USE_CXX11_ABI && __has_builtin(__builtin_current_exception)\n static_assert(test01(false));\n #endif\n \n", "prefixes": [] }