On Mon, Jan 18, 2016 at 10:34 AM, Jason Merrill <ja...@redhat.com> wrote: > On 12/25/2015 12:37 PM, Patrick Palka wrote: >> >> That alone would not be sufficient because more_specialized_fn() >> doesn't call maybe_adjust_types_for_deduction() beforehand, yet we >> have to do the decaying there too (and on both types, not just one of >> them). >> >> And maybe_adjust_types_for_deduction() seems to operate on the >> presumption that one type is the parameter type and one is the >> argument type. But in more_specialized_fn() and in get_bindings() we >> are really working with two parameter types and have to decay them >> both. So sometimes we have to decay one of the types that are >> eventually going to get passed to unify(), and other times we want to >> decay both types that are going to get passed to unify(). >> maybe_adjust_types_for_deduction() seems to only expect the former >> case. >> >> Finally, maybe_adjust_types_for_deduction() is not called when >> unifying a nested function declarator (because it is guarded by the >> subr flag in unify_one_argument), so doing it there we would also >> regress in the following test case: > > > Ah, that makes sense. > > How about keeping the un-decayed type in the PARM_DECLs, so that we get the > substitution failure in instantiate_template, but having the decayed type in > the TYPE_ARG_TYPES, probably by doing the decay in grokparms, so it's > already decayed when we're doing unification?
I just tried this, and it works well! With this approach, all but one of the test cases pass. The failing test case is unify17.C: -- 8< -- void foo (int *); template <typename T> void bar (void (T[5])); // { dg-error "array of 'void'" } void baz (void) { bar<void> (0); // { dg-error "no matching function" } } -- 8< -- Here, we don't get a substitution failure because we don't have a corresponding FUNCTION_DECL for the nested function specifier, only a FUNCTION_TYPE. So there is no PARM_DECL to recurse into during substitution, that retains the un-decayed argument type "T[5]" of the nested function specifier. I'm not yet sure how to work around this...