On Thu, 2025-01-09 at 21:15 -0500, Jason Merrill wrote:
> On 1/9/25 7:00 PM, David Malcolm wrote:
> > On Thu, 2025-01-09 at 14:21 -0500, Jason Merrill wrote:
> >
> > Thanks for taking a look...
> >
> > > > On 1/9/25 2:11 PM, David Malcolm wrote:
> > > >
> > > > @@ -4743,7 +4769,38 @@ convert_arguments (tree typelist,
> > > > vec<tree,
> > > > va_gc> **values, tree fndecl,
> > > > if (typetail && typetail != void_list_node)
> > > > {
> > > > if (complain & tf_error)
> > > > - error_args_num (input_location, fndecl,
> > > > /*too_many_p=*/false);
> > > > + {
> > > > + /* Not enough args.
> > > > + Determine minimum number of arguments
> > > > required. */
> > > > + int min_expected_num = 0;
> > > > + bool at_least_p = false;
> > > > + tree iter = typelist;
> > > > + while (true)
> > > > + {
> > > > + if (!iter)
> > > > + {
> > > > + /* Variadic arguments; stop iterating.
> > > > */
> > > > + at_least_p = true;
> > > > + break;
> > > > + }
> > > > + if (iter == void_list_node)
> > > > + /* End of arguments; stop iterating. */
> > > > + break;
> > > > + if (fndecl && TREE_PURPOSE (iter)
> > > > + && TREE_CODE (TREE_PURPOSE (iter)) !=
> > > > DEFERRED_PARSE)
> > > >
> > >
> > > Why are you checking DEFERRED_PARSE? That indicates a default
> > > argument,
> > > even if it isn't parsed yet. For that case we should get the
> > > error
> > > in
> > > convert_default_arg rather than pretend there's no default
> > > argument.
> >
> > I confess that the check for DEFERRED_PARSE was a rather mindless
> > copy
> > and paste by me from the "See if there are default arguments that
> > can be
> > used" logic earlier in the function.
> >
> > I've removed it in the latest version of the patch.
> >
> > > > + {
> > > > + /* Found a default argument; skip this
> > > > one when
> > > > + counting minimum required. */
> > > > + at_least_p = true;
> > > > + iter = TREE_CHAIN (iter);
> > > > + continue;
> > >
> > > We could break here, once you have a default arg the rest of the
> > > parms
> > > need to have them as well.
> >
> > Indeed; I've updated this in the latest version of the patch, so
> > we break out as soon as we see an arg with a non-null TREE_PURPOSE.
> >
> > >
> > > > + }
> > > > + ++min_expected_num;
> > > > + iter = TREE_CHAIN (iter);
> > > > + }
> > > > + error_args_num (input_location, fndecl,
> > > > + min_expected_num, actual_num,
> > > > at_least_p);
> > > > + }
> > > > return -1;
> > > > }
> >
> > Here's a v3 version of the patch, which is currently going through
> > my tester.
> >
> > OK for trunk if it passes bootstrap®rtesting?
>
> OK.
Thanks. However, it turns out that I may have misspoke, and the v2
patch might have been the correct approach: if we bail out on the first
arg with a TREE_PURPOSE then in
gcc/testsuite/g++.dg/cpp0x/variadic169.C
1 │ // DR 2233
2 │ // { dg-do compile { target c++11 } }
3 │
4 │ template<typename ...T> void f(int n = 0, T ...t);
5 │
6 │ int main()
7 │ {
8 │ f<int>(); // { dg-error "too few arguments to
function '\[^\n\r\]*'; expected at least 1, have 0" }
9 │ }
we instead emit the nonsensical "expected at least 0, have 0":
error: too few arguments to function ‘void f(int, T ...) [with T =
{int}]’; expected at least 0, have 0
8 | f<int>(); // { dg-error "too few
arguments to function '\[^\n\r\]*'; expected at least 1, have 0" }
| ~~~~~~^~
../../src/gcc/testsuite/g++.dg/cpp0x/variadic169.C:4:30: note: declared
here
4 | template<typename ...T> void f(int n = 0, T ...t);
| ^
whereas with the v2 patch we count the trailing arg after the default
arg, and we emit "expected at least 1, have 0", which seems correct to
me.
I'm testing a version of the patch that continues to iterate after a
TREE_PURPOSE (as v2, but but dropping the check on DEFERRED_PARSE).
Thanks
Dave