In resolve_address_of_overloaded_function, currently only the second
pass over the overload set (which considers just the function templates
in the overload set) checks constraints and performs return type
deduction when necessary.  But as the testcases below show, we need to
do this when considering non-template functions during the first pass,
too.

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

gcc/cp/ChangeLog:

        PR c++/96647
        * class.c (resolve_address_of_overloaded_function): Also check
        constraints and perform return type deduction when considering
        non-template functions in the overload set.

gcc/testsuite/ChangeLog:

        PR c++/96647
        * g++.dg/cpp0x/auto-96647.C: New test.
        * g++.dg/cpp2a/concepts-fn6.C: New test.
---
 gcc/cp/class.c                            | 16 ++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/auto-96647.C   | 10 ++++++++++
 gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C | 10 ++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/auto-96647.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3479b8207d2..c15cb04c654 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -8286,6 +8286,22 @@ resolve_address_of_overloaded_function (tree target_type,
             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.  */
+           ++function_depth;
+           instantiate_decl (fn, /*defer*/false, /*class*/false);
+           --function_depth;
+
+           require_deduced_type (fn);
+         }
+
        /* In C++17 we need the noexcept-qualifier to compare types.  */
        if (flag_noexcept_type
            && !maybe_instantiate_noexcept (fn, complain))
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto-96647.C 
b/gcc/testsuite/g++.dg/cpp0x/auto-96647.C
new file mode 100644
index 00000000000..314b2a16ac2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto-96647.C
@@ -0,0 +1,10 @@
+// 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;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C
new file mode 100644
index 00000000000..3d7941658d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C
@@ -0,0 +1,10 @@
+// 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;
-- 
2.28.0.358.g20de7e7e4f

Reply via email to