https://gcc.gnu.org/g:64e69a5bed2691e47d6f15b086fbe6174dcfdd51
commit r16-9131-g64e69a5bed2691e47d6f15b086fbe6174dcfdd51 Author: Marek Polacek <[email protected]> Date: Fri Jun 12 09:43:52 2026 -0400 c++/reflection: crash with can_substitute and fn returning ref [PR125764] Here we crash in convert_from_reference because it gets a FUNCTION_TYPE int&(). Since its return type is a reference, it passes the c_f_r check: if (TREE_TYPE (val) && TYPE_REF_P (TREE_TYPE (val))) and we crash inside that block. The call isn't needed since r17-1271: return convert_nontype_argument (type, convert_from_reference (arg), complain); but we can also avoid calling it on TYPE_P because the function is meant for expressions only. PR c++/125764 gcc/cp/ChangeLog: * reflect.cc (eval_can_substitute): Don't call convert_from_reference on types. gcc/testsuite/ChangeLog: * g++.dg/reflect/can_substitute3.C: New test. Reviewed-by: Patrick Palka <[email protected]> (cherry picked from commit ea80d5b13dd9c4fdf979234ae24d5d9559402135) Diff: --- gcc/cp/reflect.cc | 3 ++- gcc/testsuite/g++.dg/reflect/can_substitute3.C | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index 1e95d3bd69f0..5f4d1d84b242 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -5514,7 +5514,8 @@ eval_can_substitute (location_t loc, const constexpr_ctx *ctx, return throw_exception (loc, ctx, "invalid argument to can_substitute", fun, non_constant_p, jump_target); - a = convert_from_reference (a); + if (!TYPE_P (a)) + a = convert_from_reference (a); TREE_VEC_ELT (rvec, i) = a; } if (DECL_TYPE_TEMPLATE_P (r) || DECL_TEMPLATE_TEMPLATE_PARM_P (r)) diff --git a/gcc/testsuite/g++.dg/reflect/can_substitute3.C b/gcc/testsuite/g++.dg/reflect/can_substitute3.C new file mode 100644 index 000000000000..98b8fbb315f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/can_substitute3.C @@ -0,0 +1,10 @@ +// PR c++/125764 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include <meta> + +template <typename T> +struct S {}; + +static_assert(can_substitute(^^S, {^^int&()}));
