Skip to content

Commit

Permalink
Merge pull request #5451 from 9rnsr/fix15674
Browse files Browse the repository at this point in the history
[REG 2.066] Issue 15674 - alias this rejected for 'out' parameter
  • Loading branch information
MartinNowak committed Feb 23, 2016
2 parents cf67084 + 89c63bf commit 7d1e77f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 11 deletions.
24 changes: 13 additions & 11 deletions src/mtype.d
Expand Up @@ -6454,8 +6454,10 @@ public:
Expression arg = (*args)[u];
assert(arg);
//printf("arg: %s, type: %s\n", arg->toChars(), arg->type->toChars());

Type targ = arg.type;
Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;

if (p.storageClass & STClazy && tprm.ty == Tvoid && targ.ty != Tvoid)
m = MATCHconvert;
else
Expand All @@ -6470,15 +6472,20 @@ public:
m = arg.implicitConvTo(tprm);
//printf("match %d\n", m);
}

// Non-lvalues do not match ref or out parameters
if (p.storageClass & STCref)
if (p.storageClass & (STCref | STCout))
{
// 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 (p.storageClass & STCout)
goto Nomatch;

if (arg.op == TOKstring && tp.ty == Tsarray)
{
if (ta.ty != Tsarray)
Expand All @@ -6501,7 +6508,9 @@ public:
else
goto Nomatch;
}
/* find most derived alias this type being matched.

/* Find most derived alias this type being matched.
* Bugzilla 15674: Allow on both ref and out parameters.
*/
while (1)
{
Expand All @@ -6510,6 +6519,7 @@ public:
break;
ta = tat;
}

/* A ref variable should work like a head-const reference.
* e.g. disallows:
* ref T <- an lvalue of const(T) argument
Expand All @@ -6518,16 +6528,8 @@ public:
if (!ta.constConv(tp))
goto Nomatch;
}
else if (p.storageClass & STCout)
{
if (m && !arg.isLvalue())
goto Nomatch;
Type targb = targ.toBasetype();
Type tprmb = tprm.toBasetype();
if (!targb.constConv(tprmb))
goto Nomatch;
}
}

/* prefer matching the element type rather than the array
* type when more arguments are present with T[]...
*/
Expand Down
20 changes: 20 additions & 0 deletions test/runnable/aliasthis.d
Expand Up @@ -1196,6 +1196,25 @@ void test7945()
s.v.foo7945(); // 4.OK, ufcs
}

/***************************************************/
// 15674 - alias this on out parameter, consistent with 7945 case

struct S15674
{
int v;
alias v this;
}
void foo15674(out int i){ i = 42; }

void test15674()
{
S15674 s;
s.v = 1; foo15674(s); assert(s.v == 42);
s.v = 1; foo15674(s.v); assert(s.v == 42);
s.v = 1; s.foo15674(); assert(s.v == 42);
s.v = 1; s.v.foo15674(); assert(s.v == 42);
}

/***************************************************/
// 7979

Expand Down Expand Up @@ -1981,6 +2000,7 @@ int main()
test7731();
test7808();
test7945();
test15674();
test7979();
test7992();
test8169();
Expand Down

0 comments on commit 7d1e77f

Please sign in to comment.