Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216023/?format=api
{ "id": 2216023, "url": "http://patchwork.ozlabs.org/api/patches/2216023/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/acQSYCLQ-MCBsZBO@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": "<acQSYCLQ-MCBsZBO@tucnak>", "list_archive_url": null, "date": "2026-03-25T16:50:40", "name": "[RFC] c++: Handle annotations in data_member_spec/define_aggregate", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "029d321bcf3e8e49bfb13003140f147ac5178c80", "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/acQSYCLQ-MCBsZBO@tucnak/mbox/", "series": [ { "id": 497474, "url": "http://patchwork.ozlabs.org/api/series/497474/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497474", "date": "2026-03-25T16:50:40", "name": "[RFC] c++: Handle annotations in data_member_spec/define_aggregate", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497474/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216023/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216023/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=e058mvFN;\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=e058mvFN", "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 4fgtGh0vDdz1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 03:51:40 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 0F9FF4B9DB44\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 16:51:38 +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 E8EE34BA2E0E\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 16:50:58 +0000 (GMT)", "from mx-prod-mc-01.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-659-tNTPdVawOsK18KfBSVsm5A-1; Wed,\n 25 Mar 2026 12:50:50 -0400", "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 14A4B1955D4E\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 16:50:45 +0000 (UTC)", "from tucnak.zalov.cz (unknown [10.45.225.193])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id CA04F19560B1; Wed, 25 Mar 2026 16:50:43 +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 62PGoex33827674\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Wed, 25 Mar 2026 17:50:41 +0100", "(from jakub@localhost)\n by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 62PGoeYI3827673;\n Wed, 25 Mar 2026 17:50:40 +0100" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 0F9FF4B9DB44", "OpenDKIM Filter v2.11.0 sourceware.org E8EE34BA2E0E" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org E8EE34BA2E0E", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org E8EE34BA2E0E", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774457459; cv=none;\n b=r4nriSQt4Pbk4NaZUyglEqab+tWXt253XcH4XoqUWM5degnWd9IY1y5xBGKzkCLyvXh3RHnkJb3XS2eHDq/8g8ZHAkFCsDyGxgWX9MfTl64kzmPolFBM07CFcL9JzYss4SxAxFeMa5ZUObf7mV0PRg4sIrSimvdGNPa3E5KhJP0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774457459; c=relaxed/simple;\n bh=/FoJFa9vPcTmeBJ2Y5YyWYcAFqln3YXofR46Qj7Mrb8=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=h1I8mf0nFvCWUGs8/LRVZaeVjMGpNK+i2gNGelAgSjult4kDntyKLQwGNzCZdJoqG1abG4UHip+cJeUWuo5BmVuuEIa5mCZNnf/m7BN0AlvYw6Yg0TNz15c0t7cTGT8FtnuzBTB/TiL8N8biMykQz9iMyjyUKr1tEtEOI3NXQAE=", "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=1774457458;\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=sWUye9q56qTm3foGTdUfUDvFCqkAmOjjtc6VGghP6Mg=;\n b=e058mvFNWpMK7hi7+1ha0X61w5LXDUrerg4kKyOcxMH+sMHYhss7c0JzfYWtqfksN+vYG0\n epqOwUI/RZSBgK2CmOJiUQrgVQlmGHo2OBqpietsWpR1JUDQXGueG4tqZrfkWpISH2+0X8\n SOWKrD3FgNEHQEAugqgsu9/IvdUYomA=", "X-MC-Unique": "tNTPdVawOsK18KfBSVsm5A-1", "X-Mimecast-MFC-AGG-ID": "tNTPdVawOsK18KfBSVsm5A_1774457446", "Date": "Wed, 25 Mar 2026 17:50:40 +0100", "From": "Jakub Jelinek <jakub@redhat.com>", "To": "Jason Merrill <jason@redhat.com>, Marek Polacek <polacek@redhat.com>,\n Jonathan Wakely <jwakely@redhat.com>", "Cc": "gcc-patches@gcc.gnu.org", "Subject": "[RFC PATCH] c++: Handle annotations in\n data_member_spec/define_aggregate", "Message-ID": "<acQSYCLQ-MCBsZBO@tucnak>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "W29VLBSJAtvRZVjMHlmUPTGfutk5cu1_409vWad-yAE_1774457446", "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 following patch attempts to implement another part of P3795R1\n(though with some changes Barry has queued for P3795R2, in particular\nthrowing on !has-type(r) in the annotations sequence or when the\nannotations are non-empty and name is not specified), in particular\nthe addition of annotations to data_member_options and handling it in\ndata_member_spec/define_aggregate etc.\n\nThis is on top of the earlier data_member_spec patch, though even if\nit is decided to revert that part of changes, it shouldn't be hard\nto adjust this patch to apply.\n\nTested on x86_64-linux.\n\n2026-03-25 Jakub Jelinek <jakub@redhat.com>\n\nlibstdc++-v3/\n\t* include/std/meta (std::meta::data_member_options): Add annotations\n\tmember.\ngcc/cp/\n\t* reflect.cc (get_range_elts): If N is negative, just use the tree\n\tas object to extract range from instead of finding Nth argument\n\tof a call.\n\t(eval_display_string_of): Handle annotations in\n\tREFLECT_DATA_MEMBER_SPEC.\n\t(eval_data_member_spec): Read and diagnose annotations.\n\t(eval_define_aggregate): Create annotations.\n\t(compare_reflections): Compare REFLECT_DATA_MEMBER_SPEC annotations.\n\t* mangle.cc (write_reflection): Mangle REFLECT_DATA_MEMBER_SPEC\n\tannotations.\ngcc/testsuite/\n\t* g++.dg/reflect/data_member_spec5.C: New test.\n\t* g++.dg/reflect/data_member_spec6.C: New test.\n\t* g++.dg/reflect/display_string_of1.C: Expect extra \", {}\" before\n\t\")\" for empty annotations, otherwise a list of annotations.\n\t* g++.dg/reflect/u8display_string_of1.C: Likewise.\n\t* g++.dg/reflect/define_aggregate9.C: New test.\n\t* g++.dg/reflect/mangle1.C: Test mangling of REFLECT_DATA_MEMBER_SPEC\n\tannotations.\n\n\n\tJakub", "diff": "--- libstdc++-v3/include/std/meta.jj\t2026-03-25 08:14:07.297917425 +0100\n+++ libstdc++-v3/include/std/meta\t2026-03-25 10:34:52.732153013 +0100\n@@ -423,6 +423,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n optional<int> alignment;\n optional<int> bit_width;\n bool no_unique_address = false;\n+ vector<info> annotations;\n };\n consteval info data_member_spec(data_member_options);\n consteval bool is_data_member_spec(info);\n--- gcc/cp/reflect.cc.jj\t2026-03-25 08:15:13.865777063 +0100\n+++ gcc/cp/reflect.cc\t2026-03-25 17:14:12.428239630 +0100\n@@ -383,18 +383,25 @@ enum get_range_elts_kind {\n eval_reflect_constant_array. For GET_INFO_VEC kind, <meta> ensures\n the argument is reference to reflection_range concept and so both\n range_value_t is info and range_refernce_t is cv info or cv info & or\n- cv info &&. */\n+ cv info &&. If N is negative, CALL is the expression to extract\n+ values from rather than N-th argument from CALL. */\n \n static tree\n get_range_elts (location_t loc, const constexpr_ctx *ctx, tree call, int n,\n \t\tbool *non_constant_p, bool *overflow_p, tree *jump_target,\n \t\tget_range_elts_kind kind, tree fun)\n {\n- gcc_checking_assert (call_expr_nargs (call) > n);\n- tree arg = get_nth_callarg (call, n);\n- tree parm = DECL_ARGUMENTS (cp_get_callee_fndecl_nofold (call));\n- for (int i = 0; i < n; ++i)\n- parm = DECL_CHAIN (parm);\n+ tree arg, parm;\n+ if (n < 0)\n+ arg = parm = call;\n+ else\n+ {\n+ gcc_checking_assert (call_expr_nargs (call) > n);\n+ arg = get_nth_callarg (call, n);\n+ parm = DECL_ARGUMENTS (cp_get_callee_fndecl_nofold (call));\n+ for (int i = 0; i < n; ++i)\n+\tparm = DECL_CHAIN (parm);\n+ }\n tree type = TREE_TYPE (arg);\n gcc_checking_assert (TYPE_REF_P (type));\n arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue, non_constant_p,\n@@ -539,7 +546,8 @@ get_range_elts (location_t loc, const co\n tree call = finish_call_expr (obj, &args, true, false, complain);\n if (call == error_mark_node)\n return call;\n- cp_walk_tree (&call, replace_parm_r, map, NULL);\n+ if (n >= 0)\n+ cp_walk_tree (&call, replace_parm_r, map, NULL);\n if (complain != tf_none)\n return call;\n call = cxx_eval_constant_expression (ctx, call, vc_prvalue, non_constant_p,\n@@ -3643,10 +3651,16 @@ eval_display_string_of (location_t loc,\n pp_printf (&pp, \"%T: %T\", d, BINFO_TYPE (r));\n }\n else if (kind == REFLECT_DATA_MEMBER_SPEC)\n- pp_printf (&pp, \"(%T, %E, %E, %E, %s)\", TREE_VEC_ELT (r, 0),\n-\t TREE_VEC_ELT (r, 1), TREE_VEC_ELT (r, 2), TREE_VEC_ELT (r, 3),\n-\t TREE_VEC_ELT (r, 4) == boolean_true_node\n-\t ? \"true\" : \"false\");\n+ {\n+ pp_printf (&pp, \"(%T, %E, %E, %E, %s, {\", TREE_VEC_ELT (r, 0),\n+\t\t TREE_VEC_ELT (r, 1), TREE_VEC_ELT (r, 2), TREE_VEC_ELT (r, 3),\n+\t\t TREE_VEC_ELT (r, 4) == boolean_true_node\n+\t\t ? \"true\" : \"false\");\n+ for (int i = 5; i < TREE_VEC_LENGTH (r); ++i)\n+\tpp_printf (&pp, \"%s%E\", i == 5 ? \"\" : \", \",\n+\t\t REFLECT_EXPR_HANDLE (TREE_VEC_ELT (r, i)));\n+ pp_printf (&pp, \"})\");\n+ }\n else if (eval_is_annotation (r, kind) == boolean_true_node)\n pp_printf (&pp, \"[[=%E]]\",\n \t tree_strip_any_location_wrapper (TREE_VALUE (TREE_VALUE (r))));\n@@ -5560,7 +5574,8 @@ eval_data_member_spec (location_t loc, c\n *non_constant_p = true;\n return NULL_TREE;\n }\n- tree args[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };\n+ tree args[6] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,\n+\t\t NULL_TREE};\n for (tree field = next_aggregate_field (TYPE_FIELDS (TREE_TYPE (opts)));\n field; field = next_aggregate_field (DECL_CHAIN (field)))\n if (tree name = DECL_NAME (field))\n@@ -5575,8 +5590,10 @@ eval_data_member_spec (location_t loc, c\n \t args[3] = field;\n \telse if (id_equal (name, \"no_unique_address\"))\n \t args[4] = field;\n+\telse if (id_equal (name, \"annotations\"))\n+\t args[5] = field;\n }\n- for (int i = 0; i < 5; ++i)\n+ for (int i = 0; i < 6; ++i)\n {\n if (args[i] == NULL_TREE)\n \tgoto fail;\n@@ -5623,6 +5640,19 @@ eval_data_member_spec (location_t loc, c\n \t args[i] = boolean_true_node;\n \t continue;\n \t}\n+ if (i == 5)\n+\t{\n+\t tree rtype\n+\t = cp_build_reference_type (TREE_TYPE (opt), /*rval*/false);\n+\t opt = build_address (opt);\n+\t opt = fold_convert (rtype, opt);\n+\t opt = get_info_vec (loc, ctx, opt, -1, non_constant_p, overflow_p,\n+\t\t\t jump_target, fun);\n+\t if (*jump_target || *non_constant_p)\n+\t return NULL_TREE;\n+\t args[i] = opt;\n+\t continue;\n+\t}\n /* Otherwise the member is optional<something>. */\n if (!CLASS_TYPE_P (TREE_TYPE (opt)))\n \tgoto fail;\n@@ -5854,6 +5884,10 @@ eval_data_member_spec (location_t loc, c\n return throw_exception (loc, ctx,\n \t\t\t \"neither name nor bit_width specified\",\n \t\t\t fun, non_constant_p, jump_target);\n+ if (args[1] == NULL_TREE && TREE_VEC_LENGTH (args[5]))\n+ return throw_exception (loc, ctx,\n+\t\t\t \"no name and non-empty annotations specified\",\n+\t\t\t fun, non_constant_p, jump_target);\n if (args[3])\n {\n if (!CP_INTEGRAL_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)\n@@ -5895,9 +5929,30 @@ eval_data_member_spec (location_t loc, c\n \t\t\t\t\"alignment is smaller than alignment_of\",\n \t\t\t\tfun, non_constant_p, jump_target);\n }\n- tree ret = make_tree_vec (5);\n+ for (int i = 0; i < TREE_VEC_LENGTH (args[5]); ++i)\n+ {\n+ tree r = REFLECT_EXPR_HANDLE (TREE_VEC_ELT (args[5], i));\n+ reflect_kind kind = REFLECT_EXPR_KIND (TREE_VEC_ELT (args[5], i));\n+ if (!has_type (r, kind))\n+\treturn throw_exception (loc, ctx, \"reflection does not have a type\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+ tree type = type_of (r, kind);\n+ if (eval_is_array_type (loc, type) == boolean_true_node\n+\t || eval_is_object_type (loc, type) == boolean_false_node)\n+\treturn throw_exception (loc, ctx, \"reflection does not have \"\n+\t\t\t\t\t \"non-array object type\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+ tree cst = eval_constant_of (loc, ctx, r, kind, non_constant_p,\n+\t\t\t\t overflow_p, jump_target, fun);\n+ if (cst == NULL_TREE)\n+\treturn NULL_TREE;\n+ TREE_VEC_ELT (args[5], i) = cst;\n+ }\n+ tree ret = make_tree_vec (5 + TREE_VEC_LENGTH (args[5]));\n for (int i = 0; i < 5; ++i)\n TREE_VEC_ELT (ret, i) = args[i];\n+ for (int i = 0; i < TREE_VEC_LENGTH (args[5]); ++i)\n+ TREE_VEC_ELT (ret, i + 5) = TREE_VEC_ELT (args[5], i);\n return get_reflection_raw (loc, ret, REFLECT_DATA_MEMBER_SPEC);\n }\n \n@@ -6187,12 +6242,24 @@ eval_define_aggregate (location_t loc, c\n \t\t\t * BITS_PER_UNIT);\n \t DECL_USER_ALIGN (f) = 1;\n \t}\n- if (TREE_VEC_ELT (a, 4) == boolean_true_node)\n+ if (TREE_VEC_ELT (a, 4) == boolean_true_node\n+\t || TREE_VEC_LENGTH (a) != 5)\n \t{\n-\t tree attr = build_tree_list (NULL_TREE,\n-\t\t\t\t get_identifier (\"no_unique_address\"));\n-\t attr = build_tree_list (attr, NULL_TREE);\n-\t cplus_decl_attributes (&f, attr, 0);\n+\t tree attrs = NULL_TREE, attr;\n+\t if (TREE_VEC_ELT (a, 4) == boolean_true_node)\n+\t {\n+\t attr = build_tree_list (NULL_TREE,\n+\t\t\t\t get_identifier (\"no_unique_address\"));\n+\t attrs = build_tree_list (attr, NULL_TREE);\n+\t }\n+\t for (int i = TREE_VEC_LENGTH (a) - 1; i >= 5; --i)\n+\t {\n+\t attr = build_tree_list (internal_identifier,\n+\t\t\t\t annotation_identifier);\n+\t tree val = REFLECT_EXPR_HANDLE (TREE_VEC_ELT (a, i));\n+\t attrs = tree_cons (attr, build_tree_list (NULL_TREE, val), attrs);\n+\t }\n+\t cplus_decl_attributes (&f, attrs, 0);\n \t}\n fields = f;\n }\n@@ -8395,13 +8462,24 @@ compare_reflections (tree lhs, tree rhs)\n rhs = maybe_update_function_parm (rhs);\n }\n else if (lkind == REFLECT_DATA_MEMBER_SPEC)\n- return (TREE_VEC_ELT (lhs, 0) == TREE_VEC_ELT (rhs, 0)\n-\t && TREE_VEC_ELT (lhs, 1) == TREE_VEC_ELT (rhs, 1)\n-\t && tree_int_cst_equal (TREE_VEC_ELT (lhs, 2),\n-\t\t\t\t TREE_VEC_ELT (rhs, 2))\n-\t && tree_int_cst_equal (TREE_VEC_ELT (lhs, 3),\n-\t\t\t\t TREE_VEC_ELT (rhs, 3))\n-\t && TREE_VEC_ELT (lhs, 4) == TREE_VEC_ELT (rhs, 4));\n+ {\n+ if (typedef_variant_p (TREE_VEC_ELT (lhs, 0))\n+\t != typedef_variant_p (TREE_VEC_ELT (rhs, 0))\n+\t || !same_type_p (TREE_VEC_ELT (lhs, 0), TREE_VEC_ELT (rhs, 0))\n+\t || TREE_VEC_ELT (lhs, 1) != TREE_VEC_ELT (rhs, 1)\n+\t || !tree_int_cst_equal (TREE_VEC_ELT (lhs, 2),\n+\t\t\t\t TREE_VEC_ELT (rhs, 2))\n+\t || !tree_int_cst_equal (TREE_VEC_ELT (lhs, 3),\n+\t\t\t\t TREE_VEC_ELT (rhs, 3))\n+\t || TREE_VEC_ELT (lhs, 4) != TREE_VEC_ELT (rhs, 4)\n+\t || TREE_VEC_LENGTH (lhs) != TREE_VEC_LENGTH (rhs))\n+\treturn false;\n+ for (int i = 5; i < TREE_VEC_LENGTH (lhs); ++i)\n+\tif (!compare_reflections (TREE_VEC_ELT (lhs, i),\n+\t\t\t\t TREE_VEC_ELT (rhs, i)))\n+\t return false;\n+ return true;\n+ }\n else if (lkind == REFLECT_ANNOTATION)\n return TREE_VALUE (lhs) == TREE_VALUE (rhs);\n else if (TYPE_P (lhs) && TYPE_P (rhs))\n--- gcc/cp/mangle.cc.jj\t2026-03-23 11:26:45.800386996 +0100\n+++ gcc/cp/mangle.cc\t2026-03-25 17:25:42.742618257 +0100\n@@ -4254,6 +4254,8 @@ write_reflection (tree refl)\n write_char ('_');\n if (integer_nonzerop (TREE_VEC_ELT (arg, 4)))\n \twrite_char ('n');\n+ for (int i = 5; i < TREE_VEC_LENGTH (arg); ++i)\n+\twrite_template_arg (REFLECT_EXPR_HANDLE (TREE_VEC_ELT (arg, i)));\n }\n }\n \n--- gcc/testsuite/g++.dg/reflect/data_member_spec5.C.jj\t2026-03-25 13:48:30.599086322 +0100\n+++ gcc/testsuite/g++.dg/reflect/data_member_spec5.C\t2026-03-25 15:07:54.567723729 +0100\n@@ -0,0 +1,107 @@\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection\" }\n+// Test std::meta::data_member_spec.\n+\n+#include <meta>\n+\n+using namespace std::meta;\n+\n+consteval bool\n+valid_data_member_spec (data_member_options opts)\n+{\n+ try { data_member_spec (opts); }\n+ catch (std::meta::exception &) { return false; }\n+ return true;\n+}\n+\n+struct S { int a, b; };\n+\n+consteval bool\n+foo ()\n+{\n+ constexpr int two = 2;\n+ [[=1]] int three = 3;\n+ constexpr int fourtytwo = 42;\n+ constexpr double fourtytwoandhalf = 42.5;\n+ data_member_options a = { .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { ^^two, reflect_constant (42),\n+\t\t\t\t\t annotations_of (^^three)[0],\n+\t\t\t\t\t reflect_constant (42.5),\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } };\n+ auto dmsa = data_member_spec (a);\n+ if (!is_data_member_spec (dmsa))\n+ throw 1;\n+ if (dmsa\n+ != data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2),\n+\t\t\t\t\t ^^fourtytwo,\n+\t\t\t\t\t reflect_constant (1),\n+\t\t\t\t\t ^^fourtytwoandhalf,\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } }))\n+ throw 2;\n+ if (dmsa == data_member_spec ({ .type = ^^int, .name = \"_\" }))\n+ throw 3;\n+ if (dmsa\n+ == data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2L),\n+\t\t\t\t\t ^^fourtytwo,\n+\t\t\t\t\t reflect_constant (1),\n+\t\t\t\t\t ^^fourtytwoandhalf,\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } }))\n+ throw 4;\n+ if (dmsa\n+ == data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2),\n+\t\t\t\t\t ^^two,\n+\t\t\t\t\t reflect_constant (1),\n+\t\t\t\t\t ^^fourtytwoandhalf,\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } }))\n+ throw 4;\n+ if (dmsa\n+ == data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2),\n+\t\t\t\t\t ^^fourtytwo,\n+\t\t\t\t\t reflect_constant (3),\n+\t\t\t\t\t ^^fourtytwoandhalf,\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } }))\n+ throw 5;\n+ if (dmsa\n+ == data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2),\n+\t\t\t\t\t ^^fourtytwo,\n+\t\t\t\t\t reflect_constant (1),\n+\t\t\t\t\t reflect_constant (42.25),\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } }))\n+ throw 6;\n+ if (dmsa\n+ == data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2),\n+\t\t\t\t\t ^^fourtytwo,\n+\t\t\t\t\t reflect_constant (1),\n+\t\t\t\t\t reflect_constant (42.25),\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } }))\n+ throw 7;\n+ if (dmsa\n+ == data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { reflect_constant (2),\n+\t\t\t\t\t ^^fourtytwo,\n+\t\t\t\t\t reflect_constant (1),\n+\t\t\t\t\t reflect_constant (42.5),\n+\t\t\t\t\t reflect_constant (S { 2, 2 }) } }))\n+ throw 8;\n+ return true;\n+}\n+\n+static_assert (foo ());\n+\n+constexpr int arr[1] = { 1 };\n+constexpr int i = 42;\n+constexpr S s = { 42, 43 };\n+\n+static_assert (!valid_data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^:: } }));\n+static_assert (!valid_data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^foo } }));\n+static_assert (!valid_data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^arr } }));\n+static_assert (!valid_data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^arr } }));\n+static_assert (valid_data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^i } }));\n+static_assert (valid_data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^s } }));\n+static_assert (!valid_data_member_spec ({ .type = ^^int, .bit_width = 0, .annotations = { ^^i } }));\n--- gcc/testsuite/g++.dg/reflect/data_member_spec6.C.jj\t2026-03-25 13:48:38.373955304 +0100\n+++ gcc/testsuite/g++.dg/reflect/data_member_spec6.C\t2026-03-25 13:58:47.664661356 +0100\n@@ -0,0 +1,12 @@\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection\" }\n+// Test std::meta::data_member_spec.\n+\n+#include <meta>\n+\n+using namespace std::meta;\n+\n+struct T { constexpr T () : t (42) {} constexpr int bar () const { return t; } protected: int t; };\n+constexpr T t;\n+\n+constexpr auto a = data_member_spec ({ .type = ^^int, .name = \"a\", .annotations = { ^^t } }); // { dg-error \"'T' must be a cv-unqualified structural type that is not a reference type\" }\n--- gcc/testsuite/g++.dg/reflect/display_string_of1.C.jj\t2026-03-24 23:13:58.419214921 +0100\n+++ gcc/testsuite/g++.dg/reflect/display_string_of1.C\t2026-03-25 17:12:51.955591801 +0100\n@@ -115,10 +115,12 @@ foo (int a, const long b, T c, int d[4],\n static_assert (display_string_of (^^NSAlias) == \"NSAlias\");\n static_assert (display_string_of (^^NS) == \"NS\");\n static_assert (display_string_of (bases_of (^^S, ctx)[0]) == \"S: B\");\n- static_assert (display_string_of (data_member_spec ({ .type = ^^int, .name = \"member\", .alignment = 128, .no_unique_address = true })) == \"(int, member, 128, , true)\");\n- static_assert (display_string_of (data_member_spec ({ .type = ^^const int, .name = \"member\", .bit_width = 6 })) == \"(const int, member, , 6, false)\");\n- static_assert (display_string_of (data_member_spec ({ .type = ^^int, .bit_width = 0 })) == \"(int, , , 0, false)\");\n- static_assert (display_string_of (data_member_spec ({ .type = ^^long, .bit_width = 5 })) == \"(long int, , , 5, false)\");\n+ static_assert (display_string_of (data_member_spec ({ .type = ^^int, .name = \"member\", .alignment = 128, .no_unique_address = true })) == \"(int, member, 128, , true, {})\");\n+ static_assert (display_string_of (data_member_spec ({ .type = ^^const int, .name = \"member\", .bit_width = 6 })) == \"(const int, member, , 6, false, {})\");\n+ static_assert (display_string_of (data_member_spec ({ .type = ^^int, .bit_width = 0 })) == \"(int, , , 0, false, {})\");\n+ static_assert (display_string_of (data_member_spec ({ .type = ^^long, .bit_width = 5 })) == \"(long int, , , 5, false, {})\");\n+ static_assert (display_string_of (data_member_spec ({ .type = ^^long, .bit_width = 5 })) == \"(long int, , , 5, false, {})\");\n+ static_assert (display_string_of (data_member_spec ({ .type = ^^int, .name = \"_\", .annotations = { reflect_constant (42), reflect_constant (42.5) }})) == \"(int, _, , , false, {42, 4.25e+1})\");\n static_assert (display_string_of (annotations_of (^^bar)[0]) == \"[[=1]]\");\n static_assert (display_string_of (annotations_of (^^bar)[1]) == \"[[=AN{1, 42, ' '}]]\");\n static_assert (display_string_of (^^int) == \"int\");\n--- gcc/testsuite/g++.dg/reflect/u8display_string_of1.C.jj\t2026-03-24 23:13:58.597110034 +0100\n+++ gcc/testsuite/g++.dg/reflect/u8display_string_of1.C\t2026-03-25 17:13:10.900273473 +0100\n@@ -115,10 +115,11 @@ foo (int a, const long b, T c, int d[4],\n static_assert (u8display_string_of (^^NSAlias) == u8\"NSAlias\");\n static_assert (u8display_string_of (^^NS) == u8\"NS\");\n static_assert (u8display_string_of (bases_of (^^S, ctx)[0]) == u8\"S: B\");\n- static_assert (u8display_string_of (data_member_spec ({ .type = ^^int, .name = \"member\", .alignment = 128, .no_unique_address = true })) == u8\"(int, member, 128, , true)\");\n- static_assert (u8display_string_of (data_member_spec ({ .type = ^^const int, .name = \"member\", .bit_width = 6 })) == u8\"(const int, member, , 6, false)\");\n- static_assert (u8display_string_of (data_member_spec ({ .type = ^^int, .bit_width = 0 })) == u8\"(int, , , 0, false)\");\n- static_assert (u8display_string_of (data_member_spec ({ .type = ^^long, .bit_width = 5 })) == u8\"(long int, , , 5, false)\");\n+ static_assert (u8display_string_of (data_member_spec ({ .type = ^^int, .name = \"member\", .alignment = 128, .no_unique_address = true })) == u8\"(int, member, 128, , true, {})\");\n+ static_assert (u8display_string_of (data_member_spec ({ .type = ^^const int, .name = \"member\", .bit_width = 6 })) == u8\"(const int, member, , 6, false, {})\");\n+ static_assert (u8display_string_of (data_member_spec ({ .type = ^^int, .bit_width = 0 })) == u8\"(int, , , 0, false, {})\");\n+ static_assert (u8display_string_of (data_member_spec ({ .type = ^^long, .bit_width = 5 })) == u8\"(long int, , , 5, false, {})\");\n+ static_assert (u8display_string_of (data_member_spec ({ .type = ^^int, .name = u8\"_\", .annotations = { reflect_constant (42), reflect_constant (42.5) }})) == u8\"(int, _, , , false, {42, 4.25e+1})\");\n static_assert (u8display_string_of (annotations_of (^^bar)[0]) == u8\"[[=1]]\");\n static_assert (u8display_string_of (annotations_of (^^bar)[1]) == u8\"[[=AN{1, 42, ' '}]]\");\n static_assert (u8display_string_of (^^int) == u8\"int\");\n--- gcc/testsuite/g++.dg/reflect/define_aggregate9.C.jj\t2026-03-25 17:04:54.522614030 +0100\n+++ gcc/testsuite/g++.dg/reflect/define_aggregate9.C\t2026-03-25 17:17:38.458776225 +0100\n@@ -0,0 +1,35 @@\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection\" }\n+// Test std::meta::define_aggregate.\n+\n+#include <meta>\n+\n+using namespace std::meta;\n+\n+struct S { int a, b; };\n+struct T;\n+\n+consteval\n+{\n+ constexpr int two = 2;\n+ [[=1]] int three = 3;\n+ constexpr int fourtytwo = 42;\n+ constexpr double fourtytwoandhalf = 42.5;\n+ data_member_options a = { .type = ^^int, .name = \"_\",\n+\t\t\t .annotations = { ^^two, reflect_constant (42),\n+\t\t\t\t\t annotations_of (^^three)[0],\n+\t\t\t\t\t reflect_constant (42.5),\n+\t\t\t\t\t reflect_constant (S { 1, 2 }) } };\n+ auto dmsa = data_member_spec (a);\n+ define_aggregate (^^T, { dmsa });\n+}\n+consteval\n+{\n+ static_assert (annotations_of (^^T::_).size () == 5);\n+ static_assert ([: constant_of (annotations_of (^^T::_)[0]) :] == 2);\n+ static_assert ([: constant_of (annotations_of (^^T::_)[1]) :] == 42);\n+ static_assert ([: constant_of (annotations_of (^^T::_)[2]) :] == 1);\n+ static_assert ([: constant_of (annotations_of (^^T::_)[3]) :] == 42.5);\n+ static_assert ([: constant_of (annotations_of (^^T::_)[4]) :].a == 1);\n+ static_assert ([: constant_of (annotations_of (^^T::_)[4]) :].b == 2);\n+}\n--- gcc/testsuite/g++.dg/reflect/mangle1.C.jj\t2026-03-24 23:41:54.125019058 +0100\n+++ gcc/testsuite/g++.dg/reflect/mangle1.C\t2026-03-25 17:35:37.373600962 +0100\n@@ -63,6 +63,7 @@ namespace NS2 {\n };\n struct Z {\n };\n+ struct AA { int a, b; };\n }\n \n constexpr auto ctx = std::meta::access_context::current ();\n@@ -165,6 +166,10 @@ baz (int x)\n bar <332, std::meta::data_member_spec ({ .type = ^^unsigned short, .name = \"b\", .bit_width = 5 })> (); // data member description\n bar <333, std::meta::data_member_spec ({ .type = ^^long, .bit_width = 3 })> (); // data member description\n bar <334, std::meta::data_member_spec ({ .type = ^^int, .bit_width = 0 })> (); // data member description\n+ bar <335, std::meta::data_member_spec ({ .type = ^^int, .name = \"_\",\n+\t\t\t\t\t .annotations = { std::meta::reflect_constant (42),\n+\t\t\t\t\t\t\t std::meta::reflect_constant (43L),\n+\t\t\t\t\t\t\t std::meta::reflect_constant (NS2::AA { 1, 2 }) } })> (); // data member description\n bar <340, ^^NS2::X::~X> (); // function\n }\n \n@@ -250,4 +255,5 @@ baz (int x)\n // { dg-final { scan-assembler \"_Z3barILi332ELDmdst_1b__5_EEvv\" } }\n // { dg-final { scan-assembler \"_Z3barILi333ELDmdsl___3_EEvv\" } }\n // { dg-final { scan-assembler \"_Z3barILi334ELDmdsi___0_EEvv\" } }\n+// { dg-final { scan-assembler \"_Z3barILi335ELDmdsi_1____Li42ELl43EXtlN3NS22AAELi1ELi2EEEEEvv\" } }\n // { dg-final { scan-assembler \"_Z3barILi340ELDmfnN3NS21XD4EvEEvv\" } }\n", "prefixes": [ "RFC" ] }