On 6/1/26 4:30 PM, Patrick Palka wrote:
On Mon, 25 May 2026, Eczbek wrote: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;I'm not sure this is valid.. resolve_nondeduced_context is concerned with the case of resolving a template-id but here we have a conversion-function-id. Treating it as if it's a template-id doesn't seem sound:
I think we should deduce U=int under https://eel.is/c++draft/temp#deduct.conv but as I just replied separately, this patch doesn't do that yet. https://eel.is/c++draft/temp#mem-5 is also illustrative. And the other compilers accept it: https://godbolt.org/z/8oehM37e1 Jason
