Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216426/?format=api
{ "id": 2216426, "url": "http://patchwork.ozlabs.org/api/patches/2216426/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/acUfPDbhcQHP9ywS@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": "<acUfPDbhcQHP9ywS@tucnak>", "list_archive_url": null, "date": "2026-03-26T11:57:48", "name": "[RFC] c++: Implement the annotations_of on parms part of P3795R1", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "87474088c84787c3f778b47a644bbcd7bfedd2af", "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/acUfPDbhcQHP9ywS@tucnak/mbox/", "series": [ { "id": 497580, "url": "http://patchwork.ozlabs.org/api/series/497580/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497580", "date": "2026-03-26T11:57:48", "name": "[RFC] c++: Implement the annotations_of on parms part of P3795R1", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497580/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216426/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216426/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=IACTtmxV;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.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=IACTtmxV", "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 [38.145.34.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 4fhMjy6bglz1y1G\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 22:58:29 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 6DE5D4B9DB70\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 11:58:27 +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 E4F144B9DB54\n for <gcc-patches@gcc.gnu.org>; Thu, 26 Mar 2026 11:57:57 +0000 (GMT)", "from mx-prod-mc-05.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-286-h34pCBziPKudRn1VpbmlRQ-1; Thu,\n 26 Mar 2026 07:57:55 -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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 071AD195E937\n for <gcc-patches@gcc.gnu.org>; Thu, 26 Mar 2026 11:57:53 +0000 (UTC)", "from tucnak.zalov.cz (unknown [10.45.225.193])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id F33DB1800576; Thu, 26 Mar 2026 11:57:51 +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 62QBvnQH3910192\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Thu, 26 Mar 2026 12:57:49 +0100", "(from jakub@localhost)\n by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 62QBvm2V3910191;\n Thu, 26 Mar 2026 12:57:48 +0100" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 6DE5D4B9DB70", "OpenDKIM Filter v2.11.0 sourceware.org E4F144B9DB54" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org E4F144B9DB54", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org E4F144B9DB54", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774526278; cv=none;\n b=ZV9S7L5REkpeDyFGRk6fmmOk8pFP7EypRpxM94whtX+gdHhYBoI8lr5rRZaBo8gw18I+37FrTi/MM1j8Xx/1W3Q8nprC02flimBL+uZrrwd6hCRVh3hvgDy9oG19D+etMfrDdAAHW7RglReKTtZjkLHeZ2p7iuF9PrXF3FjycoI=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774526278; c=relaxed/simple;\n bh=zzautQ5I2xr7ngodEbvX94o6HO+2bk5Rer/+zSap0/U=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=L+RQBId08q4cOs8vRO+dvkn34WcUI+tI+QrMl4aFkEhQqoCcX0PzEIMNhXdEhr7EW2xjA4SO+YaXWh+qbq6T2yP/yg/xl6Tr9xFxdyql8kxwcu4VmDtrl4MYXhN80RVCG0DPPjTn34FpZjp2ej5O9E+5i72A0fxB5TGrAka+TKU=", "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=1774526277;\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; bh=ie+8syOIDV3luutduYiIJmggb30WyGLtQKDawzNhvBI=;\n b=IACTtmxVogoUDu9PLqgIYpf00ESPhmNbgICd7O71rv8+on6xEtQDDxjHXw0ziHvh/tUmL0\n +HBWCXwFKxLxAw9AwiZchHRxlRk4rfzXF7A9an5HSgfpWy34Y/BNaxor/mfAOxMtF/+n8F\n a2YXHSND4LNlVU7mdlvWA9dVW5E5JRs=", "X-MC-Unique": "h34pCBziPKudRn1VpbmlRQ-1", "X-Mimecast-MFC-AGG-ID": "h34pCBziPKudRn1VpbmlRQ_1774526275", "Date": "Thu, 26 Mar 2026 12:57:48 +0100", "From": "Jakub Jelinek <jakub@redhat.com>", "To": "Jason Merrill <jason@redhat.com>, Marek Polacek <polacek@redhat.com>", "Cc": "gcc-patches@gcc.gnu.org", "Subject": "[RFC PATCH] c++: Implement the annotations_of on parms part of\n P3795R1", "Message-ID": "<acUfPDbhcQHP9ywS@tucnak>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.111", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "E8ehM137vswaDdPipR5_IZRXx_sqfUNfTbVS3hKcW2M_1774526275", "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": "Hi!\n\nThe current behavior of GCC is that we list all annotations gathered from\nall the PARM_DECLs merged together on ^^fnparm or\nvariable_of (parameters_of (^^fn)[0]) and throw on annotations_of\non parameters_of (^^fn)[0]. The paper requires that the last one works\nlike we currently handle the former two, and for the former two we\nfilter out annotations that have not appeared on the function definition.\n\nThe following patch marks the annotations in grokfndecl before pushdecl\netc. merges it with other decls.\n\nTested on x86_64-linux.\n\n2026-03-26 Jakub Jelinek <jakub@redhat.com>\n\n\t* decl.cc (grokfndecl): For -freflection mark annotations of\n\tPARM_DECLs in a function definition.\n\t* reflect.cc (eval_annotations_of): Allow annotations_of on\n\tfunction parameters. For r which is a PARM_DECL without REFLECT_PARM,\n\tfilter out annotations not marked by grokfndecl.\n\t(reflection_mangle_prefix): Preserve the grokfndecl marking of\n\tannotations during mangling.\n\n\t* g++.dg/reflect/annotations15.C: New test.\n\n\n\tJakub", "diff": "--- gcc/cp/decl.cc.jj\t2026-03-26 07:59:59.527656320 +0100\n+++ gcc/cp/decl.cc\t2026-03-26 12:31:36.887319793 +0100\n@@ -12218,7 +12218,31 @@ grokfndecl (tree ctype,\n \n DECL_ARGUMENTS (decl) = parms;\n for (t = parms; t; t = DECL_CHAIN (t))\n- DECL_CONTEXT (t) = decl;\n+ {\n+ DECL_CONTEXT (t) = decl;\n+ if (flag_reflection\n+\t && initialized == SD_INITIALIZED\n+\t && DECL_ATTRIBUTES (t))\n+\tfor (tree a = DECL_ATTRIBUTES (t);\n+\t (a = lookup_attribute (\"internal \", \"annotation \", a));\n+\t a = TREE_CHAIN (a))\n+\t {\n+\t gcc_checking_assert (TREE_CODE (TREE_VALUE (a)) == TREE_LIST);\n+\t /* Mark TREE_PURPOSE of the value that it is an annotation\n+\t on an argument of a function definition (rather than\n+\t annotation from function declaration). For function parameter\n+\t reflection all annotations are listed, while for variable_of\n+\t only those marked here. Annotation is marked as coming from\n+\t function definition's argument if it has TREE_PURPOSE\n+\t void_cst or INTEGER_CST with signed type. */\n+\t tree val = TREE_VALUE (a);\n+\t if (TREE_PURPOSE (val) == NULL_TREE)\n+\t TREE_PURPOSE (val) = void_node;\n+\t else if (TREE_CODE (TREE_PURPOSE (val)) == INTEGER_CST)\n+\t TREE_PURPOSE (val)\n+\t\t= fold_convert (sbitsizetype, TREE_PURPOSE (val));\n+\t }\n+ }\n \n /* Propagate volatile out from type to decl. */\n if (TYPE_VOLATILE (type))\n--- gcc/cp/reflect.cc.jj\t2026-03-25 20:32:38.262640083 +0100\n+++ gcc/cp/reflect.cc\t2026-03-26 12:30:48.440143055 +0100\n@@ -3812,14 +3812,16 @@ eval_annotations_of (location_t loc, con\n \t|| eval_is_type_alias (r) == boolean_true_node\n \t|| eval_is_variable (r, kind) == boolean_true_node\n \t|| eval_is_function (r) == boolean_true_node\n+\t|| eval_is_function_parameter (r, kind) == boolean_true_node\n \t|| eval_is_namespace (r) == boolean_true_node\n \t|| eval_is_enumerator (r) == boolean_true_node\n \t|| eval_is_base (r, kind) == boolean_true_node\n \t|| eval_is_nonstatic_data_member (r) == boolean_true_node))\n return throw_exception (loc, ctx,\n \t\t\t \"reflection does not represent a type,\"\n-\t\t\t \" type alias, variable, function, namespace,\"\n-\t\t\t \" enumerator, direct base class relationship,\"\n+\t\t\t \" type alias, variable, function, function\"\n+\t\t\t \" parameter, namespace, enumerator,\"\n+\t\t\t \" direct base class relationship,\"\n \t\t\t \" or non-static data member\",\n \t\t\t fun, non_constant_p, jump_target);\n \n@@ -3836,6 +3838,7 @@ eval_annotations_of (location_t loc, con\n }\n \n r = maybe_get_first_fn (r);\n+ bool var_of = false;\n if (kind == REFLECT_BASE)\n {\n gcc_assert (TREE_CODE (r) == TREE_BINFO);\n@@ -3860,7 +3863,11 @@ eval_annotations_of (location_t loc, con\n \tr = TYPE_ATTRIBUTES (r);\n }\n else if (DECL_P (r))\n- r = DECL_ATTRIBUTES (r);\n+ {\n+ if (TREE_CODE (r) == PARM_DECL && kind != REFLECT_PARM)\n+\tvar_of = true;\n+ r = DECL_ATTRIBUTES (r);\n+ }\n else\n gcc_unreachable ();\n vec<constructor_elt, va_gc> *elts = nullptr;\n@@ -3869,6 +3876,15 @@ eval_annotations_of (location_t loc, con\n {\n gcc_checking_assert (TREE_CODE (TREE_VALUE (a)) == TREE_LIST);\n tree val = TREE_VALUE (TREE_VALUE (a));\n+ tree purpose = TREE_PURPOSE (TREE_VALUE (a));\n+ if (var_of\n+\t && (purpose == NULL_TREE\n+\t || (TREE_CODE (purpose) == INTEGER_CST\n+\t\t && !TYPE_UNSIGNED (TREE_TYPE (purpose)))))\n+\t/* For ^^fnparm or variable_of (parameters_of (^^fn)[N])\n+\t filter out annotations not specified on the function\n+\t definition. */\n+\tcontinue;\n if (type)\n \t{\n \t tree at = TREE_TYPE (val);\n@@ -8749,7 +8765,13 @@ reflection_mangle_prefix (tree refl, cha\n strcpy (prefix, \"an\");\n if (TREE_PURPOSE (TREE_VALUE (h)) == NULL_TREE)\n \tTREE_PURPOSE (TREE_VALUE (h))\n-\t = build_int_cst (integer_type_node, annotation_idx++);\n+\t = bitsize_int (annotation_idx++);\n+ /* TREE_PURPOSE void_cst or INTEGER_CST with signed type\n+\t means it is annotation which should appear in\n+\t variable_of list. */\n+ else if (TREE_PURPOSE (TREE_VALUE (h)) == void_node)\n+\tTREE_PURPOSE (TREE_VALUE (h))\n+\t = sbitsize_int (annotation_idx++);\n return TREE_PURPOSE (TREE_VALUE (h));\n }\n if (eval_is_type_alias (h) == boolean_true_node)\n--- gcc/testsuite/g++.dg/reflect/annotations15.C.jj\t2026-03-26 12:40:48.910963751 +0100\n+++ gcc/testsuite/g++.dg/reflect/annotations15.C\t2026-03-26 12:40:37.661154305 +0100\n@@ -0,0 +1,44 @@\n+// P3795R2 - Miscellaneous Reflection Cleanup\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection\" }\n+\n+#include <meta>\n+\n+void foo ([[=1]] int x);\n+constexpr auto rf = parameters_of (^^foo)[0];\n+void foo ([[=2, =3]] int x);\n+\n+void\n+foo ([[=4, =5]] int x)\n+{\n+ static_assert (annotations_of (^^x).size () == 2);\n+ static_assert ([: constant_of (annotations_of (^^x)[0]) :] == 4);\n+ static_assert ([: constant_of (annotations_of (^^x)[1]) :] == 5);\n+ static_assert (annotations_of (rf).size () == 5);\n+ static_assert ([: constant_of (annotations_of (rf)[0]) :] == 1);\n+ static_assert ([: constant_of (annotations_of (rf)[1]) :] == 2);\n+ static_assert ([: constant_of (annotations_of (rf)[2]) :] == 3);\n+ static_assert ([: constant_of (annotations_of (rf)[3]) :] == 4);\n+ static_assert ([: constant_of (annotations_of (rf)[4]) :] == 5);\n+ static_assert (annotations_of (variable_of (rf)).size () == 2);\n+ static_assert ([: constant_of (annotations_of (variable_of (rf))[0]) :] == 4);\n+ static_assert ([: constant_of (annotations_of (variable_of (rf))[1]) :] == 5);\n+ static_assert (annotations_of (parameters_of (^^foo)[0]).size () == 5);\n+ static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[0]) :] == 1);\n+ static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[1]) :] == 2);\n+ static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[2]) :] == 3);\n+ static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[3]) :] == 4);\n+ static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[4]) :] == 5);\n+ static_assert (annotations_of (^^x)[0] == annotations_of (rf)[3]);\n+ static_assert (annotations_of (^^x)[0] == annotations_of (variable_of (rf))[0]);\n+ static_assert (annotations_of (^^x)[0] == annotations_of (parameters_of (^^foo)[0])[3]);\n+}\n+\n+void foo ([[=6]] int x);\n+static_assert (annotations_of (parameters_of (^^foo)[0]).size () == 6);\n+static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[0]) :] == 1);\n+static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[1]) :] == 2);\n+static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[2]) :] == 3);\n+static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[3]) :] == 4);\n+static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[4]) :] == 5);\n+static_assert ([: constant_of (annotations_of (parameters_of (^^foo)[0])[5]) :] == 6);\n", "prefixes": [ "RFC" ] }