Skip to content

Commit

Permalink
Merge pull request #4588 from legrosbuffle/fix12603
Browse files Browse the repository at this point in the history
Issue 12603 - [CTFE] goto does not correctly call dtors
  • Loading branch information
9rnsr committed May 31, 2015
2 parents 1115587 + 5586652 commit 26ebfeb
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/interpret.c
Expand Up @@ -1826,6 +1826,28 @@ class Interpreter : public Visitor
result = ex;
return;
}
while (CTFEExp::isGotoExp(ex))
{
// If the goto target is within the body, we must not interpret the finally statement,
// because that will call destructors for objects within the scope, which we should not do.
InterState istatex = *istate;
istatex.start = istate->gotoTarget; // set starting statement
istatex.gotoTarget = NULL;
Expression *bex = interpret(s->body, &istatex);
if (istatex.start)
{
// The goto target is outside the current scope.
break;
}
// The goto target was within the body.
if (CTFEExp::isCantExp(bex))
{
result = bex;
return;
}
*istate = istatex;
ex = bex;
}
Expression *ey = interpret(s->finalbody, istate);
if (CTFEExp::isCantExp(ey))
{
Expand Down
114 changes: 114 additions & 0 deletions test/compilable/interpret3.d
Expand Up @@ -7538,3 +7538,117 @@ bool test7151()
return a == a && a != new Object;
}
static assert(test7151());


/**************************************************
12603 - [CTFE] goto does not correctly call dtors
**************************************************/

struct S12603
{
this(uint* dtorCalled)
{
*dtorCalled = 0;
this.dtorCalled = dtorCalled;
}

@disable this();

~this()
{
++*dtorCalled;
}

uint* dtorCalled;
}


auto numDtorCallsByGotoWithinScope()
{
uint dtorCalled;
{
S12603 s = S12603(&dtorCalled);
assert(dtorCalled == 0);
goto L_abc;
L_abc:
assert(dtorCalled == 0);
}
assert(dtorCalled == 1);
return dtorCalled;
}
static assert(numDtorCallsByGotoWithinScope() == 1);


auto numDtorCallsByGotoOutOfScope()
{
uint dtorCalled;
{
S12603 s = S12603(&dtorCalled);
assert(dtorCalled == 0);
goto L_abc;
}
L_abc:
assert(dtorCalled == 1);
return dtorCalled;
}
static assert(numDtorCallsByGotoOutOfScope() == 1);


uint numDtorCallsByGotoDifferentScopeAfter()
{
uint dtorCalled;
{
S12603 s = S12603(&dtorCalled);
assert(dtorCalled == 0);
}
assert(dtorCalled == 1);
goto L_abc;
L_abc:
assert(dtorCalled == 1);
return dtorCalled;
}
static assert(numDtorCallsByGotoDifferentScopeAfter() == 1);


auto numDtorCallsByGotoDifferentScopeBefore()
{
uint dtorCalled;
assert(dtorCalled == 0);
goto L_abc;
L_abc:
assert(dtorCalled == 0);
{
S12603 s = S12603(&dtorCalled);
assert(dtorCalled == 0);
}
assert(dtorCalled == 1);
return dtorCalled;
}
static assert(numDtorCallsByGotoDifferentScopeBefore() == 1);


struct S12603_2
{
~this()
{
dtorCalled = true;
}

bool dtorCalled = false;
}

auto structInCaseScope()
{
auto charsets = S12603_2();
switch(1)
{
case 0:
auto set = charsets;
break;
default:
break;
}
return charsets.dtorCalled;
}

static assert(!structInCaseScope());

0 comments on commit 26ebfeb

Please sign in to comment.