Skip to content

Commit

Permalink
fix Issue 10249 - incorrect mangling for overloaded symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Jun 9, 2013
1 parent 44fdd81 commit a15428c
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 25 deletions.
3 changes: 2 additions & 1 deletion src/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ class FuncDeclaration : public Declaration
void appendExp(Expression *e);
void appendState(Statement *s);
const char *mangle(bool isv = false);
const char *mangleExact(bool isv = false);
const char *toPrettyChars();
const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure'
bool isMain();
Expand Down Expand Up @@ -754,7 +755,7 @@ class FuncAliasDeclaration : public FuncDeclaration
FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
const char *kind();
Symbol *toSymbol();
const char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); }
const char *mangle(bool isv = false);

FuncDeclaration *toAliasFunc();
};
Expand Down
3 changes: 3 additions & 0 deletions src/dsymbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,10 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
*/
if (s2->isOverloadable() && (a || s->isOverloadable()))
{ if (!a)
{
a = new OverloadSet(s->ident);
a->parent = this;
}
/* Don't add to a[] if s2 is alias of previous sym
*/
for (size_t j = 0; j < a->a.dim; j++)
Expand Down
21 changes: 16 additions & 5 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -7216,15 +7216,26 @@ Expression *DotIdExp::semanticX(Scope *sc)
Dsymbol *ds;
switch (e1->op)
{
case TOKimport: ds = ((ScopeExp *)e1)->sds; goto L1;
case TOKvar: ds = ((VarExp *)e1)->var; goto L1;
case TOKdotvar: ds = ((DotVarExp *)e1)->var; goto L1;
default: break;
L1:
case TOKimport:
ds = ((ScopeExp *)e1)->sds;
goto L1;
case TOKvar:
ds = ((VarExp *)e1)->var;
goto L1;
case TOKdotvar:
ds = ((DotVarExp *)e1)->var;
goto L1;
case TOKoverloadset:
ds = ((OverExp *)e1)->vars;
L1:
{
const char* s = ds->mangle();
e = new StringExp(loc, (void*)s, strlen(s), 'c');
e = e->semantic(sc);
return e;
}
default:
break;
}
}

Expand Down
24 changes: 19 additions & 5 deletions src/func.c
Original file line number Diff line number Diff line change
Expand Up @@ -1929,14 +1929,28 @@ bool FuncDeclaration::equals(Object *o)
Dsymbol *s = isDsymbol(o);
if (s)
{
FuncDeclaration *fd1 = this->toAliasFunc();
FuncDeclaration *fd1 = this;
FuncDeclaration *fd2 = s->isFuncDeclaration();
if (fd2)
if (!fd2)
return false;

FuncAliasDeclaration *fa1 = fd1->isFuncAliasDeclaration();
FuncAliasDeclaration *fa2 = fd2->isFuncAliasDeclaration();
if (fa1 && fa2)
{
fd2 = fd2->toAliasFunc();
return fd1->toParent()->equals(fd2->toParent()) &&
fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type);
return fa1->toAliasFunc()->equals(fa2->toAliasFunc()) &&
fa1->hasOverloads == fa2->hasOverloads;
}

if (fa1 && (fd1 = fa1->toAliasFunc())->isUnique() && !fa1->hasOverloads)
fa1 = NULL;
if (fa2 && (fd2 = fa2->toAliasFunc())->isUnique() && !fa2->hasOverloads)
fa2 = NULL;
if ((fa1 != NULL) != (fa2 != NULL))
return false;

return fd1->toParent()->equals(fd2->toParent()) &&
fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type);
}
return false;
}
Expand Down
44 changes: 44 additions & 0 deletions src/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,49 @@ const char *Declaration::mangle(bool isv)
return p;
}

/******************************************************************************
* Normally FuncDeclaration and FuncAliasDeclaration have overloads.
* If and only if there is no overloads, mangle() could return
* exact mangled name.
*
* module test;
* void foo(long) {} // _D4test3fooFlZv
* void foo(string) {} // _D4test3fooFAyaZv
*
* // from FuncDeclaration::mangle().
* pragma(msg, foo.mangleof); // prints unexact mangled name "4test3foo"
* // by calling Dsymbol::mangle()
*
* // from FuncAliasDeclaration::mangle()
* pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof); // "_D4test3fooFlZv"
* pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof); // "_D4test3fooFAyaZv"
*
* If a function has no overloads, .mangleof property still returns exact mangled name.
*
* void bar() {}
* pragma(msg, bar.mangleof); // still prints "_D4test3barFZv"
* // by calling FuncDeclaration::mangleExact().
*/
const char *FuncDeclaration::mangle(bool isv)
{
return isUnique() ? mangleExact(isv) : Dsymbol::mangle(isv);
}
// ditto
const char *FuncAliasDeclaration::mangle(bool isv)
{
FuncDeclaration *f = toAliasFunc();
FuncAliasDeclaration *fa = f->isFuncAliasDeclaration();
if (!hasOverloads && !fa)
return f->mangleExact(isv);
if (fa)
return fa->mangle(isv);
return Dsymbol::mangle(isv);
}

/******************************************************************************
* Returns exact mangled name of function.
*/
const char *FuncDeclaration::mangleExact(bool isv)
#if __DMC__
__out(result)
{
Expand All @@ -173,6 +215,8 @@ const char *FuncDeclaration::mangle(bool isv)
__body
#endif
{
assert(!isFuncAliasDeclaration());

if (mangleOverride)
return mangleOverride;

Expand Down
29 changes: 17 additions & 12 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,14 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
{
if (s2)
{
FuncAliasDeclaration *fa1 = s1->isFuncAliasDeclaration();
if (fa1)
s1 = fa1->toAliasFunc();
FuncAliasDeclaration *fa2 = s2->isFuncAliasDeclaration();
if (fa2)
s2 = fa2->toAliasFunc();
if (!s1->equals(s2) || s1->parent != s2->parent)
if (!s1->equals(s2))
goto Lnomatch;
if (s1->parent != s2->parent &&
!s1->isFuncDeclaration() &&
!s2->isFuncDeclaration())
{
goto Lnomatch;
}
}
else
goto Lnomatch;
Expand Down Expand Up @@ -5642,6 +5642,16 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
j--;
continue;
}
if (FuncAliasDeclaration *fa = sa->isFuncAliasDeclaration())
{
FuncDeclaration *f = fa->toAliasFunc();
if (!fa->hasOverloads && f->isUnique())
{
// Strip FuncAlias only when the aliased function
// does not have any overloads.
sa = f;
}
}
(*tiargs)[j] = sa;

TemplateDeclaration *td = sa->isTemplateDeclaration();
Expand Down Expand Up @@ -6156,11 +6166,6 @@ Identifier *TemplateInstance::genIdent(Objects *args)
Lsa2:
if (d && (!d->type || !d->type->deco))
{
FuncAliasDeclaration *fad = d->isFuncAliasDeclaration();
if (fad)
{ d = fad->toAliasFunc();
goto Lsa2;
}
error("forward reference of %s %s", d->kind(), d->toChars());
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/tocsym.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ Symbol *FuncDeclaration::toSymbol()
#if 0
id = ident->toChars();
#else
id = mangle();
id = mangleExact();
#endif
//printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
//printf("\tid = '%s'\n", id);
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/diag6539.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag6539.d(21): Error: overloadset Rectangle is used as a type
fail_compilation/diag6539.d(21): Error: overloadset diag6539.Rectangle is used as a type
---
*/

Expand Down
36 changes: 36 additions & 0 deletions test/runnable/template9.d
Original file line number Diff line number Diff line change
Expand Up @@ -2402,6 +2402,42 @@ template b10134()

pragma(msg, getResultType10134!(a10134!()));

/******************************************/
// 10249

template Seq10249(T...) { alias Seq10249 = T; }

mixin template Func10249(T)
{
void func10249(T) {}
}
mixin Func10249!long;
mixin Func10249!string;

void f10249(long) {}

class C10249
{
mixin Func10249!long;
mixin Func10249!string;
static assert(Seq10249!(.func10249)[0].mangleof == "7breaker9func10249"); // <- 9func10249
static assert(Seq10249!( func10249)[0].mangleof == "7breaker6C102499func10249"); // <- 9func10249

static: // necessary to make overloaded symbols accessible via __traits(getOverloads, C10249)
void foo(long) {}
void foo(string) {}
static assert(Seq10249!(foo)[0].mangleof == "7breaker6C102493foo"); // <- _D7breaker6C102493fooFlZv
static assert(Seq10249!(__traits(getOverloads, C10249, "foo"))[0].mangleof == "_D7breaker6C102493fooFlZv"); // <-
static assert(Seq10249!(__traits(getOverloads, C10249, "foo"))[1].mangleof == "_D7breaker6C102493fooFAyaZv"); // <-

void g(string) {}
alias bar = .f10249;
alias bar = g;
static assert(Seq10249!(bar)[0].mangleof == "7breaker6C102496f10249"); // <- _D7breaker1fFlZv (todo!)
static assert(Seq10249!(__traits(getOverloads, C10249, "bar"))[0].mangleof == "_D7breaker6f10249FlZv"); // <-
static assert(Seq10249!(__traits(getOverloads, C10249, "bar"))[1].mangleof == "_D7breaker6C102491gFAyaZv"); // <-
}

/******************************************/

int main()
Expand Down

0 comments on commit a15428c

Please sign in to comment.