On Wed, Feb 18, 2026 at 10:19:13PM +0100, Jakub Jelinek wrote:
> Hi!
> 
> Some of the following testcases are incorrectly accepted.
> The problem is in convert_nontype_argument.  It just does
> maybe_constant_value earlier.  Later on for integral/enum/floating
> point args it uses cxx_constant_value for complain & tf_error if
> not val_dep_p and expr is not a simple constant, similarly for
> class type it calls
>       /* Replace the argument with a reference to the corresponding template
>          parameter object.  */
>       if (!val_dep_p)
>         expr = create_template_parm_object (expr, complain);
>       if (expr == error_mark_node)
>         return NULL_TREE;
> etc.  But for NULLPTR_TYPE_P and REFLECTION_TYPE_P cases (I bet
> Marek has based the latter on the former) it only verifies the type
> and not the actual expression.

Yeah, I'm sure I followed NULLPTR_TYPE_P.

> I think we need to do that, because if maybe_constant_value fails, it
> just returns the passed in argument and if nothing checks it, we accept
> whatever was there (and sometimes ICE later).
> 
> The following patch implements that.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2026-02-18  Jakub Jelinek  <[email protected]>
> 
>       PR c++/124070
>       * pt.cc (convert_nontype_argument): For NULLPTR_TYPE_P case
>       if expr is not integer_zerop and is not val_dep_p try harder,
>       for complain & tf_error use cxx_constant_value and return NULL_TREE
>       for error_mark_node, without tf_error return NULL_TREE.  Similarly
>       for REFLECTION_TYPE_P case if expr is not REFLECT_EXPR and is not
>       val_dep_p try harder like for NULLPTR_TYPE_P.
> 
>       * g++.dg/cpp26/pr124070.C: New test.
>       * g++.dg/reflect/parameters_of4.C: Expect different diagnostics.
>       * g++.dg/reflect/define_aggregate7.C: New test.
>       * g++.dg/reflect/define_aggregate8.C: New test.
> 
> --- gcc/cp/pt.cc.jj   2026-02-18 10:45:29.000000000 +0100
> +++ gcc/cp/pt.cc      2026-02-18 16:39:30.130099365 +0100
> @@ -8017,6 +8017,18 @@ convert_nontype_argument (tree type, tre
>                  "because it is of type %qT", expr, type, TREE_TYPE (expr));
>         return NULL_TREE;
>       }
> +      if (!integer_zerop (expr) && !val_dep_p)
> +     {
> +       if (complain & tf_error)
> +         {
> +           expr = cxx_constant_value (expr);
> +           if (expr == error_mark_node)
> +             return NULL_TREE;
> +           gcc_assert (integer_zerop (expr));
> +         }
> +       else
> +         return NULL_TREE;
> +     }
>        return expr;
>      }
>    else if (CLASS_TYPE_P (type))
> @@ -8037,6 +8049,18 @@ convert_nontype_argument (tree type, tre
>                  "because it is of type %qT", expr, type, TREE_TYPE (expr));
>         return NULL_TREE;
>       }
> +      if (TREE_CODE (expr) != REFLECT_EXPR && !val_dep_p)

!REFLECT_EXPR_P

> +     {
> +       if (complain & tf_error)
> +         {
> +           expr = cxx_constant_value (expr);
> +           if (expr == error_mark_node)
> +             return NULL_TREE;
> +           gcc_assert (TREE_CODE (expr) == REFLECT_EXPR);

REFLECT_EXPR

> +         }
> +       else
> +         return NULL_TREE;
> +     }

Too bad these cases seem awkward to merge, which would be nice
since they're basically the same code :/.

LGTM.

Marek

Reply via email to