Skip to content

Commit

Permalink
Merge pull request #468 from 9rnsr/fix6836
Browse files Browse the repository at this point in the history
Issue 6836 & 6837 & 6927 Fix UFCS fails
  • Loading branch information
WalterBright committed Nov 16, 2011
2 parents 8857ba8 + df93f21 commit 7c19395
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 55 deletions.
183 changes: 128 additions & 55 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -7052,6 +7052,131 @@ Expression *CallExp::syntaxCopy()
}


Expression *CallExp::resolveUFCS(Scope *sc)
{
Expression *ethis = NULL;
DotIdExp *dotid;
DotTemplateInstanceExp *dotti;
Identifier *ident;

if (e1->op == TOKdot)
{
dotid = (DotIdExp *)e1;
ident = dotid->ident;
ethis = dotid->e1 = dotid->e1->semantic(sc);
if (ethis->op == TOKdotexp)
return NULL;
ethis = resolveProperties(sc, ethis);
}
else if (e1->op == TOKdotti)
{
dotti = (DotTemplateInstanceExp *)e1;
ident = dotti->ti->name;
ethis = dotti->e1 = dotti->e1->semantic(sc);
if (ethis->op == TOKdotexp)
return NULL;
ethis = resolveProperties(sc, ethis);
}

if (ethis && ethis->type)
{
AggregateDeclaration *ad;
Lagain:
Type *tthis = ethis->type->toBasetype();
if (tthis->ty == Tclass)
{
ad = ((TypeClass *)tthis)->sym;
if (search_function(ad, ident))
return NULL;
goto L1;
}
else if (tthis->ty == Tstruct)
{
ad = ((TypeStruct *)tthis)->sym;
if (search_function(ad, ident))
return NULL;
L1:
if (ad->aliasthis)
{
ethis = new DotIdExp(ethis->loc, ethis, ad->aliasthis->ident);
ethis = ethis->semantic(sc);
ethis = resolveProperties(sc, ethis);
goto Lagain;
}
}
else if (tthis->ty == Taarray && e1->op == TOKdot)
{
if (ident == Id::remove)
{
/* Transform:
* aa.remove(arg) into delete aa[arg]
*/
if (!arguments || arguments->dim != 1)
{ error("expected key as argument to aa.remove()");
return new ErrorExp();
}
Expression *key = arguments->tdata()[0];
key = key->semantic(sc);
key = resolveProperties(sc, key);
key->rvalue();

TypeAArray *taa = (TypeAArray *)tthis;
key = key->implicitCastTo(sc, taa->index);

return new RemoveExp(loc, ethis, key);
}
else if (ident == Id::apply || ident == Id::applyReverse)
{
return NULL;
}
else
{ TypeAArray *taa = (TypeAArray *)tthis;
assert(taa->ty == Taarray);
StructDeclaration *sd = taa->getImpl();
Dsymbol *s = sd->search(0, ident, 2);
if (s)
return NULL;
goto Lshift;
}
}
else if (tthis->ty == Tarray || tthis->ty == Tsarray)
{
Lshift:
if (!arguments)
arguments = new Expressions();
arguments->shift(ethis);
if (e1->op == TOKdot)
{
/* Transform:
* array.id(args) into .id(array,args)
*/
#if DMDV2
e1 = new DotIdExp(dotid->loc,
new IdentifierExp(dotid->loc, Id::empty),
ident);
#else
e1 = new IdentifierExp(dotid->loc, ident);
#endif
}
else if (e1->op == TOKdotti)
{
/* Transform:
* array.foo!(tiargs)(args) into .foo!(tiargs)(array,args)
*/
#if DMDV2
e1 = new DotExp(dotti->loc,
new IdentifierExp(dotti->loc, Id::empty),
new ScopeExp(dotti->loc, dotti->ti));
#else
e1 = new ScopeExp(dotti->loc, dotti->ti);
#endif
}
//printf("-> this = %s\n", toChars());
}
}
return NULL;
}

Expression *CallExp::semantic(Scope *sc)
{
TypeFunction *tf;
Expand Down Expand Up @@ -7082,61 +7207,9 @@ Expression *CallExp::semantic(Scope *sc)
return semantic(sc);
}

/* Transform:
* array.id(args) into .id(array,args)
* aa.remove(arg) into delete aa[arg]
*/
if (e1->op == TOKdot)
{
// BUG: we should handle array.a.b.c.e(args) too

DotIdExp *dotid = (DotIdExp *)(e1);
dotid->e1 = dotid->e1->semantic(sc);
assert(dotid->e1);
if (dotid->e1->type)
{
TY e1ty = dotid->e1->type->toBasetype()->ty;
if (e1ty == Taarray && dotid->ident == Id::remove)
{
if (!arguments || arguments->dim != 1)
{ error("expected key as argument to aa.remove()");
return new ErrorExp();
}
Expression *key = arguments->tdata()[0];
key = key->semantic(sc);
key = resolveProperties(sc, key);
key->rvalue();

TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
key = key->implicitCastTo(sc, taa->index);

return new RemoveExp(loc, dotid->e1, key);
}
else if (e1ty == Tarray || e1ty == Tsarray ||
(e1ty == Taarray && dotid->ident != Id::apply && dotid->ident != Id::applyReverse))
{
if (e1ty == Taarray)
{ TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
assert(taa->ty == Taarray);
StructDeclaration *sd = taa->getImpl();
Dsymbol *s = sd->search(0, dotid->ident, 2);
if (s)
goto L2;
}
if (!arguments)
arguments = new Expressions();
arguments->shift(dotid->e1);
#if DMDV2
e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident);
#else
e1 = new IdentifierExp(dotid->loc, dotid->ident);
#endif
}

L2:
;
}
}
Expression *e = resolveUFCS(sc);
if (e)
return e;

#if 1
/* This recognizes:
Expand Down
1 change: 1 addition & 0 deletions src/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@ struct CallExp : UnaExp
CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);

Expression *syntaxCopy();
Expression *resolveUFCS(Scope *sc);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expand Down
72 changes: 72 additions & 0 deletions test/runnable/xtest46.d
Original file line number Diff line number Diff line change
Expand Up @@ -3909,6 +3909,75 @@ void test6488()
d.seconds();
}

/***************************************************/
// 6836

template map6836(fun...) if (fun.length >= 1)
{
auto map6836(Range)(Range r)
{
}
}
void test6836()
{
[1].map6836!"a"();
}

/***************************************************/
// 6837

struct Ref6837a(T)
{
T storage;
alias storage this;
}

struct Ref6837b(T)
{
T storage;
@property ref T get(){ return storage; }
alias get this;
}

int front6837(int[] arr){ return arr[0]; }

void popFront6837(ref int[] arr){ arr = arr[1..$]; }

void test6837()
{
assert([1,2,3].front6837 == 1);

auto r1 = Ref6837a!(int[])([1,2,3]);
assert(r1.front6837() == 1); // ng
assert(r1.front6837 == 1); // ok
r1.popFront6837(); // ng
r1.storage.popFront6837(); // ok

auto r2 = Ref6837b!(int[])([1,2,3]);
assert(r2.front6837() == 1); // ng
assert(r2.front6837 == 1); // ok
r2.popFront6837(); // ng
r2.get.popFront6837(); // ng
r2.get().popFront6837(); // ok
}

/***************************************************/
// 6927

@property int[] foo6927()
{
return [1, 2];
}
int[] bar6927(int[] a)
{
return a;
}
void test6927()
{
bar6927(foo6927); // OK
foo6927.bar6927(); // line 9, Error
}

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

struct Foo6813(T)
Expand Down Expand Up @@ -4323,6 +4392,9 @@ int main()
test6084();
test4237();
test6488();
test6836();
test6837();
test6927();
test6733();
test6813();
test6859();
Expand Down

0 comments on commit 7c19395

Please sign in to comment.