Message ID | 20200729191745.2781055-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: overload sets and placeholder return type [PR64194] | expand |
On Wed, 29 Jul 2020, Patrick Palka wrote: > In the testcase below, template argument deduction for the call > g(id<int>) goes wrong because the functions in the overload set id<int> > each have a yet-undeduced auto return type, and this undeduced return > type makes try_one_overload fail to match up any of these functions with > g's parameter type, leading to g's template parameter going undeduced > and to the overload set going unresolved. > > This patch fixes this issue by performing return type deduction via > instantiation before doing try_one_overload, in a manner similar to what > resolve_address_of_overloaded_function does. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to > commit? > > gcc/cp/ChangeLog: > > PR c++/64194 > * pt.c (resolve_overloaded_unification): If the function > template specialization has a placeholder return type, > then instantiate it before attempting unification. > > gcc/testsuite/ChangeLog: > > PR c++/64194 > * g++.dg/cpp1y/auto-fn60.C: New test. > --- > gcc/cp/pt.c | 11 ++++++++++- > gcc/testsuite/g++.dg/cpp1y/auto-fn60.C | 11 +++++++++++ > 2 files changed, 21 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/auto-fn60.C > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index 4d955c555dc..abb74520fc9 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -22118,7 +22118,16 @@ resolve_overloaded_unification (tree tparms, > if (subargs != error_mark_node > && !any_dependent_template_arguments_p (subargs)) > { > - elem = TREE_TYPE (instantiate_template (fn, subargs, tf_none)); > + fn = instantiate_template (fn, subargs, tf_none); > + if (undeduced_auto_decl (fn)) > + { > + /* Instantiate the function to deduce its return type. */ > + ++function_depth; > + instantiate_decl (fn, /*defer*/false, /*class*/false); > + --function_depth; > + } > + > + elem = TREE_TYPE (fn); > if (try_one_overload (tparms, targs, tempargs, parm, > elem, strict, sub_strict, addr_p, explain_p) > && (!goodfn || !same_type_p (goodfn, elem))) > diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C > new file mode 100644 > index 00000000000..237868c076b > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C > @@ -0,0 +1,11 @@ > +// PR c++/64194 > +// { dg-do compile { target c++14 } } > + > +template <typename T> void g(void (*)(T)) { } > + > +template <typename T> auto id(int) { } > +template <typename T> auto id(char) { return 0; } > + > +int main() { > + g(id<void>); Oops, this is supposed to use id<int> instead of id<void> to match up with the commit message (or vice versa). > +} > -- > 2.28.0.rc1 > >
On 7/29/20 3:23 PM, Patrick Palka wrote: > On Wed, 29 Jul 2020, Patrick Palka wrote: > >> In the testcase below, template argument deduction for the call >> g(id<int>) goes wrong because the functions in the overload set id<int> >> each have a yet-undeduced auto return type, and this undeduced return >> type makes try_one_overload fail to match up any of these functions with >> g's parameter type, leading to g's template parameter going undeduced >> and to the overload set going unresolved. >> >> This patch fixes this issue by performing return type deduction via >> instantiation before doing try_one_overload, in a manner similar to what >> resolve_address_of_overloaded_function does. >> >> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to >> commit? >> >> gcc/cp/ChangeLog: >> >> PR c++/64194 >> * pt.c (resolve_overloaded_unification): If the function >> template specialization has a placeholder return type, >> then instantiate it before attempting unification. >> >> gcc/testsuite/ChangeLog: >> >> PR c++/64194 >> * g++.dg/cpp1y/auto-fn60.C: New test. >> --- >> gcc/cp/pt.c | 11 ++++++++++- >> gcc/testsuite/g++.dg/cpp1y/auto-fn60.C | 11 +++++++++++ >> 2 files changed, 21 insertions(+), 1 deletion(-) >> create mode 100644 gcc/testsuite/g++.dg/cpp1y/auto-fn60.C >> >> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c >> index 4d955c555dc..abb74520fc9 100644 >> --- a/gcc/cp/pt.c >> +++ b/gcc/cp/pt.c >> @@ -22118,7 +22118,16 @@ resolve_overloaded_unification (tree tparms, >> if (subargs != error_mark_node >> && !any_dependent_template_arguments_p (subargs)) >> { >> - elem = TREE_TYPE (instantiate_template (fn, subargs, tf_none)); >> + fn = instantiate_template (fn, subargs, tf_none); >> + if (undeduced_auto_decl (fn)) >> + { >> + /* Instantiate the function to deduce its return type. */ >> + ++function_depth; >> + instantiate_decl (fn, /*defer*/false, /*class*/false); >> + --function_depth; >> + } >> + >> + elem = TREE_TYPE (fn); >> if (try_one_overload (tparms, targs, tempargs, parm, >> elem, strict, sub_strict, addr_p, explain_p) >> && (!goodfn || !same_type_p (goodfn, elem))) >> diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C >> new file mode 100644 >> index 00000000000..237868c076b >> --- /dev/null >> +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C >> @@ -0,0 +1,11 @@ >> +// PR c++/64194 >> +// { dg-do compile { target c++14 } } >> + >> +template <typename T> void g(void (*)(T)) { } >> + >> +template <typename T> auto id(int) { } >> +template <typename T> auto id(char) { return 0; } >> + >> +int main() { >> + g(id<void>); > > Oops, this is supposed to use id<int> instead of id<void> to match up > with the commit message (or vice versa). OK. Jason
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4d955c555dc..abb74520fc9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -22118,7 +22118,16 @@ resolve_overloaded_unification (tree tparms, if (subargs != error_mark_node && !any_dependent_template_arguments_p (subargs)) { - elem = TREE_TYPE (instantiate_template (fn, subargs, tf_none)); + fn = instantiate_template (fn, subargs, tf_none); + if (undeduced_auto_decl (fn)) + { + /* Instantiate the function to deduce its return type. */ + ++function_depth; + instantiate_decl (fn, /*defer*/false, /*class*/false); + --function_depth; + } + + elem = TREE_TYPE (fn); if (try_one_overload (tparms, targs, tempargs, parm, elem, strict, sub_strict, addr_p, explain_p) && (!goodfn || !same_type_p (goodfn, elem))) diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C new file mode 100644 index 00000000000..237868c076b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn60.C @@ -0,0 +1,11 @@ +// PR c++/64194 +// { dg-do compile { target c++14 } } + +template <typename T> void g(void (*)(T)) { } + +template <typename T> auto id(int) { } +template <typename T> auto id(char) { return 0; } + +int main() { + g(id<void>); +}