[{"id":3677378,"web_url":"http://patchwork.ozlabs.org/comment/3677378/","msgid":"<4606f782-5c22-4b34-bfd4-8b31c659bd1a@redhat.com>","list_archive_url":null,"date":"2026-04-14T19:47:02","subject":"Re: [PATCH] c++, libstdc++, v3: Implement LWG4483 - Multidimensional\n arrays are not supported by meta::reflect_constant_array and related\n functions","submitter":{"id":4337,"url":"http://patchwork.ozlabs.org/api/people/4337/","name":"Jason Merrill","email":"jason@redhat.com"},"content":"On 4/14/26 3:25 PM, Jakub Jelinek wrote:\n> On Tue, Apr 14, 2026 at 03:02:51PM -0400, Jason Merrill wrote:\n>>> +      unsigned int i;\n>>> +      tree val;\n>>> +      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val)\n>>> +\t{\n>>> +\t  CONSTRUCTOR_ELT (expr, i)->value\n>>> +\t    = adjust_array_elt (loc, ctx, TREE_TYPE (valuet), val, fun,\n>>> +\t\t\t\tnon_constant_p, jump_target);\n>>> +\t  if (*jump_target || *non_constant_p)\n>>> +\t    return NULL_TREE;\n>>> +\t}\n>>> +      return expr;\n>>> +    }\n>>> +  else if (INTEGRAL_TYPE_P (valuet))\n>>\n>> Why this special case instead of using convert_reflect_constant_arg for\n>> integers as well?\n> \n> As it was special cased in get_range_elts as well.  But guess it isn't\n> needed in this new function, the reason to use it in get_range_elts is that\n> it is really common in that case (e.g. always for reflect_constant_string),\n> while the multidimensional array case is already uncommon.\n> Removed.\n> \n>>> @@ -551,7 +593,23 @@ get_range_elts (location_t loc, const co\n>>>    \t    }\n>>>    \t  tree referencet = TYPE_MAIN_VARIANT (instr);\n>>>    \t  TREE_VEC_ELT (args, 0) = referencet;\n>>> -\t  if (!is_xible (INIT_EXPR, valuet, args))\n>>> +\t  if (valuete != valuet)\n>>> +\t    {\n>>> +\t      tree rt = referencet;\n>>> +\t      if (TYPE_REF_P (rt))\n>>> +\t\trt = TREE_TYPE (rt);\n>>> +\t      if (!same_type_ignoring_top_level_qualifiers_p (valuet, rt))\n>>\n>> You could use non_reference (referencet) here.\n> \n> Adjusted.\n> \n> Tested with reflect/* so far, ok for trunk if it passes full\n> bootstrap/regtest?\n\nOK.\n\n> 2026-04-14  Jakub Jelinek  <jakub@redhat.com>\n> \n> \t* reflect.cc (adjust_array_elt): New function.\n> \t(get_range_elts): Implement LWG4483 - Multidimensional arrays are not\n> \tsupported by meta::reflect_constant_array and related functions.\n> \tHandle ARRAY_TYPE valuet.  Don't unshare_expr in the class valuet case,\n> \tget_template_param_object will unshare.\n> \n> \t* g++.dg/reflect/reflect_constant_array9.C: New test.\n> \t* g++.dg/reflect/reflect_constant_array10.C: New test.\n> \t* g++.dg/reflect/reflect_constant_array11.C: New test.\n> \t* g++.dg/reflect/define_static_array6.C: New test.\n> \t* g++.dg/reflect/define_static_object2.C: Uncomment older tests and\n> \tfix them, add tests for unions.\n> \n> \t* include/std/meta (define_static_object): Adjust for LWG4483 changes\n> \t- handle unions and arrays differently.\n> \n> --- gcc/cp/reflect.cc.jj\t2026-04-10 08:45:20.716811803 +0200\n> +++ gcc/cp/reflect.cc\t2026-04-14 21:18:45.776260126 +0200\n> @@ -394,6 +394,40 @@ replace_parm_r (tree *tp, int *walk_subt\n>   static tree throw_exception (location_t, const constexpr_ctx *, const char *,\n>   \t\t\t     tree, bool *, tree *);\n>   \n> +/* Helper function for get_range_elts, handle adjustment of ARRAY_TYPE elts\n> +   of a retvec.  */\n> +\n> +static tree\n> +adjust_array_elt (location_t loc, const constexpr_ctx *ctx, tree valuet,\n> +\t\t  tree expr, tree fun, bool *non_constant_p, tree *jump_target)\n> +{\n> +  if (TREE_CODE (valuet) == ARRAY_TYPE)\n> +    {\n> +      if (TREE_CODE (expr) != CONSTRUCTOR\n> +\t  || TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)\n> +\treturn throw_exception (loc, ctx, \"reflect_constant_array failed\",\n> +\t\t\t\tfun, non_constant_p, jump_target);\n> +      unsigned int i;\n> +      tree val;\n> +      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val)\n> +\t{\n> +\t  CONSTRUCTOR_ELT (expr, i)->value\n> +\t    = adjust_array_elt (loc, ctx, TREE_TYPE (valuet), val, fun,\n> +\t\t\t\tnon_constant_p, jump_target);\n> +\t  if (*jump_target || *non_constant_p)\n> +\t    return NULL_TREE;\n> +\t}\n> +      return expr;\n> +    }\n> +  expr = convert_reflect_constant_arg (valuet, expr);\n> +  if (expr == error_mark_node)\n> +    return throw_exception (loc, ctx, \"reflect_constant failed\",\n> +\t\t\t    fun, non_constant_p, jump_target);\n> +  if (VAR_P (expr))\n> +    expr = DECL_INITIAL (expr);\n> +  return expr;\n> +}\n> +\n>   /* Kinds for get_range_elts.  */\n>   \n>   enum get_range_elts_kind {\n> @@ -513,23 +547,24 @@ get_range_elts (location_t loc, const co\n>   \t}\n>         if (kind == REFLECT_CONSTANT_ARRAY)\n>   \t{\n> -\t  if (!structural_type_p (valuet))\n> +\t  tree valuete = strip_array_types (valuet);\n> +\t  if (!structural_type_p (valuete))\n>   \t    {\n>   \t      if (!cxx_constexpr_quiet_p (ctx))\n>   \t\t{\n>   \t\t  auto_diagnostic_group d;\n>   \t\t  error_at (loc, \"%<reflect_constant_array%> argument with \"\n>   \t\t\t\t \"%qT which is not a structural type\", inst);\n> -\t\t  structural_type_p (valuet, true);\n> +\t\t  structural_type_p (valuete, true);\n>   \t\t}\n>   \t      *non_constant_p = true;\n>   \t      return NULL_TREE;\n>   \t    }\n>   \t  TREE_VEC_ELT (args, 0)\n> -\t    = build_stub_type (valuet,\n> -\t\t\t       cp_type_quals (valuet) | TYPE_QUAL_CONST,\n> +\t    = build_stub_type (valuete,\n> +\t\t\t       cp_type_quals (valuete) | TYPE_QUAL_CONST,\n>   \t\t\t       false);\n> -\t  if (!is_xible (INIT_EXPR, valuet, args))\n> +\t  if (!is_xible (INIT_EXPR, valuete, args))\n>   \t    {\n>   \t      if (!cxx_constexpr_quiet_p (ctx))\n>   \t\terror_at (loc, \"%<reflect_constant_array%> argument with %qT \"\n> @@ -551,7 +586,21 @@ get_range_elts (location_t loc, const co\n>   \t    }\n>   \t  tree referencet = TYPE_MAIN_VARIANT (instr);\n>   \t  TREE_VEC_ELT (args, 0) = referencet;\n> -\t  if (!is_xible (INIT_EXPR, valuet, args))\n> +\t  if (valuete != valuet)\n> +\t    {\n> +\t      tree rt = non_reference (referencet);\n> +\t      if (!same_type_ignoring_top_level_qualifiers_p (valuet, rt))\n> +\t\t{\n> +\t\t  if (!cxx_constexpr_quiet_p (ctx))\n> +\t\t    error_at (loc, \"%<reflect_constant_array%> argument with \"\n> +\t\t\t\t   \"%qT which is not compatible with %qT \"\n> +\t\t\t\t   \"%<std::ranges::range_reference_t%>\",\n> +\t\t\t      inst, referencet);\n> +\t\t  *non_constant_p = true;\n> +\t\t  return NULL_TREE;\n> +\t\t}\n> +\t    }\n> +\t  else if (!is_xible (INIT_EXPR, valuet, args))\n>   \t    {\n>   \t      if (!cxx_constexpr_quiet_p (ctx))\n>   \t\terror_at (loc, \"%<reflect_constant_array%> argument with %qT \"\n> @@ -595,12 +644,22 @@ get_range_elts (location_t loc, const co\n>   \telse\n>   \t  {\n>   \t    gcc_assert (kind == REFLECT_CONSTANT_ARRAY);\n> +\t    if (TREE_CODE (valuet) == ARRAY_TYPE)\n> +\t      {\n> +\t\tretvec[i]\n> +\t\t  = adjust_array_elt (loc, ctx, valuet,\n> +\t\t\t\t      unshare_expr (retvec[i]), fun,\n> +\t\t\t\t      non_constant_p, jump_target);\n> +\t\tif (*jump_target || *non_constant_p)\n> +\t\t  return NULL_TREE;\n> +\t\tcontinue;\n> +\t      }\n>   \t    tree expr = convert_reflect_constant_arg (valuet, retvec[i]);\n>   \t    if (expr == error_mark_node)\n>   \t      return throw_exception (loc, ctx, \"reflect_constant failed\",\n>   \t\t\t\t      fun, non_constant_p, jump_target);\n>   \t    if (VAR_P (expr))\n> -\t      expr = unshare_expr (DECL_INITIAL (expr));\n> +\t      expr = DECL_INITIAL (expr);\n>   \t    retvec[i] = expr;\n>   \t  }\n>         }\n> --- gcc/testsuite/g++.dg/reflect/reflect_constant_array9.C.jj\t2026-04-10 14:58:28.892432782 +0200\n> +++ gcc/testsuite/g++.dg/reflect/reflect_constant_array9.C\t2026-04-10 15:46:45.523823103 +0200\n> @@ -0,0 +1,28 @@\n> +// LWG4483 - Multidimensional arrays are not supported by\n> +// meta::reflect_constant_array and related functions.\n> +// { dg-do compile { target c++26 } }\n> +// { dg-additional-options \"-freflection\" }\n> +\n> +#include <meta>\n> +\n> +consteval auto\n> +foo ()\n> +{\n> +  int a[3][3][3];\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\ta[i][j][k] = i + j + k;\n> +  return std::meta::reflect_constant_array (a);\n> +}\n> +\n> +static_assert (foo () == foo ());\n> +static_assert (type_of (foo ()) == ^^const int [3][3][3]);\n> +constexpr auto &m = [: foo () :];\n> +consteval {\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\tif (m[i][j][k] != i + j + k)\n> +\t  throw 1;\n> +}\n> --- gcc/testsuite/g++.dg/reflect/reflect_constant_array10.C.jj\t2026-04-10 16:43:43.192287885 +0200\n> +++ gcc/testsuite/g++.dg/reflect/reflect_constant_array10.C\t2026-04-10 17:39:16.165672372 +0200\n> @@ -0,0 +1,57 @@\n> +// LWG4483 - Multidimensional arrays are not supported by\n> +// meta::reflect_constant_array and related functions.\n> +// { dg-do compile { target c++26 } }\n> +// { dg-additional-options \"-freflection\" }\n> +\n> +#include <ranges>\n> +#include <meta>\n> +\n> +consteval auto\n> +foo ()\n> +{\n> +  int a[3][3][3];\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\ta[i][j][k] = i + 3 * j + 9 * k;\n> +  std::span <int[3][3]> b = a;\n> +  return std::meta::reflect_constant_array (b);\n> +}\n> +\n> +static_assert (foo () == foo ());\n> +static_assert (type_of (foo ()) == ^^const int [3][3][3]);\n> +constexpr auto &m = [: foo () :];\n> +static_assert (foo () == std::meta::reflect_constant_array (m));\n> +static_assert (foo () == std::meta::reflect_constant_array (std::span <const int[3][3]> (m)));\n> +consteval {\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\tif (m[i][j][k] != i + 3 * j + 9 * k)\n> +\t  throw 1;\n> +}\n> +\n> +consteval auto\n> +bar ()\n> +{\n> +  int a[3][3][3];\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\ta[i][j][k] = i + 3 * j + 9 * k;\n> +  std::span <int[3][3]> b = a;\n> +  return std::meta::reflect_constant_array (b | std::views::reverse);\n> +}\n> +\n> +static_assert (bar () == bar ());\n> +static_assert (type_of (bar ()) == ^^const int [3][3][3]);\n> +constexpr auto &n = [: bar () :];\n> +static_assert (bar () == std::meta::reflect_constant_array (n));\n> +static_assert (bar () == std::meta::reflect_constant_array (std::span <const int[3][3]> (n)));\n> +consteval {\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\tif (n[i][j][k] != (2 - i) + 3 * j + 9 * k)\n> +\t  throw 1;\n> +}\n> --- gcc/testsuite/g++.dg/reflect/reflect_constant_array11.C.jj\t2026-04-10 17:00:44.179663685 +0200\n> +++ gcc/testsuite/g++.dg/reflect/reflect_constant_array11.C\t2026-04-10 17:05:50.683365136 +0200\n> @@ -0,0 +1,18 @@\n> +// { dg-do compile { target c++26 } }\n> +// { dg-additional-options \"-freflection\" }\n> +// Test std::meta::reflect_constant_string.\n> +\n> +#include <meta>\n> +#include <ranges>\n> +#include <span>\n> +\n> +using namespace std::meta;\n> +\n> +struct A { int a, b; mutable int c; };\n> +constexpr A aa[2] = { { 1, 2, 3 }, { 4, 5, 6 } };\n> +constexpr auto a = reflect_constant_array (aa);\n> +// { dg-error \"'reflect_constant_array' argument with 'std::ranges::range_value_t<const A \\\\\\[2\\\\\\]>' \\\\\\{aka 'A'\\\\\\} which is not a structural type\" \"\" { target *-*-* } .-1 }\n> +struct B { constexpr B (int x, int y) : a (x), b (y) {} constexpr ~B () {} B (const B &) = delete; int a, b; };\n> +constexpr B b[2][2] = { { { 1, 2 }, { 2, 3 } }, { { 3, 4 }, { 4, 5 } } };\n> +constexpr auto c = reflect_constant_array (b);\n> +// { dg-error \"'reflect_constant_array' argument with 'std::ranges::range_value_t<const B \\\\\\[2\\\\\\]\\\\\\[2\\\\\\]>' \\\\\\{aka 'B \\\\\\[2\\\\\\]'\\\\\\} which is not copy constructible\" \"\" { target *-*-* } .-1 }\n> --- gcc/testsuite/g++.dg/reflect/define_static_array6.C.jj\t2026-04-10 15:44:52.229788936 +0200\n> +++ gcc/testsuite/g++.dg/reflect/define_static_array6.C\t2026-04-10 15:52:38.099857297 +0200\n> @@ -0,0 +1,27 @@\n> +// LWG4483 - Multidimensional arrays are not supported by\n> +// meta::reflect_constant_array and related functions.\n> +// { dg-do compile { target c++26 } }\n> +// { dg-additional-options \"-freflection\" }\n> +\n> +#include <meta>\n> +\n> +consteval auto\n> +foo ()\n> +{\n> +  int a[3][3][3];\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\ta[i][j][k] = i + j + k;\n> +  return std::define_static_array (a);\n> +}\n> +\n> +static_assert (foo ().size () == 3);\n> +constexpr auto *m = foo ().data ();\n> +consteval {\n> +  for (int i = 0; i < 3; ++i)\n> +    for (int j = 0; j < 3; ++j)\n> +      for (int k = 0; k < 3; ++k)\n> +\tif (m[i][j][k] != i + j + k)\n> +\t  throw 1;\n> +}\n> --- gcc/testsuite/g++.dg/reflect/define_static_object2.C.jj\t2026-03-27 10:17:16.120298331 +0100\n> +++ gcc/testsuite/g++.dg/reflect/define_static_object2.C\t2026-04-10 16:09:20.261858550 +0200\n> @@ -1,3 +1,5 @@\n> +// LWG4483 - Multidimensional arrays are not supported by\n> +// meta::reflect_constant_array and related functions.\n>   // { dg-do compile { target c++26 } }\n>   // { dg-additional-options \"-freflection\" }\n>   // Test std::define_static_object.\n> @@ -5,14 +7,19 @@\n>   #include <meta>\n>   \n>   constexpr int arr[]{1, 2, 3};\n> -// LWG4483 use extract(reflect_constant_array())\n> -// constexpr const int(*ptr)[3] = std::define_static_object(arr);\n> -// static_assert( *ptr == std::define_static_array(arr).data() );\n> -// static_assert( ptr = &std::meta::constant_of(arr) );\n> +constexpr const int (*ptr)[3] = std::define_static_object (arr);\n> +static_assert (*ptr == std::define_static_array (arr).data ());\n> +static_assert (ptr == &[: std::meta::constant_of (^^arr) :]);\n>   \n>   constexpr int marr[3][3]{1, 2, 3};\n> -// LWG4483 array are not structural so this fail\n> -// constexpr const int(*mptr)[3][3] = std::define_static_object(marr);\n> -// static_assert( *mptr == std::define_static_array(marr).data() );\n> -// static_assert( mptr = &std::meta::constant_of(marr) );\n> +constexpr const int (*mptr)[3][3] = std::define_static_object (marr);\n> +static_assert (*mptr == std::define_static_array (marr).data ());\n> +static_assert (mptr == &[: std::meta::constant_of (^^marr) :]);\n>   \n> +union U { int a; long long b; };\n> +constexpr U u = { .a = 42 };\n> +constexpr const U *up = std::define_static_object (u);\n> +static_assert (up->a == 42);\n> +constexpr U v = { .b = 43LL };\n> +constexpr const U *vp = std::define_static_object (v);\n> +static_assert (vp->b == 43LL);\n> --- libstdc++-v3/include/std/meta.jj\t2026-04-08 07:49:13.477647992 +0200\n> +++ libstdc++-v3/include/std/meta\t2026-04-10 15:57:25.423013150 +0200\n> @@ -682,11 +682,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>       define_static_object(_Tp&& __t)\n>       {\n>         using _Up = remove_cvref_t<_Tp>;\n> -      if constexpr (meta::is_class_type(^^_Up))\n> +      if constexpr (meta::is_class_type(^^_Up) || meta::is_union_type(^^_Up))\n>   \t{\n>   \t  auto __cst = meta::reflect_constant(std::forward<_Tp>(__t));\n>   \t  return std::addressof(meta::extract<const _Up&>(__cst));\n>   \t}\n> +      else if constexpr (meta::is_array_type(^^_Up))\n> +\t{\n> +\t  auto __cst = meta::reflect_constant_array(std::forward<_Tp>(__t));\n> +\t  return std::addressof(meta::extract<const _Up&>(__cst));\n> +\t}\n>         else\n>   \treturn std::define_static_array(span(std::addressof(__t), 1)).data();\n>       }\n> \n> \n> \tJakub\n>","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=XC8Wd3uP;\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=XC8Wd3uP","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 [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 4fwFDb1fgGz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 05:47:41 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id CB7B04BA2E32\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 19:47:39 +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 373C24BA2E08\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 19:47:08 +0000 (GMT)","from mail-qv1-f70.google.com (mail-qv1-f70.google.com\n [209.85.219.70]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-167-TjK7eWt1NuS7MmfnVs4Qgw-1; Tue, 14 Apr 2026 15:47:06 -0400","by mail-qv1-f70.google.com with SMTP id\n 6a1803df08f44-8a1accb970fso159846206d6.3\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 12:47:06 -0700 (PDT)","from [192.168.50.130]\n (130-44-146-247.s12789.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com.\n [130.44.146.247]) by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-8ac84c7be06sm134109466d6.33.2026.04.14.12.47.02\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Tue, 14 Apr 2026 12:47:03 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org CB7B04BA2E32","OpenDKIM Filter v2.11.0 sourceware.org 373C24BA2E08"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 373C24BA2E08","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 373C24BA2E08","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776196028; cv=none;\n b=AzhNVeddwmWmXxcfuwvdQIbv06Pkq4wRLbka+x91P4VhpmtCud3ZXVPuM5yEbQXmz8CMUCbYO7sTwsXtcj8L6CAVz+OgX9lfBfVJIZTEmTI0IyH3ZmkBakew7NEt/Rl3wzPMWG2LXaMTtk6LBfeDhCR8IWWUBbawFzrIc/znhb4=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776196028; c=relaxed/simple;\n bh=Nwl+LGUJDIVnT9QLM28xrjQrwSlQUEmFlXp/O9EK40w=;\n h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From;\n b=LZ8+tqfNx20FDiifdECoBUaMQgulInhY7a0G6QnnCW8avolVlVfaSnx2nv5oMafXdzvryKlNrrHA+QAGcluCoX1Hw2elotPkNL+JI5kvkVfVQs7tGH+gJ3EOAoFwiZL0RrY3Cigvx1b4uAff5Wj3CabA41D8mV7+IQPbjW/mF2Q=","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=1776196027;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=7tDH3MKBXQnCQArhXLM+ZPIpo9FaSVXrcgmBi+mG4kQ=;\n b=XC8Wd3uP38gpvDZVpChIQSKZsgmLl1CYrDG5J5CNREysDXwwoIdyLJ3MzAv8/C7+JnmB86\n +zd0gelfd+MN5rO7RlsQiaYPAdbdkwbqbHKx5b+SGUGtuqhit7cepPWP1K1DAcjdxIdj7o\n 7sAoJj2CuNeVQ1qK+0jRyxtJKOh3SOg=","X-MC-Unique":"TjK7eWt1NuS7MmfnVs4Qgw-1","X-Mimecast-MFC-AGG-ID":"TjK7eWt1NuS7MmfnVs4Qgw_1776196025","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776196025; x=1776800825;\n h=content-transfer-encoding:in-reply-to:from:content-language\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=7tDH3MKBXQnCQArhXLM+ZPIpo9FaSVXrcgmBi+mG4kQ=;\n b=ppBUCfUL1Gk76kr6gE1hpradJxcgg0EPXUrRapHpShNgJixePt4pSdkoNRlgeB8NXp\n 7uMgEgohvI+InaegMSSjS+rlAGEgMHEZNYFDVoFHf+dKlDqd/CPYYppMYSPPXdSeXMBc\n bABqbYQJ6Eo/QrCHMucSwndn7sur4IxFSc5SnE2nJoQojEcENc8d5epnEJMllvSsgq8b\n ixxR39nU9d2OzZSg4HwwamdQVq2vWZXCSjfPNsjqPwhYcPD26Gmt9YCGWUg3jfzHpj8C\n mFdviVRIuTDb/XQ69TSm6RqzlZsBjF3mNHCpKZjf3+uK7Plv0PoBAWkuYh07z06KUO9b\n KRIg==","X-Forwarded-Encrypted":"i=1;\n AFNElJ9X3kT0fQuyHdAkrgHBrfovPqeDyWItE0Z5BKzKyR3Zhpn/67Ga40dhSviJrvIK000yjzuTPgqH14SZrw==@gcc.gnu.org","X-Gm-Message-State":"AOJu0YzEmZpIUpWm3blur8WzoejhgVIxlP+Ql68eNuyAkAMl6GlPaSIn\n GurvIsgauEbC80e5v5jfOPnaZoCtBq3WVs25Fl7L2l+vGdd7eTBAXqxeh/Gwb2dbfuDU5Cx4nRs\n HzV49lo33Y6Ccw8p0gHy4ND1WIbZVjp5QXlM/IZoqf6petW+KHA3+uD9ldH4=","X-Gm-Gg":"AeBDietWz2joWJxlyEgiuEj34YPaKZDOm2omRDxsO9RpHCTVpHK5cTeuwLyBp4/ozON\n hGhm/b2fN/uzASDJVaqQW7ytA3YEFepGFR79UGlQSvpuyCEnahuDkNNWWYsXMC4n0rtyJnqfHys\n 51pM5Acl0hVLXARVFYde19VpW1wZHvqyoJU2qeMmJSLk/VvhNjbXMDJ9k+Tt3nCh8TTZedabLkp\n aywrR5hw1AgbTiDhlRIZKVIUCyYB8w8uF9LFXiBnhNqYgnrKza02aQbmfxZf/0G4NJCVUZYGxm2\n gjvQwo/C52YRWykpDRG7q2Hd/85EJQ5OAX7TwG21T8b4f35ZQMn2JBo6/+PEjziDldb78vpd7SY\n Mm8FfqiXzZK+ijp89oAETYPgGA7J4XDiCUxVKrVokhVbYZLN+3RUydfUPkIAmzvAeokULfYNvaz\n NZ9ltlB3vosj9Cy3srAnykStSlEnywpicql0+AEzjcmw==","X-Received":["by 2002:a05:6214:5985:b0:8ac:a553:529d with SMTP id\n 6a1803df08f44-8aca553569amr163327536d6.23.1776196025194;\n Tue, 14 Apr 2026 12:47:05 -0700 (PDT)","by 2002:a05:6214:5985:b0:8ac:a553:529d with SMTP id\n 6a1803df08f44-8aca553569amr163326826d6.23.1776196024543;\n Tue, 14 Apr 2026 12:47:04 -0700 (PDT)"],"Message-ID":"<4606f782-5c22-4b34-bfd4-8b31c659bd1a@redhat.com>","Date":"Tue, 14 Apr 2026 15:47:02 -0400","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] c++, libstdc++, v3: Implement LWG4483 - Multidimensional\n arrays are not supported by meta::reflect_constant_array and related\n functions","To":"Jakub Jelinek <jakub@redhat.com>","Cc":"Marek Polacek <polacek@redhat.com>, Jonathan Wakely <jwakely@redhat.com>,\n Tomasz Kaminski <tkaminsk@redhat.com>, gcc-patches@gcc.gnu.org,\n libstdc++@gcc.gnu.org","References":"<adkUGggIiITbC-cp@tucnak>\n <CAKvuMXBJMd=813ixZmS-_+MuP8_EJf8SrtnbvEfueM2spptYZA@mail.gmail.com>\n <adkbHhg3-pyumdxH@tucnak> <1ab72c7c-be1a-4539-9fb5-b0d11071752b@redhat.com>\n <ad6UuwEDu1j6WhdA@tucnak>","From":"Jason Merrill <jason@redhat.com>","In-Reply-To":"<ad6UuwEDu1j6WhdA@tucnak>","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"FFgJPQmUUWnWQOnBCkpZMkwnbkhmaB8Xxwj7SDQwVAg_1776196025","X-Mimecast-Originator":"redhat.com","Content-Language":"en-US","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","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>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}},{"id":3677427,"web_url":"http://patchwork.ozlabs.org/comment/3677427/","msgid":"<CAH6eHdS5oQ8tE_wCKF3JDxWjciHiouQTef=iLOM7RdkuN6cjEA@mail.gmail.com>","list_archive_url":null,"date":"2026-04-14T23:16:34","subject":"Re: [PATCH] c++, libstdc++, v3: Implement LWG4483 - Multidimensional\n arrays are not supported by meta::reflect_constant_array and related\n functions","submitter":{"id":4329,"url":"http://patchwork.ozlabs.org/api/people/4329/","name":"Jonathan Wakely","email":"jwakely.gcc@gmail.com"},"content":"Library parts are ok too\n\nOn Tue, 14 Apr 2026, 20:47 Jason Merrill, <jason@redhat.com> wrote:\n\n> On 4/14/26 3:25 PM, Jakub Jelinek wrote:\n> > On Tue, Apr 14, 2026 at 03:02:51PM -0400, Jason Merrill wrote:\n> >>> +      unsigned int i;\n> >>> +      tree val;\n> >>> +      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val)\n> >>> +   {\n> >>> +     CONSTRUCTOR_ELT (expr, i)->value\n> >>> +       = adjust_array_elt (loc, ctx, TREE_TYPE (valuet), val, fun,\n> >>> +                           non_constant_p, jump_target);\n> >>> +     if (*jump_target || *non_constant_p)\n> >>> +       return NULL_TREE;\n> >>> +   }\n> >>> +      return expr;\n> >>> +    }\n> >>> +  else if (INTEGRAL_TYPE_P (valuet))\n> >>\n> >> Why this special case instead of using convert_reflect_constant_arg for\n> >> integers as well?\n> >\n> > As it was special cased in get_range_elts as well.  But guess it isn't\n> > needed in this new function, the reason to use it in get_range_elts is\n> that\n> > it is really common in that case (e.g. always for\n> reflect_constant_string),\n> > while the multidimensional array case is already uncommon.\n> > Removed.\n> >\n> >>> @@ -551,7 +593,23 @@ get_range_elts (location_t loc, const co\n> >>>         }\n> >>>       tree referencet = TYPE_MAIN_VARIANT (instr);\n> >>>       TREE_VEC_ELT (args, 0) = referencet;\n> >>> -     if (!is_xible (INIT_EXPR, valuet, args))\n> >>> +     if (valuete != valuet)\n> >>> +       {\n> >>> +         tree rt = referencet;\n> >>> +         if (TYPE_REF_P (rt))\n> >>> +           rt = TREE_TYPE (rt);\n> >>> +         if (!same_type_ignoring_top_level_qualifiers_p (valuet, rt))\n> >>\n> >> You could use non_reference (referencet) here.\n> >\n> > Adjusted.\n> >\n> > Tested with reflect/* so far, ok for trunk if it passes full\n> > bootstrap/regtest?\n>\n> OK.\n>\n> > 2026-04-14  Jakub Jelinek  <jakub@redhat.com>\n> >\n> >       * reflect.cc (adjust_array_elt): New function.\n> >       (get_range_elts): Implement LWG4483 - Multidimensional arrays are\n> not\n> >       supported by meta::reflect_constant_array and related functions.\n> >       Handle ARRAY_TYPE valuet.  Don't unshare_expr in the class valuet\n> case,\n> >       get_template_param_object will unshare.\n> >\n> >       * g++.dg/reflect/reflect_constant_array9.C: New test.\n> >       * g++.dg/reflect/reflect_constant_array10.C: New test.\n> >       * g++.dg/reflect/reflect_constant_array11.C: New test.\n> >       * g++.dg/reflect/define_static_array6.C: New test.\n> >       * g++.dg/reflect/define_static_object2.C: Uncomment older tests and\n> >       fix them, add tests for unions.\n> >\n> >       * include/std/meta (define_static_object): Adjust for LWG4483\n> changes\n> >       - handle unions and arrays differently.\n> >\n> > --- gcc/cp/reflect.cc.jj      2026-04-10 08:45:20.716811803 +0200\n> > +++ gcc/cp/reflect.cc 2026-04-14 21:18:45.776260126 +0200\n> > @@ -394,6 +394,40 @@ replace_parm_r (tree *tp, int *walk_subt\n> >   static tree throw_exception (location_t, const constexpr_ctx *, const\n> char *,\n> >                            tree, bool *, tree *);\n> >\n> > +/* Helper function for get_range_elts, handle adjustment of ARRAY_TYPE\n> elts\n> > +   of a retvec.  */\n> > +\n> > +static tree\n> > +adjust_array_elt (location_t loc, const constexpr_ctx *ctx, tree valuet,\n> > +               tree expr, tree fun, bool *non_constant_p, tree\n> *jump_target)\n> > +{\n> > +  if (TREE_CODE (valuet) == ARRAY_TYPE)\n> > +    {\n> > +      if (TREE_CODE (expr) != CONSTRUCTOR\n> > +       || TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)\n> > +     return throw_exception (loc, ctx, \"reflect_constant_array failed\",\n> > +                             fun, non_constant_p, jump_target);\n> > +      unsigned int i;\n> > +      tree val;\n> > +      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val)\n> > +     {\n> > +       CONSTRUCTOR_ELT (expr, i)->value\n> > +         = adjust_array_elt (loc, ctx, TREE_TYPE (valuet), val, fun,\n> > +                             non_constant_p, jump_target);\n> > +       if (*jump_target || *non_constant_p)\n> > +         return NULL_TREE;\n> > +     }\n> > +      return expr;\n> > +    }\n> > +  expr = convert_reflect_constant_arg (valuet, expr);\n> > +  if (expr == error_mark_node)\n> > +    return throw_exception (loc, ctx, \"reflect_constant failed\",\n> > +                         fun, non_constant_p, jump_target);\n> > +  if (VAR_P (expr))\n> > +    expr = DECL_INITIAL (expr);\n> > +  return expr;\n> > +}\n> > +\n> >   /* Kinds for get_range_elts.  */\n> >\n> >   enum get_range_elts_kind {\n> > @@ -513,23 +547,24 @@ get_range_elts (location_t loc, const co\n> >       }\n> >         if (kind == REFLECT_CONSTANT_ARRAY)\n> >       {\n> > -       if (!structural_type_p (valuet))\n> > +       tree valuete = strip_array_types (valuet);\n> > +       if (!structural_type_p (valuete))\n> >           {\n> >             if (!cxx_constexpr_quiet_p (ctx))\n> >               {\n> >                 auto_diagnostic_group d;\n> >                 error_at (loc, \"%<reflect_constant_array%> argument with\n> \"\n> >                                \"%qT which is not a structural type\",\n> inst);\n> > -               structural_type_p (valuet, true);\n> > +               structural_type_p (valuete, true);\n> >               }\n> >             *non_constant_p = true;\n> >             return NULL_TREE;\n> >           }\n> >         TREE_VEC_ELT (args, 0)\n> > -         = build_stub_type (valuet,\n> > -                            cp_type_quals (valuet) | TYPE_QUAL_CONST,\n> > +         = build_stub_type (valuete,\n> > +                            cp_type_quals (valuete) | TYPE_QUAL_CONST,\n> >                              false);\n> > -       if (!is_xible (INIT_EXPR, valuet, args))\n> > +       if (!is_xible (INIT_EXPR, valuete, args))\n> >           {\n> >             if (!cxx_constexpr_quiet_p (ctx))\n> >               error_at (loc, \"%<reflect_constant_array%> argument with\n> %qT \"\n> > @@ -551,7 +586,21 @@ get_range_elts (location_t loc, const co\n> >           }\n> >         tree referencet = TYPE_MAIN_VARIANT (instr);\n> >         TREE_VEC_ELT (args, 0) = referencet;\n> > -       if (!is_xible (INIT_EXPR, valuet, args))\n> > +       if (valuete != valuet)\n> > +         {\n> > +           tree rt = non_reference (referencet);\n> > +           if (!same_type_ignoring_top_level_qualifiers_p (valuet, rt))\n> > +             {\n> > +               if (!cxx_constexpr_quiet_p (ctx))\n> > +                 error_at (loc, \"%<reflect_constant_array%> argument\n> with \"\n> > +                                \"%qT which is not compatible with %qT \"\n> > +                                \"%<std::ranges::range_reference_t%>\",\n> > +                           inst, referencet);\n> > +               *non_constant_p = true;\n> > +               return NULL_TREE;\n> > +             }\n> > +         }\n> > +       else if (!is_xible (INIT_EXPR, valuet, args))\n> >           {\n> >             if (!cxx_constexpr_quiet_p (ctx))\n> >               error_at (loc, \"%<reflect_constant_array%> argument with\n> %qT \"\n> > @@ -595,12 +644,22 @@ get_range_elts (location_t loc, const co\n> >       else\n> >         {\n> >           gcc_assert (kind == REFLECT_CONSTANT_ARRAY);\n> > +         if (TREE_CODE (valuet) == ARRAY_TYPE)\n> > +           {\n> > +             retvec[i]\n> > +               = adjust_array_elt (loc, ctx, valuet,\n> > +                                   unshare_expr (retvec[i]), fun,\n> > +                                   non_constant_p, jump_target);\n> > +             if (*jump_target || *non_constant_p)\n> > +               return NULL_TREE;\n> > +             continue;\n> > +           }\n> >           tree expr = convert_reflect_constant_arg (valuet, retvec[i]);\n> >           if (expr == error_mark_node)\n> >             return throw_exception (loc, ctx, \"reflect_constant failed\",\n> >                                     fun, non_constant_p, jump_target);\n> >           if (VAR_P (expr))\n> > -           expr = unshare_expr (DECL_INITIAL (expr));\n> > +           expr = DECL_INITIAL (expr);\n> >           retvec[i] = expr;\n> >         }\n> >         }\n> > --- gcc/testsuite/g++.dg/reflect/reflect_constant_array9.C.jj 2026-04-10\n> 14:58:28.892432782 +0200\n> > +++ gcc/testsuite/g++.dg/reflect/reflect_constant_array9.C    2026-04-10\n> 15:46:45.523823103 +0200\n> > @@ -0,0 +1,28 @@\n> > +// LWG4483 - Multidimensional arrays are not supported by\n> > +// meta::reflect_constant_array and related functions.\n> > +// { dg-do compile { target c++26 } }\n> > +// { dg-additional-options \"-freflection\" }\n> > +\n> > +#include <meta>\n> > +\n> > +consteval auto\n> > +foo ()\n> > +{\n> > +  int a[3][3][3];\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     a[i][j][k] = i + j + k;\n> > +  return std::meta::reflect_constant_array (a);\n> > +}\n> > +\n> > +static_assert (foo () == foo ());\n> > +static_assert (type_of (foo ()) == ^^const int [3][3][3]);\n> > +constexpr auto &m = [: foo () :];\n> > +consteval {\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     if (m[i][j][k] != i + j + k)\n> > +       throw 1;\n> > +}\n> > --- gcc/testsuite/g++.dg/reflect/reflect_constant_array10.C.jj\n> 2026-04-10 16:43:43.192287885 +0200\n> > +++ gcc/testsuite/g++.dg/reflect/reflect_constant_array10.C   2026-04-10\n> 17:39:16.165672372 +0200\n> > @@ -0,0 +1,57 @@\n> > +// LWG4483 - Multidimensional arrays are not supported by\n> > +// meta::reflect_constant_array and related functions.\n> > +// { dg-do compile { target c++26 } }\n> > +// { dg-additional-options \"-freflection\" }\n> > +\n> > +#include <ranges>\n> > +#include <meta>\n> > +\n> > +consteval auto\n> > +foo ()\n> > +{\n> > +  int a[3][3][3];\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     a[i][j][k] = i + 3 * j + 9 * k;\n> > +  std::span <int[3][3]> b = a;\n> > +  return std::meta::reflect_constant_array (b);\n> > +}\n> > +\n> > +static_assert (foo () == foo ());\n> > +static_assert (type_of (foo ()) == ^^const int [3][3][3]);\n> > +constexpr auto &m = [: foo () :];\n> > +static_assert (foo () == std::meta::reflect_constant_array (m));\n> > +static_assert (foo () == std::meta::reflect_constant_array (std::span\n> <const int[3][3]> (m)));\n> > +consteval {\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     if (m[i][j][k] != i + 3 * j + 9 * k)\n> > +       throw 1;\n> > +}\n> > +\n> > +consteval auto\n> > +bar ()\n> > +{\n> > +  int a[3][3][3];\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     a[i][j][k] = i + 3 * j + 9 * k;\n> > +  std::span <int[3][3]> b = a;\n> > +  return std::meta::reflect_constant_array (b | std::views::reverse);\n> > +}\n> > +\n> > +static_assert (bar () == bar ());\n> > +static_assert (type_of (bar ()) == ^^const int [3][3][3]);\n> > +constexpr auto &n = [: bar () :];\n> > +static_assert (bar () == std::meta::reflect_constant_array (n));\n> > +static_assert (bar () == std::meta::reflect_constant_array (std::span\n> <const int[3][3]> (n)));\n> > +consteval {\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     if (n[i][j][k] != (2 - i) + 3 * j + 9 * k)\n> > +       throw 1;\n> > +}\n> > --- gcc/testsuite/g++.dg/reflect/reflect_constant_array11.C.jj\n> 2026-04-10 17:00:44.179663685 +0200\n> > +++ gcc/testsuite/g++.dg/reflect/reflect_constant_array11.C   2026-04-10\n> 17:05:50.683365136 +0200\n> > @@ -0,0 +1,18 @@\n> > +// { dg-do compile { target c++26 } }\n> > +// { dg-additional-options \"-freflection\" }\n> > +// Test std::meta::reflect_constant_string.\n> > +\n> > +#include <meta>\n> > +#include <ranges>\n> > +#include <span>\n> > +\n> > +using namespace std::meta;\n> > +\n> > +struct A { int a, b; mutable int c; };\n> > +constexpr A aa[2] = { { 1, 2, 3 }, { 4, 5, 6 } };\n> > +constexpr auto a = reflect_constant_array (aa);\n> > +// { dg-error \"'reflect_constant_array' argument with\n> 'std::ranges::range_value_t<const A \\\\\\[2\\\\\\]>' \\\\\\{aka 'A'\\\\\\} which is\n> not a structural type\" \"\" { target *-*-* } .-1 }\n> > +struct B { constexpr B (int x, int y) : a (x), b (y) {} constexpr ~B ()\n> {} B (const B &) = delete; int a, b; };\n> > +constexpr B b[2][2] = { { { 1, 2 }, { 2, 3 } }, { { 3, 4 }, { 4, 5 } }\n> };\n> > +constexpr auto c = reflect_constant_array (b);\n> > +// { dg-error \"'reflect_constant_array' argument with\n> 'std::ranges::range_value_t<const B \\\\\\[2\\\\\\]\\\\\\[2\\\\\\]>' \\\\\\{aka 'B\n> \\\\\\[2\\\\\\]'\\\\\\} which is not copy constructible\" \"\" { target *-*-* } .-1 }\n> > --- gcc/testsuite/g++.dg/reflect/define_static_array6.C.jj    2026-04-10\n> 15:44:52.229788936 +0200\n> > +++ gcc/testsuite/g++.dg/reflect/define_static_array6.C       2026-04-10\n> 15:52:38.099857297 +0200\n> > @@ -0,0 +1,27 @@\n> > +// LWG4483 - Multidimensional arrays are not supported by\n> > +// meta::reflect_constant_array and related functions.\n> > +// { dg-do compile { target c++26 } }\n> > +// { dg-additional-options \"-freflection\" }\n> > +\n> > +#include <meta>\n> > +\n> > +consteval auto\n> > +foo ()\n> > +{\n> > +  int a[3][3][3];\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     a[i][j][k] = i + j + k;\n> > +  return std::define_static_array (a);\n> > +}\n> > +\n> > +static_assert (foo ().size () == 3);\n> > +constexpr auto *m = foo ().data ();\n> > +consteval {\n> > +  for (int i = 0; i < 3; ++i)\n> > +    for (int j = 0; j < 3; ++j)\n> > +      for (int k = 0; k < 3; ++k)\n> > +     if (m[i][j][k] != i + j + k)\n> > +       throw 1;\n> > +}\n> > --- gcc/testsuite/g++.dg/reflect/define_static_object2.C.jj   2026-03-27\n> 10:17:16.120298331 +0100\n> > +++ gcc/testsuite/g++.dg/reflect/define_static_object2.C      2026-04-10\n> 16:09:20.261858550 +0200\n> > @@ -1,3 +1,5 @@\n> > +// LWG4483 - Multidimensional arrays are not supported by\n> > +// meta::reflect_constant_array and related functions.\n> >   // { dg-do compile { target c++26 } }\n> >   // { dg-additional-options \"-freflection\" }\n> >   // Test std::define_static_object.\n> > @@ -5,14 +7,19 @@\n> >   #include <meta>\n> >\n> >   constexpr int arr[]{1, 2, 3};\n> > -// LWG4483 use extract(reflect_constant_array())\n> > -// constexpr const int(*ptr)[3] = std::define_static_object(arr);\n> > -// static_assert( *ptr == std::define_static_array(arr).data() );\n> > -// static_assert( ptr = &std::meta::constant_of(arr) );\n> > +constexpr const int (*ptr)[3] = std::define_static_object (arr);\n> > +static_assert (*ptr == std::define_static_array (arr).data ());\n> > +static_assert (ptr == &[: std::meta::constant_of (^^arr) :]);\n> >\n> >   constexpr int marr[3][3]{1, 2, 3};\n> > -// LWG4483 array are not structural so this fail\n> > -// constexpr const int(*mptr)[3][3] = std::define_static_object(marr);\n> > -// static_assert( *mptr == std::define_static_array(marr).data() );\n> > -// static_assert( mptr = &std::meta::constant_of(marr) );\n> > +constexpr const int (*mptr)[3][3] = std::define_static_object (marr);\n> > +static_assert (*mptr == std::define_static_array (marr).data ());\n> > +static_assert (mptr == &[: std::meta::constant_of (^^marr) :]);\n> >\n> > +union U { int a; long long b; };\n> > +constexpr U u = { .a = 42 };\n> > +constexpr const U *up = std::define_static_object (u);\n> > +static_assert (up->a == 42);\n> > +constexpr U v = { .b = 43LL };\n> > +constexpr const U *vp = std::define_static_object (v);\n> > +static_assert (vp->b == 43LL);\n> > --- libstdc++-v3/include/std/meta.jj  2026-04-08 07:49:13.477647992 +0200\n> > +++ libstdc++-v3/include/std/meta     2026-04-10 15:57:25.423013150 +0200\n> > @@ -682,11 +682,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n> >       define_static_object(_Tp&& __t)\n> >       {\n> >         using _Up = remove_cvref_t<_Tp>;\n> > -      if constexpr (meta::is_class_type(^^_Up))\n> > +      if constexpr (meta::is_class_type(^^_Up) ||\n> meta::is_union_type(^^_Up))\n> >       {\n> >         auto __cst = meta::reflect_constant(std::forward<_Tp>(__t));\n> >         return std::addressof(meta::extract<const _Up&>(__cst));\n> >       }\n> > +      else if constexpr (meta::is_array_type(^^_Up))\n> > +     {\n> > +       auto __cst =\n> meta::reflect_constant_array(std::forward<_Tp>(__t));\n> > +       return std::addressof(meta::extract<const _Up&>(__cst));\n> > +     }\n> >         else\n> >       return std::define_static_array(span(std::addressof(__t),\n> 1)).data();\n> >       }\n> >\n> >\n> >       Jakub\n> >\n>\n>","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 (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=Ey9QLPa1;\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 (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=Ey9QLPa1","sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com","sourceware.org; spf=pass smtp.mailfrom=gmail.com","server2.sourceware.org;\n arc=pass smtp.remote-ip=209.85.167.41"],"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 4fwLMQ022wz1yHM\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 09:38:57 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 338E34BA2E13\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 23:38:56 +0000 (GMT)","from mail-lf1-f41.google.com (mail-lf1-f41.google.com\n [209.85.167.41])\n by sourceware.org (Postfix) with ESMTPS id 438CC4BA23DF\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 23:16:49 +0000 (GMT)","by mail-lf1-f41.google.com with SMTP id\n 2adb3069b0e04-5a402b2d102so2072721e87.3\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 16:16:49 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 338E34BA2E13","OpenDKIM Filter v2.11.0 sourceware.org 438CC4BA23DF"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 438CC4BA23DF","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 438CC4BA23DF","ARC-Seal":["i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1776208614; cv=pass;\n b=b2aKDF2GLz7NtAwqKXRBsgYPKXw47s6BQ1KWiZpcRkkgc9DE0JB342O+QiTwAfgDhmPfRCZuhNVoHCJbUmX+FSrlFQd/zK8ARp3wyUIXHXxCBtWnt2DIrexje3/YMhvG//aBWLL3aqTXB7l9HmTcQfTXAPAzZNrkmd/5ZOlXhSg=","i=1; a=rsa-sha256; t=1776208608; cv=none;\n d=google.com; s=arc-20240605;\n b=dBY63/W2ceJLRtOd6KwH3bFFppS0ZfP8N7e7m9XgyOKuWjOsCJ6kNJ8QuW6Uwp+uuR\n NzwiVl1VasGHHmgW+j2w4nIOXwNumYKtq2d01IUn/UPvAv+khKJGezJxx0aetOfQcZ0d\n OQg38XABjnoZtAMZZ17Y2sj7PDKxGV6Yn55AFw0RMNp3Kzgr90sp/6j7PzNOAVPHC9Ji\n givgi6UyPIrZjV7bcfZ3Kk7p5cU46uTLeKC/CbThWtaGWA2LuMjUaOCUmbktcww+XYBH\n Z3VOZ+HL6VHcraTAKXPHjmqdJw5rlaBdIxgHJ+vBLIylO2VypBOobb4T8YskIt9qiavf\n rtpQ=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776208614; c=relaxed/simple;\n bh=tkGdx5MjY/C2M5o63gaLI5u6KUPzBd9qyEPmY/e1XrQ=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=rRF3mlMEUzs8Xi8Zu0vnGsj/QKwZH5//Q8hJ/VswP+bdKprp3K101b9mW1bx/PL0MVgFTfJAkkjf30x7irCncfcHfXll1fHIQi/DRhWGO352yU2ibZBmJI26Gm5LLWU/WHMEONrfNK3jYRxQAUxjFtOwrOnKQ4Nr6Bi1PvSxfts=","i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;\n s=arc-20240605;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:dkim-signature;\n bh=VNlZqUDo6YVAhiYnyvk0WV01mObFr7ju7aqxbJKG7Jw=;\n fh=vn1icq01dqyMxeJ/8MGyKlr850Achr0AKqa/DEn0qtY=;\n b=HyB/etnSImxD0DulJIK7+peOENGa4gKauJbYzjeX5oLd29goQkAZzjZbABWPIN03cu\n K6zJ8+4d6b9LDSkc4PyDO28U7RxnFoit4YesKloVlHjXfn6aLUGgxt5vs/AY3e5NtwPk\n oFzJ1F6K7sSg0f46ahr7HyOZWX9/0JDHF/kfwMicVh2ps9oILDJ2COJ6XRrkePyJZyOT\n 9YdHZlb1MAkvXOwbpFfOuzmA9gapPr91UaASqbzMZEtSLhO9THW+9PY1nGTNN3gKdLzU\n pCYwI1hBaP0PdDJBWteHcAGgVVZNgn2DdW2uyRfR9lGFDA00tmUnLwla7L/kPH37Q7tj\n DEkA==; darn=gcc.gnu.org"],"ARC-Authentication-Results":["i=2; server2.sourceware.org","i=1; mx.google.com; arc=none"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776208608; x=1776813408; darn=gcc.gnu.org;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:from:to:cc:subject:date:message-id:reply-to;\n bh=VNlZqUDo6YVAhiYnyvk0WV01mObFr7ju7aqxbJKG7Jw=;\n b=Ey9QLPa1RrfN1nBqfL1uYuFMLmN/FQBZCa/81K8BrNCPDxp+c3gakrJTyGm8zArcUW\n bzuHdfN6vrdH/1rjzkbjIV03dEsxU1HpCwuVUSVBPLSv6PlI5LVzuZUzxvz7J4memp+l\n q0KaeLbCL5uCBfjIRbdli/1EQpkI3gc4dgd0RLbvFjAh1SMRuJ98C74V3Fpap/BEqUTO\n J8GjrT0vLkQZ/MTP+RSDNWXXobcKwOZCuRa9+Rujgzm8RczFcLIomD3s+76BQSUgjgE5\n X+GoiDmMzpfBD+la7uZnc0CbWuAIRrHKlqHJ9ZN4TWCtp8DVKsoMkiJWSJT76xMneZWp\n XJvA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776208608; x=1776813408;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=VNlZqUDo6YVAhiYnyvk0WV01mObFr7ju7aqxbJKG7Jw=;\n b=K8qW0ky9raow+7OQGYfm5xqJvScuZs39jeH2evZowV620ZwzHnd5U+KIDFZinrLzZK\n SQv5i+0NgsyXEg0yrGEmv1pHry5yx9JRjnRMS0NfxHqBkfY2Y/LppOOEAOr1971T8Omf\n gZY2idra2D/7SuPXqb5N33ole2JAjmdkhB3izIkBZ7swhKOcgXq+q1S/Xwz0QKgqLQie\n s+MU6jkzNoxkMfCL99eUTSnfvAxT+sDP4otFblBi8c3ZtIjjGiRbBv6ebq0NlY1In2y5\n kRBZlZGAmbcjLf9Zf3UhWCSrRik4i+ZLnzCdEVWUtVQjIVa58tjVGSGrgGWvWoYxA3u8\n GJHA==","X-Forwarded-Encrypted":"i=1;\n AFNElJ+hIEv1JwQnJ2cOl3186AxK88wmgl8KB3A/Zx2Vz1ia2A/SqOfaTEPZHEwcSkB3a9iM537FCixbShWHPQ==@gcc.gnu.org","X-Gm-Message-State":"AOJu0Yx2nZ3Y6m+aIIF+nvIAAhBaYol33UE1BNSgJlluWBkSrSv1ELQ9\n bU0ixeDZOsI++bfXbczL0RyeEzEgMojWR9AeZqYW8xTbKmXsq+dnWhyjG1k5BRFzheeqAeDkcEr\n zr6iHyZj0xz65Rr0rcol2Yugkivz1PQQ=","X-Gm-Gg":"AeBDietuiYI+9dB5Qb+ceozNispVCiqDcBeWnN/P40wLhzdqgBP9U0DlxnpavtD4JPH\n PZ+a7mTzKJVxFKRGgLxk+x3k/Sfj96Wkqfe1h67i2DyqJO+zi2SrBuAZ5BOOY3hUhw6jaoxsD8o\n Ai0fdUEeTRiXt0YDhzXXimXkmBihiC00Wla9S12kWMf4MWw7MyqwrNRpeVuoty574EhYVDay4V5\n bV7VD/C25x6i1XbIioqfb5zjeM/V1CHrf7VsFlPTHsSNRRsEsWWxr8pi8V074CQssdc4JAt7xWW\n 3jDual75uAiXvxw1P0J+Nrflk1PpCzGaQ8VW48xwdCeHqySM3MNDZdtF6tmeVwCHZkVW8vjwT2n\n Hoqq4a0PztlDJY3qq43nF0dyXQjE=","X-Received":"by 2002:a05:6512:1248:b0:5a3:ffc6:660c with SMTP id\n 2adb3069b0e04-5a3ffc669f1mr2830418e87.1.1776208607454; Tue, 14 Apr 2026\n 16:16:47 -0700 (PDT)","MIME-Version":"1.0","References":"<adkUGggIiITbC-cp@tucnak>\n <CAKvuMXBJMd=813ixZmS-_+MuP8_EJf8SrtnbvEfueM2spptYZA@mail.gmail.com>\n <adkbHhg3-pyumdxH@tucnak> <1ab72c7c-be1a-4539-9fb5-b0d11071752b@redhat.com>\n <ad6UuwEDu1j6WhdA@tucnak> <4606f782-5c22-4b34-bfd4-8b31c659bd1a@redhat.com>","In-Reply-To":"<4606f782-5c22-4b34-bfd4-8b31c659bd1a@redhat.com>","From":"Jonathan Wakely <jwakely.gcc@gmail.com>","Date":"Wed, 15 Apr 2026 00:16:34 +0100","X-Gm-Features":"AQROBzB8tmf4G8jqHTTpP-PULCDXnxuuTRsQywfZ5jqi2fEPRKJrKWBCisJk4vk","Message-ID":"\n <CAH6eHdS5oQ8tE_wCKF3JDxWjciHiouQTef=iLOM7RdkuN6cjEA@mail.gmail.com>","Subject":"Re: [PATCH] c++, libstdc++, v3: Implement LWG4483 - Multidimensional\n arrays are not supported by meta::reflect_constant_array and related\n functions","To":"Jason Merrill <jason@redhat.com>","Cc":"Jakub Jelinek <jakub@redhat.com>, Marek Polacek <polacek@redhat.com>,\n Jonathan Wakely <jwakely@redhat.com>, Tomasz Kaminski <tkaminsk@redhat.com>,\n gcc-patches <gcc-patches@gcc.gnu.org>, \"libstdc++\" <libstdc++@gcc.gnu.org>","Content-Type":"multipart/alternative; boundary=\"0000000000001828b4064f73cb08\"","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>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}}]