aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-09-09 09:21:09 -0400
committerPatrick Palka <ppalka@redhat.com>2020-09-09 09:21:09 -0400
commit4e03e2e08b94f65f2be3db17f880c205ec262f87 (patch)
tree5374563ac2681eda05b43e4349fcc27042e963c8 /gcc
parent58905f90434ba9a64abac56324131d67c53910ae (diff)
downloadgcc-4e03e2e08b94f65f2be3db17f880c205ec262f87.zip
gcc-4e03e2e08b94f65f2be3db17f880c205ec262f87.tar.gz
gcc-4e03e2e08b94f65f2be3db17f880c205ec262f87.tar.bz2
c++: Fix resolving the address of overloaded pmf [PR96647]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/class.c13
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto-96647.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error9.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-fn6.C10
6 files changed, 41 insertions, 2 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3479b82..c9a1f75 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 708de83..7873941 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 33c8377..50a042e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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
index 0000000..314b2a1
--- /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/cpp0x/error9.C b/gcc/testsuite/g++.dg/cpp0x/error9.C
new file mode 100644
index 0000000..b712c7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/error9.C
@@ -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
index 0000000..3d79416
--- /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;