Skip to content

Commit

Permalink
Dwarfeh: new patterns not detected by destructorr code
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Dec 27, 2015
1 parent 0d50b3d commit a5994bf
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/backend/el.c
Expand Up @@ -2287,6 +2287,7 @@ elem *el_ddtor(elem *e,void *decl)

/*********************************************
* Create constructor/destructor pair of elems.
* Caution: The pattern generated here must match that detected in e2ir.c's visit(CallExp).
* Params:
* ec = code to construct (may be NULL)
* ed = code to destruct
Expand Down
38 changes: 26 additions & 12 deletions src/e2ir.c
Expand Up @@ -3520,13 +3520,15 @@ elem *toElem(Expression *e, IRState *irs)
ectype = dve->e1->type->toBasetype();

/* Recognize:
* [1] ((S __ctmp = initializer),__ctmp).ctor(args)
* where the left of the . was turned into:
* [2] (dctor info ((__ctmp = initializer),__ctmp), __ctmp)
* [1] ce: ((S __ctmp = initializer),__ctmp).ctor(args)
* where the left of the . was turned into [2] or [3] for EH_DWARF:
* [2] ec: (dctor info ((__ctmp = initializer),__ctmp)), __ctmp
* [3] ec: (dctor info ((_flag=0),((__ctmp = initializer),__ctmp))), __ctmp
* The trouble (Bugzilla 13095) is if ctor(args) throws, then __ctmp is destructed even though __ctmp
* is not a fully constructed object yet. The solution is to move the ctor(args) itno the dctor tree.
* But first, detect [1], then [2], then split up [2] into:
* eeq: (dctor info ((__ctmp = initializer),__ctmp))
* eeq: (dctor info ((_flag=0),((__ctmp = initializer),__ctmp))) for EH_DWARF
* ec: __ctmp
*/
if (fd && fd->isCtorDeclaration())
Expand All @@ -3536,20 +3538,22 @@ elem *toElem(Expression *e, IRState *irs)
{
//printf("test30a\n");
if (((CommaExp *)dve->e1)->e1->op == TOKdeclaration && ((CommaExp *)dve->e1)->e2->op == TOKvar)
{
{ // dve->e1: (declaration , var)

//printf("test30b\n");
if (ec->Eoper == OPcomma &&
ec->E1->Eoper == OPinfo &&
ec->E1->E1->Eoper == OPdctor &&
ec->E1->E2->Eoper == OPcomma)
{
{ // ec: ((dctor info (* , *)) , *)

//printf("test30c\n");
dctor = true; // remember we detected it

// Split ec into eeq and ec per comment above
eeq = ec->E1;
eeq = ec->E1; // (dctor info (*, *))
ec->E1 = NULL;
ec = el_selecte2(ec);
ec = el_selecte2(ec); // *
}
}
}
Expand Down Expand Up @@ -3654,17 +3658,27 @@ elem *toElem(Expression *e, IRState *irs)
/* Continuation of fix outlined above for moving constructor call into dctor tree.
* Given:
* eeq: (dctor info ((__ctmp = initializer),__ctmp))
* eeq: (dctor info ((_flag=0),((__ctmp = initializer),__ctmp))) for EH_DWARF
* ecall: * call(ce, args)
* Rewrite ecall as:
* * (dctor info ((__ctmp = initializer),call(ce, args)))
* * (dctor info ((_flag=0),(__ctmp = initializer),call(ce, args)))
*/
assert(eeq->E2->Eoper == OPcomma);
elem *ea = ecall->E1; // ea: call(ce,args)
tym_t ty = ea->Ety;
ecall->E1 = eeq;
eeq->Ety = ea->Ety;
el_free(eeq->E2->E2);
eeq->E2->E2 = ea; // replace ,__ctmp with ,call(ce,args)
eeq->E2->Ety = ea->Ety;
assert(eeq->Eoper == OPinfo);
elem *eeqcomma = eeq->E2;
assert(eeqcomma->Eoper == OPcomma);
while (eeqcomma->E2->Eoper == OPcomma)
{
eeqcomma->Ety = ty;
eeqcomma = eeqcomma->E2;
}
eeq->Ety = ty;
el_free(eeqcomma->E2);
eeqcomma->E2 = ea; // replace ,__ctmp with ,call(ce,args)
eeqcomma->Ety = ty;
eeq = NULL;
}

Expand Down
30 changes: 30 additions & 0 deletions test/runnable/sdtor.d
Expand Up @@ -4172,6 +4172,35 @@ static assert(test14838());

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

struct S63
{
private long p = 87;

this(int x)
{
assert(p == 87);
p += x;
}

~this() { }

this(this) { }

void funky() { assert(p == 90); }

static void tester()
{
S63(3).funky();
}
}

void test63()
{
S63.tester();
}

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

int main()
{
test1();
Expand Down Expand Up @@ -4290,6 +4319,7 @@ int main()
test14860();
test14696();
test14838();
test63();

printf("Success\n");
return 0;
Expand Down

0 comments on commit a5994bf

Please sign in to comment.