Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216833/?format=api
{ "id": 2216833, "url": "http://patchwork.ozlabs.org/api/patches/2216833/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/acZbKawUtKtxBfx0@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": "<acZbKawUtKtxBfx0@tucnak>", "list_archive_url": null, "date": "2026-03-27T10:25:45", "name": "[RFC] c++, libstdc++, v2: 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": "102d5c471d3d379557cf6377e1386e4f80426911", "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/acZbKawUtKtxBfx0@tucnak/mbox/", "series": [ { "id": 497741, "url": "http://patchwork.ozlabs.org/api/series/497741/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497741", "date": "2026-03-27T10:25:45", "name": "[RFC] c++, libstdc++, v2: Attempt to implement P3842R2 - A conservative fix for constexpr uncaught_exceptions() and current_exception()", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497741/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216833/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216833/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=E108B3/g;\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=E108B3/g", "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.129.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 4fhxdr1ccnz1y1j\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 21:26:55 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id C85EE4BAD155\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 10:26:52 +0000 (GMT)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id 6728C4BA2E0A\n for <gcc-patches@gcc.gnu.org>; Fri, 27 Mar 2026 10:26:04 +0000 (GMT)", "from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-209-WSJaVDQoMeOp0FlHtpWEKw-1; Fri,\n 27 Mar 2026 06:25:51 -0400", "from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 001461956055; Fri, 27 Mar 2026 10:25:50 +0000 (UTC)", "from tucnak.zalov.cz (unknown [10.45.225.193])\n by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id 0606B30001A1; Fri, 27 Mar 2026 10:25:48 +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 62RAPkqF2627013\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Fri, 27 Mar 2026 11:25:46 +0100", "(from jakub@localhost)\n by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 62RAPjb12627012;\n Fri, 27 Mar 2026 11:25:45 +0100" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org C85EE4BAD155", "OpenDKIM Filter v2.11.0 sourceware.org 6728C4BA2E0A" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 6728C4BA2E0A", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 6728C4BA2E0A", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774607164; cv=none;\n b=AhPE1t6WQFe7c1ey7apex5+mfYrhOMPvazL/ev9afr2i0GOf7U1xxNtnvPxLwk1jCuxZd3KNkHRS/hGdpO672YnOk0HlAzQfhlJ+jYZHyDbZxcq4mRZlrr39A6hq+ENCISmlhynoJv4RClmPr8KzfgdLvPXkfVVvMpBsX795CwA=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774607164; c=relaxed/simple;\n bh=SE3u5wuyjPfw9NOf8yRXNaemokaqD5iULnGtrvCdrs4=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=nejkBabQ6QEvJtUQVI608+uXjPvqEn2B92ngTZl+0mLiOyzinVLQhoH8q18J1cxiK+D+J0MXLzeI++8eBj16wFapKEwe69yzLTD7IzWUWMoEPbXwdhjabiPaJv50EPZ5eNNG9ZEp3jtDYqIMA9p2M6kGh0qu0JQ1x0TzG8J74t8=", "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=1774607164;\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:in-reply-to:in-reply-to: references:references;\n bh=J2BXOsTotquBJziGze9mXDw5ja3p5eXLPyhkPL/TlJc=;\n b=E108B3/g1YUxNI5bjymwjZr27cEU3kt9xHkIEUTRgIaSaXpHMWPOg6yI2z/c8ylY/5eULr\n eqYIXbmX4cyhTQjHRiHMVJ5siHcpD6DdharjIP18SFoTRAUnhIUEsl89qgTXpd2NG6hf05\n h7Ql6LWibjlFnIGdy+gxzPozAjcMpaE=", "X-MC-Unique": "WSJaVDQoMeOp0FlHtpWEKw-1", "X-Mimecast-MFC-AGG-ID": "WSJaVDQoMeOp0FlHtpWEKw_1774607150", "Date": "Fri, 27 Mar 2026 11:25:45 +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,\n Ville Voutilainen <ville.voutilainen@gmail.com>, Hana =?iso-8859-1?q?Dus=ED?=\n\t=?iso-8859-1?q?kov=E1?= <hanicka@hanicka.net>", "Subject": "[RFC PATCH] c++, libstdc++, v2: Attempt to implement P3842R2 - A\n conservative fix for constexpr uncaught_exceptions() and current_exception()", "Message-ID": "<acZbKawUtKtxBfx0@tucnak>", "References": "<acTi9ApfgNjpz8TG@tucnak>", "MIME-Version": "1.0", "In-Reply-To": "<acTi9ApfgNjpz8TG@tucnak>", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.4", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "5ikXweXC0PrTpQxhvgZFXSEgmOtPIP9BU6a3pNXvf8k_1774607150", "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 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\nHere is an updated version of the patch which implements P3842R2.\nIn particular, reverts all nested_exception.h changes over the last year\nand 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\n2026-03-27 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\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", "prefixes": [ "RFC" ] }