Tested dg.exp=reflect/* on x86_64-pc-linux-gnu, ok for trunk/16?

-- >8 --
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.

I see no evidence that we need this call at all.  Otherwise we'd have
to guard it with some check before calling it.

        PR c++/125764

gcc/cp/ChangeLog:

        * reflect.cc (eval_can_substitute): Don't call
        convert_from_reference.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/can_substitute3.C: New test.
---
 gcc/cp/reflect.cc                              |  1 -
 gcc/testsuite/g++.dg/reflect/can_substitute3.C | 10 ++++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/reflect/can_substitute3.C

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 673b79d0bde..0377639bede 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -5517,7 +5517,6 @@ 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);
       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 00000000000..98b8fbb315f
--- /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&()}));

base-commit: 46f07a7b7d4d5b391723a756e5fb7673800bac57
-- 
2.54.0

Reply via email to