Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here meta::extract either wrongly throws or we crash.  The problem is
that it got a partial specialization, with which it can't do much.

When we have

  template <class F>
  struct S {
      template <int I>
      static constexpr int visit(F&&) { return 42; }

      static constexpr std::meta::info fptrs = ^^visit<0>;
  };

and do get_reflection -> resolve_nondeduced_context for ^^visit<0>,
we should already have substituted F, otherwise we only substitute
I with 0 and are left with a partial specialization.  F should have
been substituted in tsubst_expr/REFLECT_EXPR, but the reflection is

  REFLECT_EXPR<TEMPLATE_ID_EXPR<OVERLOAD, 0>>

and tsubst_expr doesn't do much with an OVERLOAD.  This thing should
be

  REFLECT_EXPR<BASELINK<TEMPLATE_ID_EXPR<OVERLOAD, 0>>>

so that we go to tsubst_baselink and properly substitute the
TEMPLATE_DECL in the OVERLOAD.

cp_parser_reflect_expression doesn't call finish_id_expression which
would add the BASELINK for reason mentioned in the comment there.  So
I think we can do the following: just call baselink_for_fns to create
the BASELINK if needed.

        PR c++/124617

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_reflect_expression): Call baselink_for_fns.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/dep12.C: New test.
        * g++.dg/reflect/dep13.C: New test.
---
 gcc/cp/parser.cc                     |  2 ++
 gcc/testsuite/g++.dg/reflect/dep12.C | 15 +++++++++++++++
 gcc/testsuite/g++.dg/reflect/dep13.C | 25 +++++++++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/reflect/dep12.C
 create mode 100644 gcc/testsuite/g++.dg/reflect/dep13.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 8d88dc9c312..34c88be8beb 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -10185,6 +10185,8 @@ cp_parser_reflect_expression (cp_parser *parser)
        && variable_template_p (TREE_OPERAND (t, 0))
        && !concept_check_p (t))
       t = finish_template_variable (t);
+    else if (is_overloaded_fn (t))
+      t = baselink_for_fns (t);
     if (cp_parser_parse_definitely (parser))
       return get_reflection (loc, t);
   }
diff --git a/gcc/testsuite/g++.dg/reflect/dep12.C 
b/gcc/testsuite/g++.dg/reflect/dep12.C
new file mode 100644
index 00000000000..22dfc37b48b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/dep12.C
@@ -0,0 +1,15 @@
+// PR c++/124617
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+template <class T>
+struct S {
+  template <class U>
+  static void f() {}
+
+  static constexpr auto p = ^^f<int>;
+};
+
+constexpr void (*p)() = extract<void(*)()>(S<int>::p);
diff --git a/gcc/testsuite/g++.dg/reflect/dep13.C 
b/gcc/testsuite/g++.dg/reflect/dep13.C
new file mode 100644
index 00000000000..8d262a4a878
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/dep13.C
@@ -0,0 +1,25 @@
+// PR c++/124617
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+template <class F>
+struct S {
+    template <int I>
+    static constexpr int visit(F&&) { return 42; }
+
+    using Ptr = decltype(&visit<0>);
+    static constexpr std::meta::info fptrs = ^^visit<0>;
+};
+
+template <class F>
+constexpr int foo(F&& f) {
+    using Impl = S<F>;
+    auto which = Impl::fptrs;
+    auto func = std::meta::extract<typename Impl::Ptr>(which);
+    return func((F&&)f);
+}
+
+struct Plus { };
+static_assert(foo(Plus{}) == 42);

base-commit: c2203f9b2153f7a5a512cdb91135f728fe1851af
-- 
2.53.0

Reply via email to