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
