Skip to content

Commit

Permalink
fix Issue 17246 - [REG2.053] Extra destructor call.
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Oct 24, 2017
1 parent 7253190 commit 6eccdee
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/ddmd/e2ir.d
Expand Up @@ -5696,7 +5696,7 @@ private elem *toElemStructLit(StructLiteralExp sle, IRState *irs, TOK op, Symbol
* Add destructors
*/

elem *appendDtors(IRState *irs, elem *er, size_t starti, size_t endi)
private elem *appendDtors(IRState *irs, elem *er, size_t starti, size_t endi)
{
//printf("appendDtors(%d .. %d)\n", starti, endi);

Expand Down Expand Up @@ -5778,7 +5778,7 @@ elem *appendDtors(IRState *irs, elem *er, size_t starti, size_t endi)

elem *toElemDtor(Expression e, IRState *irs)
{
//printf("Expression.toElemDtor() %s\n", toChars());
//printf("Expression.toElemDtor() %s\n", e.toChars());
size_t starti = irs.varsInScope ? irs.varsInScope.dim : 0;
elem *er = toElem(e, irs);
size_t endi = irs.varsInScope ? irs.varsInScope.dim : 0;
Expand Down
14 changes: 9 additions & 5 deletions src/ddmd/expression.d
Expand Up @@ -1483,16 +1483,20 @@ extern (C++) bool preFunctionParameters(Loc loc, Scope* sc, Expressions* exps)
*/
extern (C++) Expression valueNoDtor(Expression e)
{
if (e.op == TOKcall)
auto ex = e;
while (ex.op == TOKcomma)
ex = (cast(CommaExp)ex).e2;

if (ex.op == TOKcall)
{
/* The struct value returned from the function is transferred
* so do not call the destructor on it.
* Recognize:
* ((S _ctmp = S.init), _ctmp).this(...)
* and make sure the destructor is not called on _ctmp
* BUG: if e is a CommaExp, we should go down the right side.
* BUG: if ex is a CommaExp, we should go down the right side.
*/
CallExp ce = cast(CallExp)e;
CallExp ce = cast(CallExp)ex;
if (ce.e1.op == TOKdotvar)
{
DotVarExp dve = cast(DotVarExp)ce.e1;
Expand All @@ -1516,9 +1520,9 @@ extern (C++) Expression valueNoDtor(Expression e)
}
}
}
else if (e.op == TOKvar)
else if (ex.op == TOKvar)
{
auto vtmp = (cast(VarExp)e).var.isVarDeclaration();
auto vtmp = (cast(VarExp)ex).var.isVarDeclaration();
if (vtmp && (vtmp.storage_class & STCrvalue))
{
vtmp.storage_class |= STCnodtor;
Expand Down
50 changes: 50 additions & 0 deletions test/runnable/test17246.d
@@ -0,0 +1,50 @@
/* REQUIRED_ARGS:
* OPTIONAL_ARGS:
*/

// https://issues.dlang.org/show_bug.cgi?id=17246

struct Foo
{
int* rc;
this(int val)
{
rc = new int;
(*rc) = 1;
}
this(this)
{
(*rc)++;
}
~this()
{
if (rc)
{
assert(*rc > 0);
(*rc)--;
}
}
}

struct Bar
{
Foo foo;
this(Foo foo, bool)
{
this.foo = foo;
}
}

bool fun(bool val) { return !val; }

auto genBar(bool flag)
{
return flag ? Bar() : Bar(Foo(10), fun(!flag));
}

int main(string[] args)
{
auto bar = genBar(args.length == 0);
return 0;
}

0 comments on commit 6eccdee

Please sign in to comment.