Bootstrapped/regtested on x86_64-pc-linux-gnu.

This accidentally allows `&(A::operator int);` to compile.
`auto f = &(A::operator int);` correctly errors, but emits a funny message: 
"note: (a pointer to member can only be formed with '&A::operator int<int>')"

-- >8 --

Taking the address of a conversion function template instantiation
incorrectly errors.

        PR c++/122383

gcc/cp/ChangeLog:

        * pt.cc (resolve_overloaded_unification): If expr represents a
        conversion function template instantiation, call
        lookup_template_function with baselink, then fall through to
        TEMPLATE_ID_EXPR check.
        (resolve_nondeduced_context): Likewise.

gcc/testsuite/ChangeLog:

        * g++.dg/template/conv22.C: New test.
---
 gcc/cp/pt.cc                           | 22 ++++++++++++++++++++--
 gcc/testsuite/g++.dg/template/conv22.C | 18 ++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/conv22.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6992b5196fe..1faba19c48e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -25193,6 +25193,7 @@ resolve_overloaded_unification (tree tparms,
   int good = 0;
   tree goodfn = NULL_TREE;
   bool addr_p;
+  tree baselink = NULL_TREE;
 
   if (TREE_CODE (arg) == ADDR_EXPR)
     {
@@ -25212,7 +25213,18 @@ resolve_overloaded_unification (tree tparms,
 
   /* Strip baselink information.  */
   if (BASELINK_P (arg))
-    arg = BASELINK_FUNCTIONS (arg);
+    {
+      baselink = arg;
+      arg = BASELINK_FUNCTIONS (arg);
+    }
+
+  if (TREE_CODE (arg) == OVERLOAD
+      && IDENTIFIER_CONV_OP_P (OVL_NAME (arg)))
+    {
+      tree targs = make_tree_vec (1);
+      TREE_VEC_ELT (targs, 0) = BASELINK_OPTYPE (baselink);
+      arg = lookup_template_function (arg, targs);
+    }
 
   if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
     {
@@ -25361,7 +25373,13 @@ resolve_nondeduced_context (tree orig_expr, 
tsubst_flags_t complain)
       baselink = expr;
       expr = BASELINK_FUNCTIONS (expr);
     }
-
+  if (TREE_CODE (expr) == OVERLOAD
+      && IDENTIFIER_CONV_OP_P (OVL_NAME (expr)))
+    {
+      tree targs = make_tree_vec (1);
+      TREE_VEC_ELT (targs, 0) = BASELINK_OPTYPE (baselink);
+      expr = lookup_template_function (expr, targs);
+    }
   if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
     {
       int good = 0;
diff --git a/gcc/testsuite/g++.dg/template/conv22.C 
b/gcc/testsuite/g++.dg/template/conv22.C
new file mode 100644
index 00000000000..99a3f829b5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/conv22.C
@@ -0,0 +1,18 @@
+// PR c++/122383
+// { dg-do compile }
+
+struct A {
+  template<typename T>
+  operator T() {
+    return 0;
+  }
+};
+
+template<typename U>
+void f(U(A::*)()) {}
+
+int main() {
+  &A::operator int;
+
+  f(&A::operator int);
+}

base-commit: b1987874feead5e98f1ea005bd1ce5ff515eda7a
-- 
2.54.0

Reply via email to