[PATCH] c++, libstdc++, v2: Implement LWG4483 - Multidimensional arrays are not supported by meta::reflect_constant_array and related functions

Jason Merrill jason@redhat.com
Tue Apr 14 19:02:51 GMT 2026


On 4/10/26 11:45 AM, Jakub Jelinek wrote:
> On Fri, Apr 10, 2026 at 05:29:13PM +0200, Tomasz Kaminski wrote:
>> Could you add a line:
>>       static_assert(foo() ==  std::meta::reflect_constant_array(std::span
>> <int[3][3]>(m)));
>> I.e. we check that only content matters, and not type of the range.
> 
> Here is an updated patch.
> 
> Interdiff is just
> +static_assert (foo () == std::meta::reflect_constant_array (m));
> +static_assert (foo () == std::meta::reflect_constant_array (std::span <const int[3][3]> (m)));
> ...
> +static_assert (bar () == std::meta::reflect_constant_array (n));
> +static_assert (bar () == std::meta::reflect_constant_array (std::span <const int[3][3]> (n)));
> in reflect_constant_array10.C test.
> 
> 2026-04-10  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* reflect.cc (adjust_array_elt): New function.
> 	(get_range_elts): Implement LWG4483 - Multidimensional arrays are not
> 	supported by meta::reflect_constant_array and related functions.
> 	Handle ARRAY_TYPE valuet.  Don't unshare_expr in the class valuet case,
> 	get_template_param_object will unshare.
> 
> 	* g++.dg/reflect/reflect_constant_array9.C: New test.
> 	* g++.dg/reflect/reflect_constant_array10.C: New test.
> 	* g++.dg/reflect/reflect_constant_array11.C: New test.
> 	* g++.dg/reflect/define_static_array6.C: New test.
> 	* g++.dg/reflect/define_static_object2.C: Uncomment older tests and
> 	fix them, add tests for unions.
> 
> 	* include/std/meta (define_static_object): Adjust for LWG4483 changes
> 	- handle unions and arrays differently.
> 
> --- gcc/cp/reflect.cc.jj	2026-04-10 08:45:20.716811803 +0200
> +++ gcc/cp/reflect.cc	2026-04-10 15:32:30.747654790 +0200
> @@ -394,6 +394,47 @@ replace_parm_r (tree *tp, int *walk_subt
>   static tree throw_exception (location_t, const constexpr_ctx *, const char *,
>   			     tree, bool *, tree *);
>   
> +/* Helper function for get_range_elts, handle adjustment of ARRAY_TYPE elts
> +   of a retvec.  */
> +
> +static tree
> +adjust_array_elt (location_t loc, const constexpr_ctx *ctx, tree valuet,
> +		  tree expr, tree fun, bool *non_constant_p, tree *jump_target)
> +{
> +  if (TREE_CODE (valuet) == ARRAY_TYPE)
> +    {
> +      if (TREE_CODE (expr) != CONSTRUCTOR
> +	  || TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
> +	return throw_exception (loc, ctx, "reflect_constant_array failed",
> +				fun, non_constant_p, jump_target);
> +      unsigned int i;
> +      tree val;
> +      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val)
> +	{
> +	  CONSTRUCTOR_ELT (expr, i)->value
> +	    = adjust_array_elt (loc, ctx, TREE_TYPE (valuet), val, fun,
> +				non_constant_p, jump_target);
> +	  if (*jump_target || *non_constant_p)
> +	    return NULL_TREE;
> +	}
> +      return expr;
> +    }
> +  else if (INTEGRAL_TYPE_P (valuet))

Why this special case instead of using convert_reflect_constant_arg for 
integers as well?

> +    {
> +      if (TREE_CODE (expr) == INTEGER_CST)
> +	return expr;
> +      return throw_exception (loc, ctx, "array element not a constant integer",
> +			      fun, non_constant_p, jump_target);
> +    }
> +  expr = convert_reflect_constant_arg (valuet, expr);
> +  if (expr == error_mark_node)
> +    return throw_exception (loc, ctx, "reflect_constant failed",
> +			    fun, non_constant_p, jump_target);
> +  if (VAR_P (expr))
> +    expr = DECL_INITIAL (expr);
> +  return expr;
> +}
> +
>   /* Kinds for get_range_elts.  */
>   
>   enum get_range_elts_kind {
> @@ -551,7 +593,23 @@ get_range_elts (location_t loc, const co
>   	    }
>   	  tree referencet = TYPE_MAIN_VARIANT (instr);
>   	  TREE_VEC_ELT (args, 0) = referencet;
> -	  if (!is_xible (INIT_EXPR, valuet, args))
> +	  if (valuete != valuet)
> +	    {
> +	      tree rt = referencet;
> +	      if (TYPE_REF_P (rt))
> +		rt = TREE_TYPE (rt);
> +	      if (!same_type_ignoring_top_level_qualifiers_p (valuet, rt))

You could use non_reference (referencet) here.

Jason



More information about the Libstdc++ mailing list