https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124249
--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The trunk branch has been updated by Marek Polacek <[email protected]>: https://gcc.gnu.org/g:127bd0f40827d7472cebacd2093d3379ec25dbd7 commit r17-4197-g127bd0f40827d7472cebacd2093d3379ec25dbd7 Author: Marek Polacek <[email protected]> Date: Tue Aug 4 16:10:55 2026 -0400 c++/reflection: P4101, Consteval-only values [PR125820] <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4101r1.html> changes the consteval-only type model to a consteval-only values model. A null reflection is no longer consteval-only. So, for instance, this is now OK: std::meta::info i; auto foo (std::meta::info i) { return i; } // not consteval but std::meta::info type = ^^int; is still ill-formed, provided it's not in an immediate function context I suppose for users the change is not that dramatic, but our implementation had to change quite a bit. For one thing, we now need to be able to handle null reflections in the ME. This is done by removing META_TYPE and using LANG_TYPE instead. In dwarf2out, LANG_TYPE already maps to DW_TAG_unspecified_type so we should get "decltype(^^int)" in debug info. To be able to detect invalid code like the bare: ^^int; and to allow code like: int i = (^^int, 42); // namespace scope convert_to_void no longer throws away discarded-value expressions. But the modules and analyzer code sort of depended on these being discarded. Obviously, first we have to check for consteval-only values and only then can we discard them. But we need to do the discarding before maybe_save_constexpr_fundef; otherwise we'd have to add a separate walk for the copy. I moved the discarding into cp_fold_r. Consteval-only values are now checked right before the discarding and in cp_genericize_r. As mentioned above, a null reflection can get into the ME, but REFLECT_EXPR still can't. rewrite_null_reflection rewrites REFLECT_EXPRs representing a null reflection to zero. The gcov-24.C change is arguably a fix, caused by adding a location to the CONVERT_EXPR in convert_to_void. genericize_c_loop has location_t incr_locus = expr_loc_or_loc (incr, start_locus); protected_set_expr_location_if_unset (incr, start_locus); where incr is the CONVERT_EXPR. Previously its location was UNKNOWN_LOCATION so _if_unset set start_locus, but now the increment stays on line 41. Taking the address of a consteval function is no longer prohibited outside an immediate function context, provided the result initializes a constexpr variable. I didn't want to inflate the patch with testsuite changes for all the consteval tests that will need to be updated once this is resolved. PR c++/125820 PR c++/124249 PR c++/124414 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_binary_expression): Check REFLECTION_TYPE_P instead of REFLECT_EXPR_P. (check_bit_cast_type): Also detect REFLECTION_TYPE_P. (cxx_eval_outermost_constant_expr): Delete consteval-only smuggling detection code. (potential_constant_expression_1) <case CONVERT_EXPR>: Recurse with want_rval=false for discarded-value expressions. * constraint.cc (satisfy_atom): Check require_constant_expression before calling cxx_constant_value. Set result to error_mark_node otherwise. * cp-gimplify.cc (cp_gimplify_expr) <case CALL_EXPR>: Don't call consteval_only_p and check_out_of_consteval_use. (wipe_consteval_only_r): Remove. (cp_fold_immediate_r): Don't detect invalid uses of consteval-only types here. Set *stmt_p to error_mark_node if the consteval call was invalid. <case IF_STMT>: Don't call wipe_consteval_only_r. (cp_fold_r) <case CONVERT_EXPR>: New, remove discarded-value expressions. (cp_genericize_r) <case ADDR_EXPR>: Call check_out_of_consteval_use. <case BIND_EXPR>: Call rewrite_null_reflection before pruning. <case REFLECT_EXPR>: Detect invalid uses of consteval-only expressions. * cp-objcp-common.cc (cp_common_init_ts): Remove the META_TYPE marking. * cp-tree.def (META_TYPE): Remove. * cp-tree.h (REFLECTION_TYPE_P): Adjust to check if TYPE is meta_info_type_node. (rewrite_null_reflection): Declare. (consteval_only_p): No longer pure. (check_consteval_only_fn): Remove. * cvt.cc (convert_to_void): Don't call check_out_of_consteval_use here. Don't remove discarded-value expressions here. Use a location when building the CONVERT_EXPR. * cxx-pretty-print.cc (cxx_pretty_printer::simple_type_specifier) <case META_TYPE>: Remove. <case LANG_TYPE>: New. (cxx_pretty_printer::type_id) <case META_TYPE>: Remove. <case LANG_TYPE>: New. * decl.cc (wrapup_namespace_globals): Call rewrite_null_reflection on each element of statics. (cp_finish_decl): Don't call check_out_of_consteval_use. Assert !consteval_only_p. (grokfndecl): Don't call check_consteval_only_fn. * decl2.cc (maybe_make_one_only): Don't return early for consteval_only_p. (mark_needed): Likewise. (prune_vars_needing_no_initialization): Don't prune consteval_only_p variables. (c_parse_final_cleanups): Call rewrite_null_reflection. * error.cc (dump_type) <case LANG_TYPE>: Handle REFLECTION_TYPE_P. <case META_TYPE>: Remove. (dump_type_prefix) <case META_TYPE>: Remove. (dump_type_suffix) <case META_TYPE>: Remove. (dump_expr): Use REFLECTION_TYPE_P. * init.cc (perform_member_init): Don't call check_out_of_consteval_use. * mangle.cc (write_type) <case META_TYPE>: Remove. <case LANG_TYPE>: Handle REFLECTION_TYPE_P. * module.cc (trees_out::type_node) <case META_TYPE>: Remove. <case LANG_TYPE>: New. (trees_in::tree_node) <case META_TYPE>: Remove. <case LANG_TYPE>: New. * name-lookup.cc (name_lookup::adl_type): Move the REFLECTION_TYPE_P handling to case LANG_TYPE. * pt.cc (tsubst) <case META_TYPE>: Remove. (unify) <case META_TYPE>: Remove. <case LANG_TYPE>: New. (instantiate_body): Don't call check_consteval_only_fn. * reflect.cc (init_reflection): Use LANG_TYPE instead of META_TYPE for meta_info_type_node. (null_reflection_p): Also accept the rewritten form. (rewrite_null_reflection): New. (consteval_only_p): Rewrite for P4101. (struct consteval_only_p_walker): Remove. (consteval_only_value_p): New. (consteval_only_p_walker::walk): Remove. (check_out_of_consteval_use_r): Walk INIT_EXPR. Handle EXPR_STMT specially. (check_out_of_consteval_use): Remove the special VAR_P handling. (compare_reflections): Deal with null reflections first. (check_consteval_only_fn): Remove. * search.cc (check_final_overrider): Don't check consteval_only_p. * semantics.cc (cp_build_bit_cast): Likewise. * tree.cc (type_has_unique_obj_representations) <case LANG_TYPE>: New, handle REFLECTION_TYPE_P. * typeck.cc (cp_build_binary_op): Use REFLECTION_TYPE_P. (check_return_expr): Don't call check_out_of_consteval_use. * typeck2.cc (store_init_value): Check that an immediate object is associated with a constexpr variable. gcc/ChangeLog: * expr.cc (count_type_elements) <case LANG_TYPE>: Return 1. * tree.cc (wide_int_to_tree_1) <case LANG_TYPE>: New. (cache_integer_cst) <case LANG_TYPE>: New. libstdc++-v3/ChangeLog: * include/std/meta (std::meta::exception::what): Change it to constexpr. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-uneval3.C: Add a dg-error. * g++.dg/gcov/gcov-24.C: Adjust expected output. * g++.dg/reflect/bit_cast.C: Remove dg-error. Extend. * g++.dg/reflect/crash12.C: Remove dg-error. * g++.dg/reflect/crash18.C: Likewise. * g++.dg/reflect/diag3.C: Adjust expected output. * g++.dg/reflect/expr11.C: Likewise. * g++.dg/reflect/expr12.C: Likewise. * g++.dg/reflect/init10.C: Likewise. * g++.dg/reflect/init11.C: Likewise. * g++.dg/reflect/init12.C: Remove dg-error. * g++.dg/reflect/init16.C: Adjust expected output. * g++.dg/reflect/init19.C: Remove dg-error. * g++.dg/reflect/init4.C: Add an XFAIL. * g++.dg/reflect/init5.C: Remove dg-error. * g++.dg/reflect/init6.C: Adjust expected output. * g++.dg/reflect/init7.C: Likewise. * g++.dg/reflect/init9.C: Likewise. * g++.dg/reflect/override1.C: Likewise. * g++.dg/reflect/p2996-15.C: Remove dg-error. * g++.dg/reflect/parm3.C: Adjust expected output. * g++.dg/reflect/parm4.C: Likewise. * g++.dg/reflect/pr124012.C: Remove dg-error. * g++.dg/reflect/type12.C: Likewise. * g++.dg/reflect/type2.C: Adjust expected output. * g++.dg/reflect/bit_cast2.C: New test. * g++.dg/reflect/expr19.C: New test. * g++.dg/reflect/null7.C: New test. * g++.dg/reflect/type_trait19.C: New test. * g++.dg/reflect/typeinfo1.C: New test. * g++.dg/reflect/value1.C: New test. * g++.dg/reflect/value2.C: New test. * g++.dg/reflect/value3.C: New test. * g++.dg/reflect/value4.C: New test. * g++.dg/reflect/value5.C: New test. * g++.dg/reflect/value6.C: New test. * g++.dg/reflect/value7.C: New test. * g++.dg/reflect/value8.C: New test. * g++.dg/reflect/vector2.C: New test. Reviewed-by: Jason Merrill <[email protected]>
