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