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