Skip to content

Commit

Permalink
fix Issue 12390 - "has no effect in expression" diagnostic regression
Browse files Browse the repository at this point in the history
When value discarding check on statements, the side-effect check should not be done deeply.
  • Loading branch information
9rnsr committed Apr 7, 2014
1 parent 6d10394 commit 89ca0a1
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 69 deletions.
143 changes: 74 additions & 69 deletions src/sideeffect.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "attrib.h"

bool walkPostorder(Expression *e, StoppableVisitor *v);
void discardValue(Expression *e);
bool lambdaHasSideEffect(Expression *e);

/********************************************
* Determine if Expression has any side effects.
Expand All @@ -39,81 +39,86 @@ bool hasSideEffect(Expression *e)

void visit(Expression *e)
{
switch (e->op)
{
// Sort the cases by most frequently used first
case TOKassign:
case TOKplusplus:
case TOKminusminus:
case TOKdeclaration:
case TOKconstruct:
case TOKblit:
case TOKaddass:
case TOKminass:
case TOKcatass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKshlass:
case TOKshrass:
case TOKushrass:
case TOKandass:
case TOKorass:
case TOKxorass:
case TOKpowass:
case TOKin:
case TOKremove:
case TOKassert:
case TOKhalt:
case TOKdelete:
case TOKnew:
case TOKnewanonclass:
// stop walking if we determine this expression has side effects
stop = true;
break;
// stop walking if we determine this expression has side effects
stop = lambdaHasSideEffect(e);
}
};

LambdaHasSideEffect v;
return walkPostorder(e, &v);
}

case TOKcall:
bool lambdaHasSideEffect(Expression *e)
{
switch (e->op)
{
// Sort the cases by most frequently used first
case TOKassign:
case TOKplusplus:
case TOKminusminus:
case TOKdeclaration:
case TOKconstruct:
case TOKblit:
case TOKaddass:
case TOKminass:
case TOKcatass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKshlass:
case TOKshrass:
case TOKushrass:
case TOKandass:
case TOKorass:
case TOKxorass:
case TOKpowass:
case TOKin:
case TOKremove:
case TOKassert:
case TOKhalt:
case TOKdelete:
case TOKnew:
case TOKnewanonclass:
return true;

case TOKcall:
{
CallExp *ce = (CallExp *)e;
/* Calling a function or delegate that is pure nothrow
* has no side effects.
*/
if (ce->e1->type)
{
CallExp *ce = (CallExp *)e;
/* Calling a function or delegate that is pure nothrow
* has no side effects.
*/
if (ce->e1->type)
Type *t = ce->e1->type->toBasetype();
if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak &&
((TypeFunction *)t)->isnothrow)
||
(t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak &&
((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
)
{
Type *t = ce->e1->type->toBasetype();
if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak &&
((TypeFunction *)t)->isnothrow)
||
(t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak &&
((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
)
{
}
else
stop = true;
}
break;
}

case TOKcast:
{
CastExp *ce = (CastExp *)e;
/* if:
* cast(classtype)func() // because it may throw
*/
if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass)
stop = true;
break;
else
return true;
}
break;
}

default:
break;
}
case TOKcast:
{
CastExp *ce = (CastExp *)e;
/* if:
* cast(classtype)func() // because it may throw
*/
if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass)
return true;
break;
}
};

LambdaHasSideEffect v;
return walkPostorder(e, &v);
default:
break;
}
return false;
}


Expand All @@ -123,7 +128,7 @@ bool hasSideEffect(Expression *e)
*/
void discardValue(Expression *e)
{
if (hasSideEffect(e))
if (lambdaHasSideEffect(e)) // check side-effect shallowly
return;
switch (e->op)
{
Expand Down
15 changes: 15 additions & 0 deletions test/fail_compilation/fail12390.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail12390.d(14): Error: == has no effect in expression (fun().i == 4)
---
*/

struct S { int i; }

S fun() { return S(42); }

void main()
{
fun().i == 4;
}

0 comments on commit 89ca0a1

Please sign in to comment.