Skip to content

Commit

Permalink
Merge pull request #3508 from AndrejMitrovic/Fix8101
Browse files Browse the repository at this point in the history
Issue 8101 - Display candidate function overloads when function call fails.
  • Loading branch information
WalterBright committed May 2, 2014
2 parents e389d1c + 94eb614 commit 58445fb
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 25 deletions.
139 changes: 117 additions & 22 deletions src/func.c
Expand Up @@ -3044,6 +3044,100 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
return MATCHnomatch;
}

/// Walk through candidate template overloads and print them in the diagnostics.
struct TemplateCandidateWalker
{
Loc loc;
int numToDisplay; // max num of overloads to print (-v overrides this).

/// Count template overloads.
struct CountWalker
{
int numOverloads;

static int fp(void *param, Dsymbol *s)
{
CountWalker *p = (CountWalker *)param;
++(p->numOverloads);
return 0;
}
};

static int fp(void *param, Dsymbol *s)
{
TemplateDeclaration *t = s->isTemplateDeclaration();
if (!t) return 0;

TemplateCandidateWalker *p = (TemplateCandidateWalker *)param;

::errorSupplemental(t->loc, "%s", t->toPrettyChars());

if (!global.params.verbose && --(p->numToDisplay) == 0 && t->overnext)
{
// Too many overloads to sensibly display.
// Just show count of remaining overloads.
CountWalker cw;
cw.numOverloads = 0;
overloadApply(t->overnext, &cw, &CountWalker::fp);

if (cw.numOverloads > 0)
::errorSupplemental(p->loc, "... (%d more, -v to show) ...", cw.numOverloads);

return 1; // stop iterating
}

return 0;
}
};

/// Walk through candidate template overloads and print them in the diagnostics.
struct FuncCandidateWalker
{
Loc loc;
int numToDisplay; // max num of overloads to print (-v overrides this).

/// Count function overloads.
struct CountWalker
{
int numOverloads;

static int fp(void *param, Dsymbol *s)
{
CountWalker *p = (CountWalker *)param;

if (s->isFuncDeclaration())
++(p->numOverloads);

return 0;
}
};

static int fp(void *param, Dsymbol *s)
{
FuncDeclaration *f = s->isFuncDeclaration();
if (!f) return 0;

FuncCandidateWalker *p = (FuncCandidateWalker *)param;

::errorSupplemental(f->loc, "%s%s", f->toPrettyChars(),
Parameter::argsTypesToChars(((TypeFunction *)f->type)->parameters, ((TypeFunction *)f->type)->varargs));

if (!global.params.verbose && --(p->numToDisplay) == 0 && f->overnext)
{
CountWalker cw;
cw.numOverloads = 0;
overloadApply(f->overnext, &cw, &CountWalker::fp);

if (cw.numOverloads > 0)
::errorSupplemental(p->loc, "... (%d more, -v to show) ...", cw.numOverloads);

return 1; // stop iterating
}

return 0;
}
};

/*******************************************
* Given a symbol that could be either a FuncDeclaration or
* a function template, resolve it to a function symbol.
Expand Down Expand Up @@ -3144,51 +3238,52 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
if (tthis)
tthis->modToBuffer(&fargsBuf);

const int numOverloadsDisplay = 5; // sensible number to display

if (!m.lastf && !(flags & 1)) // no match
{
if (td && !fd) // all of overloads are template
if (td && !fd) // all of overloads are templates
{
::error(loc, "%s %s.%s cannot deduce function from argument types !(%s)%s, candidates are:",
td->kind(), td->parent->toPrettyChars(), td->ident->toChars(),
tiargsBuf.peekString(), fargsBuf.peekString());

// Display candidate template functions
int numToDisplay = 5; // sensible number to display
for (TemplateDeclaration *tdx = td; tdx; tdx = tdx->overnext)
{
::errorSupplemental(tdx->loc, "%s", tdx->toPrettyChars());
if (!global.params.verbose && --numToDisplay == 0 && tdx->overnext)
{
// Too many overloads to sensibly display.
// Just show count of remaining overloads.
int remaining = 0;
for (TemplateDeclaration *tdy = tdx->overnext; tdy; tdy = tdy->overnext)
++remaining;
if (remaining > 0)
::errorSupplemental(loc, "... (%d more, -v to show) ...", remaining);
break;
}
}
// Display candidate templates (even if there are no multiple overloads)
TemplateCandidateWalker tcw;
tcw.loc = loc;
tcw.numToDisplay = numOverloadsDisplay;
overloadApply(td, &tcw, &TemplateCandidateWalker::fp);
}
else
{
assert(fd);

const char *trailMsg = (fd->overnext != NULL) ? ", candidates are:" : "";
TypeFunction *tf = (TypeFunction *)fd->type;
if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch
{
OutBuffer thisBuf, funcBuf;
MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod);
MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod);
::error(loc, "%smethod %s is not callable using a %sobject",
funcBuf.peekString(), fd->toPrettyChars(), thisBuf.peekString());
::error(loc, "%smethod %s is not callable using a %sobject%s",
funcBuf.peekString(), fd->toPrettyChars(), thisBuf.peekString(), trailMsg);
}
else
{
//printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
fd->error(loc, "%s%s is not callable using argument types %s",
fd->error(loc, "%s%s is not callable using argument types %s%s",
Parameter::argsTypesToChars(tf->parameters, tf->varargs),
tf->modToChars(),
fargsBuf.peekString());
fargsBuf.peekString(), trailMsg);
}

// Display candidate functions (only when there are multiple overloads)
if (fd->overnext)
{
FuncCandidateWalker fcw;
fcw.loc = loc;
fcw.numToDisplay = numOverloadsDisplay;
overloadApply(fd, &fcw, &FuncCandidateWalker::fp);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions test/fail_compilation/diag10415.d
@@ -1,8 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag10415.d(34): Error: function diag10415.C.x () const is not callable using argument types (int) const
fail_compilation/diag10415.d(37): Error: d.x is not an lvalue
fail_compilation/diag10415.d(36): Error: function diag10415.C.x () const is not callable using argument types (int) const, candidates are:
fail_compilation/diag10415.d(13): diag10415.C.x()
fail_compilation/diag10415.d(18): diag10415.C.x(int _param_0)
fail_compilation/diag10415.d(39): Error: d.x is not an lvalue
---
*/

Expand Down
4 changes: 3 additions & 1 deletion test/fail_compilation/diag11078.d
@@ -1,7 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag11078.d(17): Error: function diag11078.S1.value () is not callable using argument types (double)
fail_compilation/diag11078.d(19): Error: function diag11078.S1.value () is not callable using argument types (double), candidates are:
fail_compilation/diag11078.d(12): diag11078.S1.value()
fail_compilation/diag11078.d(13): diag11078.S1.value(int n)
---
*/

Expand Down
63 changes: 63 additions & 0 deletions test/fail_compilation/diag8101.d
@@ -0,0 +1,63 @@
/*
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: function diag8101.f_1 (int) is not 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: function diag8101.f_2 (int) is not 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) ...
---
*/

void f_0(int);

void f_1(int);
void f_1(int, int);

void f_2(int);
void f_2(int, int);
void f_2(int, int, int);
void f_2(int, int, int, int);
void f_2(int, int, int, int, int);
void f_2(int, int, int, int, int, int);

void t_0(T1)();

void t_1(T1)();
void t_1(T1, T2)();

void t_2(T1)();
void t_2(T1, T2)();
void t_2(T1, T2, T3)();
void t_2(T1, T2, T3, T4)();
void t_2(T1, T2, T3, T4, T5)();
void t_2(T1, T2, T3, T4, T5, T6)();

void main()
{
f_0();
f_1();
f_2();

t_0();
t_1();
t_2();
}

0 comments on commit 58445fb

Please sign in to comment.