Message ID | CAFk2RUZ+yx4ftYzL5g36B90-k_4tG2ahqKJ5ZC9ouxteLkvtEQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | [C++] Make taking the address of an overloaded function a non-deduced context | expand |
On 30 August 2017 at 01:19, Ville Voutilainen <ville.voutilainen@gmail.com> wrote: > 2017-08-29 Ville Voutilainen <ville.voutilainen@gmail.com> > > Make taking the address of an overloaded function a non-deduced context > > cp/ > > * pt.c (unify_overload_resolution_failure): Return unify_success > instead of unify_invalid. > > testsuite/ > > * g++.dg/overload/template6.C: New. Ah yes, tested on Linux-PPC64. I see some libstdc++ (runtime) failures from the testsuite, but as far as I can see they are there even before this patch.
On 30 August 2017 at 01:25, Ville Voutilainen <ville.voutilainen@gmail.com> wrote: > On 30 August 2017 at 01:19, Ville Voutilainen > <ville.voutilainen@gmail.com> wrote: >> 2017-08-29 Ville Voutilainen <ville.voutilainen@gmail.com> >> >> Make taking the address of an overloaded function a non-deduced context >> >> cp/ >> >> * pt.c (unify_overload_resolution_failure): Return unify_success >> instead of unify_invalid. >> >> testsuite/ >> >> * g++.dg/overload/template6.C: New. > > Ah yes, tested on Linux-PPC64. I see some libstdc++ (runtime) failures > from the testsuite, but as far as I can > see they are there even before this patch. ..and were caused by an unclean libstdc++ build on my end. The patch passes the full testsuite with no regressions.
On Tue, Aug 29, 2017 at 6:19 PM, Ville Voutilainen <ville.voutilainen@gmail.com> wrote: > 2017-08-29 Ville Voutilainen <ville.voutilainen@gmail.com> > > Make taking the address of an overloaded function a non-deduced context > > cp/ > > * pt.c (unify_overload_resolution_failure): Return unify_success > instead of unify_invalid. Please also remove the error. OK with that change. Jason
On 30 August 2017 at 19:07, Jason Merrill <jason@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.voutilainen@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);
+}
On Wed, Aug 30, 2017 at 1:08 PM, Ville Voutilainen <ville.voutilainen@gmail.com> wrote: > On 30 August 2017 at 19:07, Jason Merrill <jason@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.voutilainen@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. Please add a comment before unify_success along the lines of "If there isn't a unique match, this is a non-deduced context, so we still succeed." OK with that change. Jason
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 564ffb0..4f731fd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6370,7 +6370,7 @@ unify_overload_resolution_failure (bool explain_p, tree arg) inform (input_location, " could not resolve address from overloaded function %qE", arg); - return unify_invalid (explain_p); + return unify_success (explain_p); } /* Attempt to convert the non-type template parameter EXPR to the 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); +}