one, or vice versa. */
continue;
+ /* Constraints must be satisfied. This is done before
+ return type deduction since that instantiates the
+ function. */
+ if (!constraints_satisfied_p (fn))
+ continue;
+
+ if (undeduced_auto_decl (fn))
+ {
+ /* Force instantiation to do return type deduction. */
+ maybe_instantiate_decl (fn);
+ require_deduced_type (fn);
+ }
+
/* In C++17 we need the noexcept-qualifier to compare types. */
if (flag_noexcept_type
&& !maybe_instantiate_noexcept (fn, complain))
extern bool always_instantiate_p (tree);
extern bool maybe_instantiate_noexcept (tree, tsubst_flags_t = tf_warning_or_error);
extern tree instantiate_decl (tree, bool, bool);
+extern void maybe_instantiate_decl (tree);
extern int comp_template_parms (const_tree, const_tree);
extern bool template_heads_equivalent_p (const_tree, const_tree);
extern bool builtin_pack_fn_p (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
static bool determine_hidden_inline (tree);
-static void maybe_instantiate_decl (tree);
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
them instantiated for reduction clauses which inline them by hand
directly. */
-static void
+void
maybe_instantiate_decl (tree decl)
{
if (DECL_LANG_SPECIFIC (decl)
--- /dev/null
+// PR c++/96647
+// { dg-do compile { target c++11 } }
+
+template<typename>
+struct Base {
+ auto f(int) { }
+ auto f(char) { }
+};
+
+void (Base<void>::*ptr)(int) = &Base<void>::f;
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+void f(int) { }
+auto f(bool) { return f(true); } // { dg-error "auto" }
+
+void (*ptr)(int) = &f;
--- /dev/null
+// PR c++/96647
+// { dg-do compile { target c++20 } }
+
+template<typename T>
+struct Base {
+ auto f(int) { }
+ auto f(int) requires T::fail { static_assert(T::fail); }
+};
+
+void (Base<void>::*ptr)(int) = &Base<void>::f;