Skip to content

Commit

Permalink
Merge pull request #7584 from ntrel/count-args
Browse files Browse the repository at this point in the history
 Fix Issue 16165 - Show expected number of function arguments on mismatch
  • Loading branch information
thewilsonator committed Dec 1, 2018
2 parents 7bb8cb8 + bff6a03 commit f35640a
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 39 deletions.
44 changes: 38 additions & 6 deletions src/dmd/mtype.d
Expand Up @@ -4529,6 +4529,15 @@ extern (C++) final class TypeFunction : TypeNext
return buf.extractString();
}

private extern(D) const(char)* getMatchError(A...)(const(char)* format, A args)
{
if (global.gag && !global.params.showGaggedErrors)
return null;
OutBuffer buf;
buf.printf(format, args);
return buf.extractString();
}

/********************************
* 'args' are being matched to function 'this'
* Determine match level.
Expand Down Expand Up @@ -4575,13 +4584,15 @@ extern (C++) final class TypeFunction : TypeNext

size_t nparams = Parameter.dim(parameters);
size_t nargs = args ? args.dim : 0;
if (nparams == nargs)
{
}
else if (nargs > nparams)
if (nargs > nparams)
{
if (varargs == 0)
goto Nomatch;
{
// suppress early exit if an error message is wanted,
// so we can check any matching args are valid
if (!pMessage)
goto Nomatch;
}
// too many args; no match
match = MATCH.convert; // match ... with a "conversion" match level
}
Expand Down Expand Up @@ -4629,8 +4640,8 @@ extern (C++) final class TypeFunction : TypeNext
{
if (p.defaultArg)
continue;
goto L1;
// try typesafe variadics
goto L1;
}
{
Expression arg = (*args)[u];
Expand Down Expand Up @@ -4748,7 +4759,19 @@ extern (C++) final class TypeFunction : TypeNext
tsa = cast(TypeSArray)tb;
sz = tsa.dim.toInteger();
if (sz != nargs - u)
{
if (pMessage)
// Windows (Vista) OutBuffer.vprintf issue? 2nd argument always zero
//*pMessage = getMatchError("expected %d variadic argument(s), not %d", sz, nargs - u);
if (!global.gag || global.params.showGaggedErrors)
{
OutBuffer buf;
buf.printf("expected %d variadic argument(s)", sz);
buf.printf(", not %d", nargs - u);
*pMessage = buf.extractString();
}
goto Nomatch;
}
goto case Tarray;
case Tarray:
{
Expand Down Expand Up @@ -4799,13 +4822,22 @@ extern (C++) final class TypeFunction : TypeNext
}
if (pMessage && u < nargs)
*pMessage = getParamError((*args)[u], p);
else if (pMessage)
*pMessage = getMatchError("missing argument for parameter #%d: `%s`",
u + 1, parameterToChars(p, this, false));
goto Nomatch;
}
if (m < match)
match = m; // pick worst match
}

Ldone:
if (pMessage && !varargs && nargs > nparams)
{
// all parameters had a match, but there are surplus args
*pMessage = getMatchError("expected %d argument(s), not %d", nparams, nargs);
goto Nomatch;
}
//printf("match = %d\n", match);
return match;

Expand Down
18 changes: 18 additions & 0 deletions test/fail_compilation/bug16165.d
@@ -0,0 +1,18 @@
void f(int x, Object y);

void g()
{
Object o;
f(o, o, 404);
f(5, 6, 404);
}

/*
TEST_OUTPUT:
---
fail_compilation/bug16165.d(6): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(Object, Object, int)`
fail_compilation/bug16165.d(6): cannot pass argument `o` of type `object.Object` to parameter `int x`
fail_compilation/bug16165.d(7): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(int, int, int)`
fail_compilation/bug16165.d(7): cannot pass argument `6` of type `int` to parameter `Object y`
---
*/
47 changes: 24 additions & 23 deletions test/fail_compilation/diag8101.d
@@ -1,29 +1,30 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag8101.d(56): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
fail_compilation/diag8101.d(57): Error: none of the overloads of `f_1` are callable using argument types `()`, candidates are:
fail_compilation/diag8101.d(32): `diag8101.f_1(int)`
fail_compilation/diag8101.d(33): `diag8101.f_1(int, int)`
fail_compilation/diag8101.d(58): Error: none of the overloads of `f_2` are callable using argument types `()`, candidates are:
fail_compilation/diag8101.d(35): `diag8101.f_2(int)`
fail_compilation/diag8101.d(36): `diag8101.f_2(int, int)`
fail_compilation/diag8101.d(37): `diag8101.f_2(int, int, int)`
fail_compilation/diag8101.d(38): `diag8101.f_2(int, int, int, int)`
fail_compilation/diag8101.d(39): `diag8101.f_2(int, int, int, int, int)`
fail_compilation/diag8101.d(58): ... (1 more, -v to show) ...
fail_compilation/diag8101.d(60): Error: template `diag8101.t_0` cannot deduce function from argument types `!()()`, candidates are:
fail_compilation/diag8101.d(42): `diag8101.t_0(T1)()`
fail_compilation/diag8101.d(61): Error: template `diag8101.t_1` cannot deduce function from argument types `!()()`, candidates are:
fail_compilation/diag8101.d(44): `diag8101.t_1(T1)()`
fail_compilation/diag8101.d(45): `diag8101.t_1(T1, T2)()`
fail_compilation/diag8101.d(62): Error: template `diag8101.t_2` cannot deduce function from argument types `!()()`, candidates are:
fail_compilation/diag8101.d(47): `diag8101.t_2(T1)()`
fail_compilation/diag8101.d(48): `diag8101.t_2(T1, T2)()`
fail_compilation/diag8101.d(49): `diag8101.t_2(T1, T2, T3)()`
fail_compilation/diag8101.d(50): `diag8101.t_2(T1, T2, T3, T4)()`
fail_compilation/diag8101.d(51): `diag8101.t_2(T1, T2, T3, T4, T5)()`
fail_compilation/diag8101.d(62): ... (1 more, -v to show) ...
fail_compilation/diag8101.d(57): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
fail_compilation/diag8101.d(57): missing argument for parameter #1: `int`
fail_compilation/diag8101.d(58): Error: none of the overloads of `f_1` are callable using argument types `()`, candidates are:
fail_compilation/diag8101.d(33): `diag8101.f_1(int)`
fail_compilation/diag8101.d(34): `diag8101.f_1(int, int)`
fail_compilation/diag8101.d(59): Error: none of the overloads of `f_2` are callable using argument types `()`, candidates are:
fail_compilation/diag8101.d(36): `diag8101.f_2(int)`
fail_compilation/diag8101.d(37): `diag8101.f_2(int, int)`
fail_compilation/diag8101.d(38): `diag8101.f_2(int, int, int)`
fail_compilation/diag8101.d(39): `diag8101.f_2(int, int, int, int)`
fail_compilation/diag8101.d(40): `diag8101.f_2(int, int, int, int, int)`
fail_compilation/diag8101.d(59): ... (1 more, -v to show) ...
fail_compilation/diag8101.d(61): Error: template `diag8101.t_0` cannot deduce function from argument types `!()()`, candidates are:
fail_compilation/diag8101.d(43): `diag8101.t_0(T1)()`
fail_compilation/diag8101.d(62): Error: template `diag8101.t_1` cannot deduce function from argument types `!()()`, candidates are:
fail_compilation/diag8101.d(45): `diag8101.t_1(T1)()`
fail_compilation/diag8101.d(46): `diag8101.t_1(T1, T2)()`
fail_compilation/diag8101.d(63): Error: template `diag8101.t_2` cannot deduce function from argument types `!()()`, candidates are:
fail_compilation/diag8101.d(48): `diag8101.t_2(T1)()`
fail_compilation/diag8101.d(49): `diag8101.t_2(T1, T2)()`
fail_compilation/diag8101.d(50): `diag8101.t_2(T1, T2, T3)()`
fail_compilation/diag8101.d(51): `diag8101.t_2(T1, T2, T3, T4)()`
fail_compilation/diag8101.d(52): `diag8101.t_2(T1, T2, T3, T4, T5)()`
fail_compilation/diag8101.d(63): ... (1 more, -v to show) ...
---
*/

Expand Down
3 changes: 2 additions & 1 deletion test/fail_compilation/diag9420.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT
---
fail_compilation/diag9420.d(20): Error: function `diag9420.S.t3!().tx()` is not callable using argument types `(int)`
fail_compilation/diag9420.d(21): Error: function `diag9420.S.t3!().tx()` is not callable using argument types `(int)`
fail_compilation/diag9420.d(21): expected 0 argument(s), not 1
---
*/

Expand Down
45 changes: 43 additions & 2 deletions test/fail_compilation/fail332.d
@@ -1,15 +1,56 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail332.d(14): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `()`
fail_compilation/fail332.d(22): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `()`
fail_compilation/fail332.d(22): missing argument for parameter #1: `int _param_0`
fail_compilation/fail332.d(23): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `(typeof(null))`
fail_compilation/fail332.d(23): cannot pass argument `null` of type `typeof(null)` to parameter `int _param_0`
fail_compilation/fail332.d(25): Error: function `fail332.baz(int[] _param_0...)` is not callable using argument types `(string)`
fail_compilation/fail332.d(25): cannot pass argument `""` of type `string` to parameter `int[] _param_0...`
fail_compilation/fail332.d(26): Error: function `fail332.baz(int[] _param_0...)` is not callable using argument types `(int, typeof(null))`
fail_compilation/fail332.d(26): cannot pass argument `null` of type `typeof(null)` to parameter `int[] _param_0...`
---
*/

import core.vararg;

void foo(int, ...) {}
void baz(int[]...) {}

void bar()
void test()
{
foo();
foo(null);

baz("");
baz(3, null);
}

/*
TEST_OUTPUT:
---
fail_compilation/fail332.d(50): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `()`
fail_compilation/fail332.d(50): missing argument for parameter #1: `Object`
fail_compilation/fail332.d(51): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(int)`
fail_compilation/fail332.d(51): cannot pass argument `4` of type `int` to parameter `Object`
fail_compilation/fail332.d(52): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null))`
fail_compilation/fail332.d(52): expected 2 variadic argument(s), not 0
fail_compilation/fail332.d(53): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int)`
fail_compilation/fail332.d(53): expected 2 variadic argument(s), not 1
fail_compilation/fail332.d(54): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, string)`
fail_compilation/fail332.d(54): cannot pass argument `""` of type `string` to parameter `int[2]...`
fail_compilation/fail332.d(55): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, int, int)`
fail_compilation/fail332.d(55): expected 2 variadic argument(s), not 3
---
*/
void bar(Object, int[2]...);

void test2()
{
bar();
bar(4);
bar(null);
bar(null, 2);
bar(null, 2, "");
bar(null, 2,3,4);
}
3 changes: 2 additions & 1 deletion test/fail_compilation/fail99.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail99.d(12): Error: delegate `dg(int)` is not callable using argument types `()`
fail_compilation/fail99.d(13): Error: delegate `dg(int)` is not callable using argument types `()`
fail_compilation/fail99.d(13): missing argument for parameter #1: `int`
---
*/

Expand Down
3 changes: 2 additions & 1 deletion test/fail_compilation/ice10922.d
@@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice10922.d(9): Error: function `ice10922.__lambda4(const(uint) n)` is not callable using argument types `()`
fail_compilation/ice10922.d(10): Error: function `ice10922.__lambda4(const(uint) n)` is not callable using argument types `()`
fail_compilation/ice10922.d(10): missing argument for parameter #1: `const(uint) n`
---
*/

Expand Down
8 changes: 5 additions & 3 deletions test/fail_compilation/ice12501.d
@@ -1,9 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice12501.d(29): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
fail_compilation/ice12501.d(29): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
fail_compilation/ice12501.d(43): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
fail_compilation/ice12501.d(31): expected 1 argument(s), not 2
fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
fail_compilation/ice12501.d(31): expected 1 argument(s), not 2
fail_compilation/ice12501.d(45): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
---
*/

Expand Down
5 changes: 3 additions & 2 deletions test/fail_compilation/ice9540.d
@@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice9540.d(34): Error: function `ice9540.A.test.AddFront!(this, f).AddFront.dg(int _param_0)` is not callable using argument types `()`
fail_compilation/ice9540.d(25): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
fail_compilation/ice9540.d(35): Error: function `ice9540.A.test.AddFront!(this, f).AddFront.dg(int _param_0)` is not callable using argument types `()`
fail_compilation/ice9540.d(35): missing argument for parameter #1: `int _param_0`
fail_compilation/ice9540.d(26): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
---
*/

Expand Down

0 comments on commit f35640a

Please sign in to comment.