On 30 August 2017 at 19:07, Jason Merrill <ja...@redhat.com> wrote: > Please also remove the error. OK with that change.
Here's a new and much improved version as discussed on IRC. Tested on Linux-PPC64. Ok for trunk? 2017-08-30 Ville Voutilainen <ville.voutilai...@gmail.com> Make taking the address of an overloaded function a non-deduced context cp/ * pt.c (unify_overload_resolution_failure): Remove. (unify_one_argument): Adjust. testsuite/ * g++.dg/overload/template6.C: New.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 564ffb0..5cfe292 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6363,16 +6363,6 @@ unify_template_argument_mismatch (bool explain_p, tree parm, tree arg) return unify_invalid (explain_p); } -static int -unify_overload_resolution_failure (bool explain_p, tree arg) -{ - if (explain_p) - inform (input_location, - " could not resolve address from overloaded function %qE", - arg); - return unify_invalid (explain_p); -} - /* Attempt to convert the non-type template parameter EXPR to the indicated TYPE. If the conversion is successful, return the converted value. If the conversion is unsuccessful, return @@ -19090,12 +19080,10 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, templates and at most one of a set of overloaded functions provides a unique match. */ - - if (resolve_overloaded_unification - (tparms, targs, parm, arg, strict, - arg_strict, explain_p)) - return unify_success (explain_p); - return unify_overload_resolution_failure (explain_p, arg); + resolve_overloaded_unification (tparms, targs, parm, + arg, strict, + arg_strict, explain_p); + return unify_success (explain_p); } arg_expr = arg; diff --git a/gcc/testsuite/g++.dg/overload/template6.C b/gcc/testsuite/g++.dg/overload/template6.C new file mode 100644 index 0000000..f2650aa --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/template6.C @@ -0,0 +1,47 @@ +// { dg-do compile { target c++11 } } + +template <typename> +struct is_function { + static constexpr bool value = false; +}; + +template <typename R, typename ...Args> +struct is_function<R(Args...)> +{ + static constexpr bool value = true; +}; + +template<bool, typename> struct enable_if {}; + +template<typename T> struct enable_if<true, T> +{ + typedef T type; +}; + +template <class T> +struct remove_pointer +{ + typedef T type; +}; + +template <class T> +struct remove_pointer<T*> +{ + typedef T type; +}; + +void f(int) {} +void f(double) {} + +template <class T> +struct X +{ + template <class U=T, + typename enable_if<is_function< + typename remove_pointer<U>::type>::value, + bool>::type = false> X(U&&) {} +}; + +int main() { + X<void(*)(int)> x0(f); +}