c++: Fix resolving the address of overloaded pmf [PR96647]
authorPatrick Palka <ppalka@redhat.com>
Wed, 9 Sep 2020 13:21:09 +0000 (09:21 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 9 Sep 2020 13:21:09 +0000 (09:21 -0400)
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 the same when considering non-template functions during the first
pass.

gcc/cp/ChangeLog:

PR c++/96647
* class.c (resolve_address_of_overloaded_function): Check
constraints_satisfied_p and perform return-type deduction via
maybe_instantiate_decl when considering non-template functions
in the overload set.
* cp-tree.h (maybe_instantiate_decl): Declare.
* decl2.c (maybe_instantiate_decl): Remove static.

gcc/testsuite/ChangeLog:

PR c++/96647
* g++.dg/cpp0x/auto-96647.C: New test.
* g++.dg/cpp0x/error9.C: New test.
* g++.dg/cpp2a/concepts-fn6.C: New test.

gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/testsuite/g++.dg/cpp0x/auto-96647.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/error9.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C [new file with mode: 0644]

index 3479b8207d2d1a8a5e696229c74fbc1efc61343a..c9a1f753d565419cd9bc6d4b2b28c7870de11fc7 100644 (file)
@@ -8286,6 +8286,19 @@ 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.  */
+           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))
index 708de83eb466e68da9eaed328fbe219db6b5a616..7873941175522e4713f47f1cd92b7cc1b0ae0b2d 100644 (file)
@@ -6905,6 +6905,7 @@ extern void do_type_instantiation         (tree, tree, tsubst_flags_t);
 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);
index 33c83773d33a4e4dfd4182557c5f5ec65c580097..50a042e807016e16d127d9392507c24a789853a2 100644 (file)
@@ -81,7 +81,6 @@ static void import_export_class (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
@@ -5386,7 +5385,7 @@ possibly_inlined_p (tree decl)
    them instantiated for reduction clauses which inline them by hand
    directly.  */
 
-static void
+void
 maybe_instantiate_decl (tree decl)
 {
   if (DECL_LANG_SPECIFIC (decl)
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto-96647.C b/gcc/testsuite/g++.dg/cpp0x/auto-96647.C
new file mode 100644 (file)
index 0000000..314b2a1
--- /dev/null
@@ -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/cpp0x/error9.C b/gcc/testsuite/g++.dg/cpp0x/error9.C
new file mode 100644 (file)
index 0000000..b712c7d
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+
+void f(int) { }
+auto f(bool) { return f(true); } // { dg-error "auto" }
+
+void (*ptr)(int) = &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 (file)
index 0000000..3d79416
--- /dev/null
@@ -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;