From: Jakub Jelinek Date: Fri, 3 Jul 2026 18:41:45 +0000 (+0200) Subject: c++: Fix up ICEs with some metafns with non-dependent args in templates [PR126036] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a55bba03ab13df7140bcf4edd97481e584687d00;p=thirdparty%2Fgcc.git c++: Fix up ICEs with some metafns with non-dependent args in templates [PR126036] The following testcase ICEs, because potential_constant_expression_1 handles some forms of CAST_EXPR, but cxx_eval_constant_expression doesn't. Normally, if we have e.g. a non-dependent compound literal in a template, finish_compound_literal will create a CAST_EXPR, but fold_non_dependent_expr_template -> instantiate_non_dependent_expr_internal will fold that away, so constexpr.cc evaluation doesn't see it. reflect.cc calls finish_compound_literal in 3 spots, one is to create std::array {}, another one is when creating the std::meta::exception object to throw and the last one when creating std::vector object to return from various metafns. If that is done with processing_template_decl, finish_compound_literal will again return a CAST_EXPR, but unlike the usual case it is during constant evaluation and so instantiate_non_dependent_expr_internal will not be invoked on it to clean that up. Now, in the get_meta_exception_object case, we already have /* Don't throw in a template. */ if (processing_template_decl) { *non_constant_p = true; return NULL_TREE; } This patch uses the same thing (i.e. avoid folding even non-dependent metafn calls that would need finish_compound_literal during processing_template_decl) to fix this. I think in both cases it is fine to defer the constant evaluation, the return type from those metafns is not dependent (std::meta::info in the reflect_constant_array case, std::vector otherwise). 2026-07-03 Jakub Jelinek PR c++/126036 * reflect.cc (get_range_elts): Avoid calling finish_compound_literal when processing_template_decl, instead set *non_constant_p and return NULL_TREE. (process_metafunction): Likewise. * g++.dg/reflect/pr126036.C: New test. Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index 96f5de8481d..6caa74825b5 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -698,6 +698,12 @@ get_range_elts (location_t loc, const constexpr_ctx *ctx, tree call, int n, } if (kind == REFLECT_CONSTANT_ARRAY && sz == 0) { + /* Don't call finish_compound_literal in a template. */ + if (processing_template_decl) + { + *non_constant_p = true; + return NULL_TREE; + } /* Return std::array {}. */ tree args = make_tree_vec (2); TREE_VEC_ELT (args, 0) = valuet; @@ -7891,6 +7897,14 @@ process_metafunction (const constexpr_ctx *ctx, tree fun, tree call, if (check_metafn_return_type (loc, METAFN_KIND_RET (minfo), rettype, non_constant_p)) return NULL_TREE; + /* Don't call get_vector_of_info_elts (for any metafn which returns + vector) in a template. */ + if (processing_template_decl + && METAFN_KIND_RET (minfo) == METAFN_KIND_RET_VECTOR_INFO) + { + *non_constant_p = true; + return NULL_TREE; + } for (int argno = 0; argno < 3; ++argno) switch (METAFN_KIND_ARG (minfo, argno)) { diff --git a/gcc/testsuite/g++.dg/reflect/pr126036.C b/gcc/testsuite/g++.dg/reflect/pr126036.C new file mode 100644 index 00000000000..ad99aba37d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/pr126036.C @@ -0,0 +1,21 @@ +// PR c++/126036 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include + +namespace A { int a; }; + +template +void +foo () +{ + constexpr auto m = std::meta::members_of (^^A, std::meta::access_context::unchecked ()); + // { dg-error "is not a constant expression because it refers to a result of 'operator new'" "" { target *-*-* } .-1 } +} + +void +bar () +{ + foo <42> (); +}