Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 13783 - Function overload with rvalue inout parameter not selected when enum parameter implicitly converted to its base type #4177

Merged
1 commit merged into from Dec 6, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 20 additions & 23 deletions src/mtype.c
Expand Up @@ -5831,30 +5831,30 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
// Non-lvalues do not match ref or out parameters
if (p->storageClass & STCref)
{
Type *targb = targ->toBasetype();
Type *tprmb = tprm->toBasetype();
//printf("%s\n", targb->toChars());
//printf("%s\n", tprmb->toChars());
// Bugzilla 13783: Don't use toBasetype() to handle enum types.
Type *ta = targ;
Type *tp = tprm;
//printf("fparam[%d] ta = %s, tp = %s\n", u, ta->toChars(), tp->toChars());

if (m && !arg->isLvalue())
{
if (arg->op == TOKstring && tprmb->ty == Tsarray)
if (arg->op == TOKstring && tp->ty == Tsarray)
{
if (targb->ty != Tsarray)
if (ta->ty != Tsarray)
{
Type *tn = tprmb->nextOf()->castMod(targb->nextOf()->mod);
Type *tn = tp->nextOf()->castMod(ta->nextOf()->mod);
dinteger_t dim = ((StringExp *)arg)->len;
targb = tn->sarrayOf(dim);
ta = tn->sarrayOf(dim);
}
}
else if (arg->op == TOKslice && tprmb->ty == Tsarray)
else if (arg->op == TOKslice && tp->ty == Tsarray)
{
// Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
if (targb->ty != Tsarray)
if (ta->ty != Tsarray)
{
Type *tn = targb->nextOf();
dinteger_t dim = ((TypeSArray *)tprmb)->dim->toUInteger();
targb = tn->sarrayOf(dim);
Type *tn = ta->nextOf();
dinteger_t dim = ((TypeSArray *)tp)->dim->toUInteger();
ta = tn->sarrayOf(dim);
}
}
else
Expand All @@ -5865,21 +5865,18 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
*/
while (1)
{
Type *tat = targb->aliasthisOf();
Type *tat = ta->toBasetype()->aliasthisOf();
if (!tat || !tat->implicitConvTo(tprm))
break;
targb = tat;
ta = tat;
}

/* Don't allow static arrays to be passed to mutable references
* to static arrays if the argument cannot be modified.
/* A ref variable should work like a head-const reference.
* e.g. disallows:
* ref T <- an lvalue of const(T) argument
* ref T[dim] <- an lvalue of const(T[dim]) argument
*/
if (targb->nextOf() && tprmb->ty == Tsarray &&
!MODimplicitConv(targb->nextOf()->mod, tprmb->nextOf()->mod))
goto Nomatch;

// ref variable behaves like head-const reference
if (!targb->constConv(tprmb))
if (!ta->constConv(tp))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is redundant so the case will be covered correctly by the following constConv call.

goto Nomatch;
}
else if (p->storageClass & STCout)
Expand Down
15 changes: 15 additions & 0 deletions test/runnable/overload.d
Expand Up @@ -1053,6 +1053,20 @@ void test11916()
assert(g11916(m) == 2);
}

/***************************************************/
// 13783

enum E13783 { a = 5 }

inout(int) f( inout(int) t) { return t * 2; }
ref inout(int) f(ref inout(int) t) { return t; }

void test13783()
{
const E13783 e = E13783.a;
assert(f(e) == 10);
}

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

int main()
Expand Down Expand Up @@ -1086,6 +1100,7 @@ int main()
test11785();
test11915();
test11916();
test13783();

printf("Success\n");
return 0;
Expand Down