Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2217402/?format=api
{ "id": 2217402, "url": "http://patchwork.ozlabs.org/api/patches/2217402/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/acgFmf_HboMo2vcn@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": "<acgFmf_HboMo2vcn@tucnak>", "list_archive_url": null, "date": "2026-03-28T16:45:14", "name": "c++, v3: Handle annotations in data_member_spec/define_aggregate from P3795R2", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "be2831228d6c9902fee6a1dfad5a65b669fdb2b5", "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/acgFmf_HboMo2vcn@tucnak/mbox/", "series": [ { "id": 497877, "url": "http://patchwork.ozlabs.org/api/series/497877/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497877", "date": "2026-03-28T16:45:14", "name": "c++, v3: Handle annotations in data_member_spec/define_aggregate from P3795R2", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497877/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2217402/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2217402/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=gp9opKNa;\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=gp9opKNa", "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 4fjkGt3RYNz1y1x\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 29 Mar 2026 03:58:11 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 715E24BA23D7\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 28 Mar 2026 16:58:09 +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 1A5964BA2E30\n for <gcc-patches@gcc.gnu.org>; Sat, 28 Mar 2026 16:57:24 +0000 (GMT)", "from mx-prod-mc-06.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-497-1jHiVBI9PoaiAjMzjit0RA-1; Sat,\n 28 Mar 2026 12:57:21 -0400", "from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17])\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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id CC3FA180035C\n for <gcc-patches@gcc.gnu.org>; Sat, 28 Mar 2026 16:57:20 +0000 (UTC)", "from tucnak.zalov.cz (unknown [10.44.32.9])\n by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id 23EF41955D84; Sat, 28 Mar 2026 16:57:19 +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 62SGvHdV1667395\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Sat, 28 Mar 2026 17:57:17 +0100", "(from jakub@localhost)\n by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 62SGvGEE1667394;\n Sat, 28 Mar 2026 17:57:16 +0100" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 715E24BA23D7", "OpenDKIM Filter v2.11.0 sourceware.org 1A5964BA2E30" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 1A5964BA2E30", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 1A5964BA2E30", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774717044; cv=none;\n b=PVUiDKgvxeBx45RV0mU8UZ4D6vkg4Ng0XjHGXmFJ43VqdLXZor0FJghWRLyQz8j9npM/bgKKTx6kZeGHYT6DsFN9ItY7lMO7ba07xQUT3DzTEjhFkAlI9R56U5sNm7vMPuafhNWc1FpCg9IBHCGBxosdQ50nv8U/z9zEspuN/H0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774717044; c=relaxed/simple;\n bh=jU81jqfs8ddoVWuKYAMfUY0luZzRJNa0KulMU6ot6qQ=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=BQHmnMMbnnU/bPE5Q5ir6LeaUEsKmMrOIje85UWGsxmXF0z/NXL2mhbRK5xhRrOrp1+NcpDDkMe3K4lbIdyFK6f6cqKW6HOG+w2u7lIUasli4BMEhxKI7bCDgPnaWOwQWqun3PFHZWh3EJm2uHX8bluGeYjKF88i+pHDSUbpie8=", "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=1774717043;\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=Bj8WUBq+LLxatbJAnCxH6K3ucXGCjkFVrw3Pt0LnDWo=;\n b=gp9opKNaX2eM/JZHQSnV8TJMouiq0ezLjmLSdhQdDiOy9a0cH1dQFkrMzMcKiCPBsrKrdl\n kwR4Fyngsqh+PH4xjB/vCjQYlqJop4zBc1d4BNLrN7PEu1VVUxBUIjLbL9KgECKg8z7EFD\n ZedCxVr/dI1aa2VQTIFcbDT0ErkoeF8=", "X-MC-Unique": "1jHiVBI9PoaiAjMzjit0RA-1", "X-Mimecast-MFC-AGG-ID": "1jHiVBI9PoaiAjMzjit0RA_1774717041", "Resent-From": "Jakub Jelinek <jakub@redhat.com>", "Resent-Date": "Sat, 28 Mar 2026 17:57:16 +0100", "Resent-Message-ID": "<acgIbGecP7gtcu5r@tucnak>", "Resent-To": "Jason Merrill <jason@redhat.com>,\n Marek Polacek <polacek@redhat.com>,\n Jonathan Wakely <jwakely@redhat.com>, gcc-patches@gcc.gnu.org", "Date": "Sat, 28 Mar 2026 17:45:14 +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": "[PATCH] c++, v3: Handle annotations in\n data_member_spec/define_aggregate from P3795R2", "Message-ID": "<acgFmf_HboMo2vcn@tucnak>", "References": "<acQSYCLQ-MCBsZBO@tucnak>\n <acRAR6USZZUC8jaY@tucnak>", "MIME-Version": "1.0", "In-Reply-To": "<acRAR6USZZUC8jaY@tucnak>", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.17", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "wtuWqwwPz994108AI1mfuq9ZJa2peRy9vr9NmBZ1l-4_1774717041", "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 Wed, Mar 25, 2026 at 09:06:31PM +0100, Jakub Jelinek wrote:\n> On Wed, Mar 25, 2026 at 05:50:40PM +0100, Jakub Jelinek wrote:\n> > The following patch attempts to implement another part of P3795R1\n> > (though with some changes Barry has queued for P3795R2, in particular\n> > throwing on !has-type(r) in the annotations sequence or when the\n> > annotations are non-empty and name is not specified), in particular\n> > the addition of annotations to data_member_options and handling it in\n> > data_member_spec/define_aggregate etc.\n> > \n> > This is on top of the earlier data_member_spec patch, though even if\n> > it is decided to revert that part of changes, it shouldn't be hard\n> > to adjust this patch to apply.\n> \n> Here is an updated patch which is not on top of the earlier data_member_spec\n> patch. And updates various function comments to include ANN etc.\n\nNow reposted as no longer RFC PATCH given that it has been voted in and\nproperly successfully bootstrapped/regtested on x86_64-linux and i686-linux.\n\n2026-03-28 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_is_bit_field, eval_type_of, eval_size_of, eval_alignment_of,\n\teval_bit_size_of, eval_has_identifier, eval_identifier_of): Adjust\n\tfunction comments from P3795R2.\n\t(eval_display_string_of): Handle annotations in\n\tREFLECT_DATA_MEMBER_SPEC.\n\t(eval_annotations_of): Adjust function comments from P3795R2.\n\t(eval_data_member_spec): Likewise. Read and diagnose annotations.\n\t(eval_define_aggregate): Adjust function comments from P3795R2.\n\tCreate 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\n\tJakub", "diff": "--- libstdc++-v3/include/std/meta.jj\t2026-03-25 20:19:10.759162427 +0100\n+++ libstdc++-v3/include/std/meta\t2026-03-25 20:19:53.791992428 +0100\n@@ -422,6 +422,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(info, data_member_options);\n consteval bool is_data_member_spec(info);\n--- gcc/cp/reflect.cc.jj\t2026-03-25 20:19:10.715163161 +0100\n+++ gcc/cp/reflect.cc\t2026-03-25 20:32:38.262640083 +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@@ -1853,7 +1861,7 @@ eval_is_explicit (tree r)\n \n /* Process std::meta::is_bit_field.\n Returns: true if r represents a bit-field, or if r represents a data member\n- description (T,N,A,W,NUA) for which W is not _|_. Otherwise, false. */\n+ description (T,N,A,W,NUA,ANN) for which W is not _|_. Otherwise, false. */\n \n static tree\n eval_is_bit_field (const_tree r, reflect_kind kind)\n@@ -2518,8 +2526,8 @@ type_of (tree r, reflect_kind kind)\n \t of the enum-specifier as specified in [dcl.enum].\n -- Otherwise, if r represents a direct base class relationship (D,B), then\n a reflection of B.\n- -- Otherwise, for a data member description (T,N,A,W,NUA), a reflection of\n- the type T. */\n+ -- Otherwise, for a data member description (T,N,A,W,NUA,ANN), a reflection\n+ of the type T. */\n \n static tree\n eval_type_of (location_t loc, const constexpr_ctx *ctx, tree r,\n@@ -3169,7 +3177,7 @@ eval_offset_of (location_t loc, const co\n /* Process std::meta::size_of.\n Returns: If r represents\n -- a non-static data member of type T,\n- -- a data member description (T,N,A,W,NUA), or\n+ -- a data member description (T,N,A,W,NUA,ANN), or\n -- dealias(r) represents a type T,\n then sizeof(T) if T is not a reference type and size_of(add_pointer(^^T))\n otherwise. Otherwise, size_of(type_of(r)).\n@@ -3178,7 +3186,7 @@ eval_offset_of (location_t loc, const co\n -- dealias(r) is a reflection of a type, object, value, variable of\n \tnon-reference type, non-static data member that is not a bit-field,\n \tdirect base class relationship, or data member description\n-\t(T,N,A,W,NUA) where W is not _|_.\n+\t(T,N,A,W,NUA,ANN) where W is not _|_.\n -- If dealias(r) represents a type, then is_complete_type(r) is true. */\n \n static tree\n@@ -3229,12 +3237,13 @@ eval_size_of (location_t loc, const cons\n -- Otherwise, if r represents a non-static data member M of a class C,\n then the alignment of the direct member subobject corresponding to M of a\n complete object of type C.\n- -- Otherwise, r represents a data member description (T,N,A,W,NUA).\n+ -- Otherwise, r represents a data member description (T,N,A,W,NUA,ANN).\n If A is not _|_, then the value A. Otherwise, alignment_of(^^T).\n Throws: meta::exception unless all of the following conditions are met:\n -- dealias(r) is a reflection of a type, object, variable of non-reference\n type, non-static data member that is not a bit-field, direct base class\n- relationship, or data member description (T,N,A,W,NUA) where W is _|_.\n+ relationship, or data member description (T,N,A,W,NUA,ANN) where W is\n+ _|_.\n -- If dealias(r) represents a type, then is_complete_type(r) is true. */\n \n static tree\n@@ -3303,7 +3312,7 @@ eval_alignment_of (location_t loc, const\n Returns:\n -- If r represents an unnamed bit-field or a non-static data member that\n \tis a bit-field with width W, then W.\n- -- Otherwise, if r represents a data member description (T,N,A,W,NUA)\n+ -- Otherwise, if r represents a data member description (T,N,A,W,NUA,ANN)\n \tand W is not _|_, then W.\n -- Otherwise, CHAR_BIT * size_of(r).\n \n@@ -3400,8 +3409,8 @@ eval_bit_size_of (location_t loc, const\n namespace, or namespace alias, then true.\n -- Otherwise, if r represents a direct base class relationship, then\n has_identifier(type_of(r)).\n- -- Otherwise, r represents a data member description (T,N,A,W,NUA); true if\n- N is not _|_. Otherwise, false. */\n+ -- Otherwise, r represents a data member description (T,N,A,W,NUA,ANN);\n+ true if N is not _|_. Otherwise, false. */\n \n static tree\n eval_has_identifier (tree r, reflect_kind kind)\n@@ -3516,7 +3525,7 @@ eval_has_identifier (tree r, reflect_kin\n the declaration of that entity.\n -- Otherwise, if r represents a direct base class relationship, then\n identifier_of(type_of(r)) or u8identifier_of(type_of(r)), respectively.\n- -- Otherwise, r represents a data member description (T,N,A,W,NUA);\n+ -- Otherwise, r represents a data member description (T,N,A,W,NUA,ANN);\n a string_view or u8string_view, respectively, containing the identifier\n N.\n Throws: meta::exception unless has_identifier(r) is true and the identifier\n@@ -3643,10 +3652,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@@ -3762,15 +3777,21 @@ remove_const (tree type)\n }\n \n /* Process std::meta::annotations_of and annotations_of_with_type.\n- Let E be\n- -- the corresponding base-specifier if item represents a direct base class\n- relationship,\n- -- otherwise, the entity represented by item.\n+ For a function F, let S(F) be the set of declarations, ignoring any explicit\n+ instantiations, that declare either F or a templated function of which F is\n+ a specialization.\n Returns: A vector containing all of the reflections R representing each\n- annotation applying to each declaration of E that precedes either some\n- point in the evaluation context or a point immediately following the\n- class-specifier of the outermost class for which such a point is in a\n- complete-class context.\n+ annotation applying to:\n+ -- if item represents a function parameter P of a function F, then the\n+ declaration of P in each declaration of F in S(F),\n+ -- otherwise, if item represents a function F, then each declaration of F\n+ in S(F),\n+ -- otherwise, if item represents a direct base class relationship (D,B),\n+ then the corresponding base-specifier in the definition of D,\n+ -- otherwise, each declaration of the entity represented by item,\n+ such that precedes either some point in the evaluation context or a point\n+ immediately following the class-specifier of the outermost class for which\n+ such a point is in a complete-class context.\n For any two reflections R1 and R2 in the returned vector, if the annotation\n represented by R1 precedes the annotation represented by R2, then R1\n appears before R2.\n@@ -3779,8 +3800,8 @@ remove_const (tree type)\n from T.\n \n Throws: meta::exception unless item represents a type, type alias,\n- variable, function, namespace, enumerator, direct base class relationship,\n- or non-static data member. */\n+ variable, function, function parameter, namespace, enumerator, direct base\n+ class relationship, or non-static data member. */\n \n static tree\n eval_annotations_of (location_t loc, const constexpr_ctx *ctx, tree r,\n@@ -5517,15 +5538,17 @@ eval_variant_alternative (location_t loc\n }\n \n /* Process std::meta::data_member_spec.\n- Returns: A reflection of a data member description (T,N,A,W,NUA) where\n+ Returns: A reflection of a data member description (T,N,A,W,NUA,ANN) where\n -- T is the type represented by dealias(type),\n -- N is either the identifier encoded by options.name or _|_ if\n options.name does not contain a value,\n -- A is either the alignment value held by options.alignment or _|_ if\n options.alignment does not contain a value,\n -- W is either the value held by options.bit_width or _|_ if\n- options.bit_width does not contain a value, and\n- -- NUA is the value held by options.no_unique_address.\n+ options.bit_width does not contain a value,\n+ -- NUA is the value held by options.no_unique_address, and\n+ -- ANN is the sequence of values constant_of(r) for each r in\n+ options.annotations.\n Throws: meta::exception unless the following conditions are met:\n -- dealias(type) represents either an object type or a reference type;\n -- if options.name contains a value, then:\n@@ -5537,15 +5560,18 @@ eval_variant_alternative (location_t loc\n \t that is not a keyword when interpreted with the ordinary literal\n \t encoding;\n -- if options.name does not contain a value, then options.bit_width\n- contains a value;\n+ contains a value and options.annotations is empty;\n -- if options.bit_width contains a value V, then\n -- is_integral_type(type) || is_enum_type(type) is true,\n -- options.alignment does not contain a value,\n -- options.no_unique_address is false,\n -- V is not negative, and\n- -- if V equals 0, then options.name does not contain a value; and\n+ -- if V equals 0, then options.name does not contain a value;\n -- if options.alignment contains a value, it is an alignment value not less\n- than alignment_of(type). */\n+ than alignment_of(type); and\n+ -- for every reflection r in options.annotations, has-type(r) is true,\n+ type_of(r) represents a non-array object type, and evaluation of\n+ constant_of(r) does not exit via an exception. */\n \n static tree\n eval_data_member_spec (location_t loc, const constexpr_ctx *ctx,\n@@ -5564,7 +5590,8 @@ eval_data_member_spec (location_t loc, c\n *non_constant_p = true;\n return NULL_TREE;\n }\n- tree args[5] = { type, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };\n+ tree args[6] = { type, 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@@ -5577,8 +5604,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 = 1; i < 5; ++i)\n+ for (int i = 1; i < 6; ++i)\n {\n if (args[i] == NULL_TREE)\n \tgoto fail;\n@@ -5602,6 +5631,21 @@ 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 /* To handle annotations, read it using input range from\n+\t std::vector<info>. */\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@@ -5833,6 +5877,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@@ -5874,17 +5922,38 @@ 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 /* Process std::meta::define_aggregate.\n Let C be the type represented by class_type and r_K be the Kth reflection\n value in mdescrs.\n- For every r_K in mdescrs, let (T_K,N_K,A_K,W_K,NUA_K) be the corresponding\n- data member description represented by r_K.\n+ For every r_K in mdescrs, let (T_K,N_K,A_K,W_K,NUA_K,ANN_K) be the\n+ corresponding data member description represented by r_K.\n Constant When:\n -- class_type represents a cv-unqualified class type;\n -- C is incomplete from every point in the evaluation context;\n@@ -5915,6 +5984,8 @@ eval_data_member_spec (location_t loc, c\n \t Otherwise, M_K is not a bit-field.\n -- If A_K is not _|_, M_K has the alignment-specifier alignas(A_K).\n \t Otherwise, M_K has no alignment-specifier.\n+ -- M_K has an annotation whose underlying constant is r for every\n+\t reflection r in ANN_K.\n -- For every r_L in mdescrs such that K<L, the declaration corresponding to\n r_K precedes the declaration corresponding to r_L.\n Returns: class_type.\n@@ -6166,12 +6237,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@@ -8373,13 +8456,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-25 20:19:10.715163161 +0100\n+++ gcc/cp/mangle.cc\t2026-03-25 20:19:53.793444246 +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 20:19:53.793845668 +0100\n+++ gcc/testsuite/g++.dg/reflect/data_member_spec5.C\t2026-03-25 20:57:51.968202948 +0100\n@@ -0,0 +1,114 @@\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 (info type, data_member_options opts)\n+{\n+ try { data_member_spec (type, 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 = { .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 (^^int, a);\n+ if (!is_data_member_spec (dmsa))\n+ throw 1;\n+ if (dmsa\n+ != data_member_spec (^^int,\n+\t\t\t { .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 (^^int, { .name = \"_\" }))\n+ throw 3;\n+ if (dmsa\n+ == data_member_spec (^^int,\n+\t\t\t { .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 (^^int,\n+\t\t\t { .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 (^^int,\n+\t\t\t { .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 (^^int,\n+\t\t\t { .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 (^^int,\n+\t\t\t { .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 (^^int,\n+\t\t\t { .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 (^^int, { .name = \"a\", .annotations = { ^^:: } }));\n+static_assert (!valid_data_member_spec (^^int, { .name = \"a\", .annotations = { ^^foo } }));\n+static_assert (!valid_data_member_spec (^^int, { .name = \"a\", .annotations = { ^^arr } }));\n+static_assert (!valid_data_member_spec (^^int, { .name = \"a\", .annotations = { ^^arr } }));\n+static_assert (valid_data_member_spec (^^int, { .name = \"a\", .annotations = { ^^i } }));\n+static_assert (valid_data_member_spec (^^int, { .name = \"a\", .annotations = { ^^s } }));\n+static_assert (!valid_data_member_spec (^^int, { .bit_width = 0, .annotations = { ^^i } }));\n--- gcc/testsuite/g++.dg/reflect/data_member_spec6.C.jj\t2026-03-25 20:19:53.793938985 +0100\n+++ gcc/testsuite/g++.dg/reflect/data_member_spec6.C\t2026-03-25 20:36:46.230470634 +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 (^^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-25 20:19:10.716163144 +0100\n+++ gcc/testsuite/g++.dg/reflect/display_string_of1.C\t2026-03-25 20:38:11.399038570 +0100\n@@ -115,10 +115,11 @@ 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 (^^int, { .name = \"member\", .alignment = 128, .no_unique_address = true })) == \"(int, member, 128, , true)\");\n- static_assert (display_string_of (data_member_spec (^^const int, { .name = \"member\", .bit_width = 6 })) == \"(const int, member, , 6, false)\");\n- static_assert (display_string_of (data_member_spec (^^int, { .bit_width = 0 })) == \"(int, , , 0, false)\");\n- static_assert (display_string_of (data_member_spec (^^long, { .bit_width = 5 })) == \"(long int, , , 5, false)\");\n+ static_assert (display_string_of (data_member_spec (^^int, { .name = \"member\", .alignment = 128, .no_unique_address = true })) == \"(int, member, 128, , true, {})\");\n+ static_assert (display_string_of (data_member_spec (^^const int, { .name = \"member\", .bit_width = 6 })) == \"(const int, member, , 6, false, {})\");\n+ static_assert (display_string_of (data_member_spec (^^int, { .bit_width = 0 })) == \"(int, , , 0, false, {})\");\n+ static_assert (display_string_of (data_member_spec (^^long, { .bit_width = 5 })) == \"(long int, , , 5, false, {})\");\n+ static_assert (display_string_of (data_member_spec (^^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-25 20:19:10.719163094 +0100\n+++ gcc/testsuite/g++.dg/reflect/u8display_string_of1.C\t2026-03-25 20:39:33.691654866 +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 (^^int, { .name = \"member\", .alignment = 128, .no_unique_address = true })) == u8\"(int, member, 128, , true)\");\n- static_assert (u8display_string_of (data_member_spec (^^const int, { .name = \"member\", .bit_width = 6 })) == u8\"(const int, member, , 6, false)\");\n- static_assert (u8display_string_of (data_member_spec (^^int, { .bit_width = 0 })) == u8\"(int, , , 0, false)\");\n- static_assert (u8display_string_of (data_member_spec (^^long, { .bit_width = 5 })) == u8\"(long int, , , 5, false)\");\n+ static_assert (u8display_string_of (data_member_spec (^^int, { .name = \"member\", .alignment = 128, .no_unique_address = true })) == u8\"(int, member, 128, , true, {})\");\n+ static_assert (u8display_string_of (data_member_spec (^^const int, { .name = \"member\", .bit_width = 6 })) == u8\"(const int, member, , 6, false, {})\");\n+ static_assert (u8display_string_of (data_member_spec (^^int, { .bit_width = 0 })) == u8\"(int, , , 0, false, {})\");\n+ static_assert (u8display_string_of (data_member_spec (^^long, { .bit_width = 5 })) == u8\"(long int, , , 5, false, {})\");\n+ static_assert (u8display_string_of (data_member_spec (^^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 20:19:53.794445393 +0100\n+++ gcc/testsuite/g++.dg/reflect/define_aggregate9.C\t2026-03-25 20:37:16.232966156 +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 = { .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 (^^int, 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-25 20:19:14.911093136 +0100\n+++ gcc/testsuite/g++.dg/reflect/mangle1.C\t2026-03-25 20:58:44.185325865 +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,11 @@ baz (int x)\n bar <332, data_member_spec (^^unsigned short, { .name = \"b\", .bit_width = 5 })> (); // data member description\n bar <333, data_member_spec (^^long, { .bit_width = 3 })> (); // data member description\n bar <334, data_member_spec (^^int, { .bit_width = 0 })> (); // data member description\n+ bar <335, std::meta::data_member_spec (^^int,\n+\t\t\t\t\t { .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 +256,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": [] }