aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2023-12-13 15:55:01 -0500
committerPatrick Palka <ppalka@redhat.com>2023-12-13 15:55:01 -0500
commitc822ad86984e752734b9c371f9cfef9330334ec4 (patch)
tree482989747017054bdb743a22cdbdc5d8803e547c
parentff35f1d4daa37e74f7a68e87c1a6c180d9a91f10 (diff)
downloadgcc-c822ad86984e752734b9c371f9cfef9330334ec4.zip
gcc-c822ad86984e752734b9c371f9cfef9330334ec4.tar.gz
gcc-c822ad86984e752734b9c371f9cfef9330334ec4.tar.bz2
c++: unifying FUNCTION_DECLs [PR93740]
unify currently always returns success when unifying two FUNCTION_DECLs (due to the is_overloaded_fn deferment within the default case), which means for the below testcase we incorrectly unify &A::foo and &A::bar leading to deduction failure for the index_of calls due to a bogus base class ambiguity. This patch makes unify handle FUNCTION_DECL naturally like other decls. PR c++/93740 gcc/cp/ChangeLog: * pt.cc (unify) <case FUNCTION_DECL>: Handle it like FIELD_DECL and TEMPLATE_DECL. gcc/testsuite/ChangeLog: * g++.dg/template/ptrmem34.C: New test.
-rw-r--r--gcc/cp/pt.cc1
-rw-r--r--gcc/testsuite/g++.dg/template/ptrmem34.C27
2 files changed, 28 insertions, 0 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 0dd0a9c..9a21467b 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24964,6 +24964,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
gcc_unreachable ();
case FIELD_DECL:
+ case FUNCTION_DECL:
case TEMPLATE_DECL:
/* Matched cases are handled by the ARG == PARM test above. */
return unify_template_argument_mismatch (explain_p, parm, arg);
diff --git a/gcc/testsuite/g++.dg/template/ptrmem34.C b/gcc/testsuite/g++.dg/template/ptrmem34.C
new file mode 100644
index 0000000..75c911e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ptrmem34.C
@@ -0,0 +1,27 @@
+// PR c++/93740
+// { dg-do compile { target c++11 } }
+
+struct A {
+ void foo();
+ void bar();
+};
+
+template<class T, T val>
+struct const_val { };
+
+template<int N, class T>
+struct indexed_elem { };
+
+using mem_fun_A_foo = const_val<decltype(&A::foo), &A::foo>;
+using mem_fun_A_bar = const_val<decltype(&A::bar), &A::bar>;
+
+struct A_indexed_member_funcs
+ : indexed_elem<0, mem_fun_A_foo>,
+ indexed_elem<1, mem_fun_A_bar>
+{ };
+
+template<class T, int N>
+constexpr int index_of(indexed_elem<N, T>) { return N; }
+
+static_assert(index_of<mem_fun_A_foo>(A_indexed_member_funcs{}) == 0, "");
+static_assert(index_of<mem_fun_A_bar>(A_indexed_member_funcs{}) == 1, "");