Skip to content

Commit

Permalink
fix Issue 12760 - Initializing an object that has "this(Args) inout" …
Browse files Browse the repository at this point in the history
…causes "discards return value" warning
  • Loading branch information
9rnsr committed May 23, 2014
1 parent e0ff705 commit 3f3f8cf
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 11 deletions.
11 changes: 8 additions & 3 deletions src/e2ir.c
Expand Up @@ -55,6 +55,9 @@ elem *toElemDtor(Expression *e, IRState *irs);
unsigned totym(Type *tx);
Symbol *toSymbol(Dsymbol *s);

int callSideEffectLevel(FuncDeclaration *f);
int callSideEffectLevel(Type *t);

#define el_setLoc(e,loc) ((e)->Esrcpos.Sfilename = (char *)(loc).filename, \
(e)->Esrcpos.Slinnum = (loc).linnum, \
(e)->Esrcpos.Scharnum = (loc).charnum)
Expand Down Expand Up @@ -372,7 +375,8 @@ if (I32) assert(tysize[TYnptr] == 4);
e = el_una(op,tyret,ep);
}
else
{ /* Do not do "no side effect" calls if a hidden parameter is passed,
{
/* Do not do "no side effect" calls if a hidden parameter is passed,
* as the return value is stored through the hidden parameter, which
* is a side effect.
*/
Expand All @@ -381,8 +385,9 @@ if (I32) assert(tysize[TYnptr] == 4);
//printf("\tfd = %s, tf = %s\n", fd->toChars(), tf->toChars());
/* assert() has 'implicit side effect' so disable this optimization.
*/
int ns = ((fd ? fd->isPure() : tf->purity) == PUREstrong &&
tf->isnothrow && (retmethod != RETstack) &&
int ns = ((fd ? callSideEffectLevel(fd)
: callSideEffectLevel(t)) == 2 &&
retmethod != RETstack &&
!global.params.useAssert && global.params.optimize);
if (ep)
e = el_bin(ns ? OPcallns : OPcall, tyret, ec, ep);
Expand Down
77 changes: 69 additions & 8 deletions src/sideeffect.c
Expand Up @@ -48,6 +48,67 @@ bool hasSideEffect(Expression *e)
return walkPostorder(e, &v);
}

/********************************************
* Determine if the call of f, or function type or delegate type t1, has any side effects.
* Returns:
* 0 has any side effects
* 1 nothrow + constant purity
* 2 nothrow + strong purity
*/

int callSideEffectLevel(FuncDeclaration *f)
{
/* Bugzilla 12760: ctor call always has side effects.
*/
if (f->isCtorDeclaration())
return 0;

assert(f->type->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)f->type;
if (tf->isnothrow)
{
PURE purity = f->isPure();
if (purity == PUREstrong)
return 2;
if (purity == PUREconst)
return 1;
}
return 0;
}

int callSideEffectLevel(Type *t)
{
t = t->toBasetype();

TypeFunction *tf;
if (t->ty == Tdelegate)
tf = (TypeFunction *)((TypeDelegate *)t)->next;
else
{
assert(t->ty == Tfunction);
tf = (TypeFunction *)t;
}

tf->purityLevel();
PURE purity = tf->purity;
if (t->ty == Tdelegate && purity > PUREweak)
{
if (tf->isMutable())
purity = PUREweak;
else if (!tf->isImmutable())
purity = PUREconst;
}

if (tf->isnothrow)
{
if (purity == PUREstrong)
return 2;
if (purity == PUREconst)
return 1;
}
return 0;
}

bool lambdaHasSideEffect(Expression *e)
{
switch (e->op)
Expand Down Expand Up @@ -92,10 +153,10 @@ bool lambdaHasSideEffect(Expression *e)
Type *t = ce->e1->type->toBasetype();
if (t->ty == Tdelegate)
t = ((TypeDelegate *)t)->next;
if (t->ty == Tfunction)
((TypeFunction *)t)->purityLevel();
if (t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak &&
((TypeFunction *)t)->isnothrow)
if (t->ty == Tfunction &&
(ce->f && ce->f->type->ty == Tfunction
? callSideEffectLevel(ce->f)
: callSideEffectLevel(ce->e1->type)) > 0)
{
}
else
Expand Down Expand Up @@ -168,10 +229,10 @@ void discardValue(Expression *e)
Type *t = ce->e1->type->toBasetype();
if (t->ty == Tdelegate)
t = ((TypeDelegate *)t)->next;
if (t->ty == Tfunction)
((TypeFunction *)t)->purityLevel();
if (t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak &&
((TypeFunction *)t)->isnothrow)
if (t->ty == Tfunction &&
(ce->f && ce->f->type->ty == Tfunction
? callSideEffectLevel(ce->f)
: callSideEffectLevel(ce->e1->type)) > 0)
{
const char *s;
if (ce->f)
Expand Down
19 changes: 19 additions & 0 deletions test/fail_compilation/fail3882.d
Expand Up @@ -44,3 +44,22 @@ void test12619() pure
ubyte[10] a, b;
debug memcpy(a.ptr, b.ptr, 5); // memcpy call should have side effect
}

/******************************************/
// 12760

struct S12760(T)
{
T i;
this(T j) inout {}
}

struct K12760
{
S12760!int nullable;

this(int)
{
nullable = 0; // weak purity
}
}

0 comments on commit 3f3f8cf

Please sign in to comment.