Skip to content

Commit

Permalink
Merge pull request #4650 from MartinNowak/aggrDtor
Browse files Browse the repository at this point in the history
make inclusive dtor/postblit available
  • Loading branch information
WalterBright committed May 17, 2015
2 parents 484447b + a6b73d2 commit 448ff39
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 23 deletions.
48 changes: 36 additions & 12 deletions src/clone.c
Expand Up @@ -833,13 +833,13 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
ea = new CastExp(loc, ea, Type::tvoid->pointerTo());

Expression *et = getTypeInfo(v->type, sc);
et = new DotIdExp(loc, et, Id::postblit);
et = new DotIdExp(loc, et, Identifier::idPool("postblit"));
ex = new CallExp(loc, et, ea);
}
a->push(new ExpStatement(loc, ex)); // combine in forward order

/* Bugzilla 10972: When the following field postblit calls fail,
* this field should be destructed for Excetion Safety.
* this field should be destructed for Exception Safety.
*/
if (!sdv->dtor)
continue;
Expand Down Expand Up @@ -869,20 +869,22 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
if (a || (stc & STCdisable))
{
//printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Identifier::idPool("__fieldPostBlit"));
PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id::__fieldPostblit);
dd->fbody = a ? new CompoundStatement(loc, a) : NULL;
sd->postblits.shift(dd);
sd->members->push(dd);
dd->semantic(sc);
}

FuncDeclaration *xpostblit = NULL;
switch (sd->postblits.dim)
{
case 0:
return NULL;
break;

case 1:
return sd->postblits[0];
xpostblit = sd->postblits[0];
break;

default:
Expression *e = NULL;
Expand All @@ -901,12 +903,22 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
ex = new CallExp(loc, ex);
e = Expression::combine(e, ex);
}
PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Identifier::idPool("__aggrPostBlit"));
PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id::__aggrPostblit);
dd->fbody = new ExpStatement(loc, e);
sd->members->push(dd);
dd->semantic(sc);
return dd;
xpostblit = dd;
break;
}
// Add an __xpostblit alias to make the inclusive postblit accessible
if (xpostblit)
{
AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xpostblit, xpostblit);
alias->semantic(sc);
sd->members->push(alias);
alias->addMember(sc, sd); // add to symbol table
}
return xpostblit;
}

/*****************************************
Expand Down Expand Up @@ -969,20 +981,22 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc)
if (e || (stc & STCdisable))
{
//printf("Building __fieldDtor()\n");
DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Identifier::idPool("__fieldDtor"));
DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Id::__fieldDtor);
dd->fbody = new ExpStatement(loc, e);
ad->dtors.shift(dd);
ad->members->push(dd);
dd->semantic(sc);
}

FuncDeclaration *xdtor = NULL;
switch (ad->dtors.dim)
{
case 0:
return NULL;
break;

case 1:
return ad->dtors[0];
xdtor = ad->dtors[0];
break;

default:
e = NULL;
Expand All @@ -1001,12 +1015,22 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc)
ex = new CallExp(loc, ex);
e = Expression::combine(ex, e);
}
DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Identifier::idPool("__aggrDtor"));
DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Id::__aggrDtor);
dd->fbody = new ExpStatement(loc, e);
ad->members->push(dd);
dd->semantic(sc);
return dd;
xdtor = dd;
break;
}
// Add an __xdtor alias to make the inclusive dtor accessible
if (xdtor)
{
AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xdtor, xdtor);
alias->semantic(sc);
ad->members->push(alias);
alias->addMember(sc, ad); // add to symbol table
}
return xdtor;
}

/******************************************
Expand Down
2 changes: 1 addition & 1 deletion src/func.c
Expand Up @@ -4691,7 +4691,7 @@ void PostBlitDeclaration::semantic(Scope *sc)
errors = true;
return;
}
if (ident == Id::_postblit && semanticRun < PASSsemantic)
if (ident == Id::postblit && semanticRun < PASSsemantic)
ad->postblits.push(this);
if (!type)
type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
Expand Down
9 changes: 7 additions & 2 deletions src/idgen.d
Expand Up @@ -39,7 +39,13 @@ Msgtable[] msgtable =
{ "super" },
{ "ctor", "__ctor" },
{ "dtor", "__dtor" },
{ "_postblit", "__postblit" },
{ "__xdtor", "__xdtor" },
{ "__fieldDtor", "__fieldDtor" },
{ "__aggrDtor", "__aggrDtor" },
{ "postblit", "__postblit" },
{ "__xpostblit", "__xpostblit" },
{ "__fieldPostblit", "__fieldPostblit" },
{ "__aggrPostblit", "__aggrPostblit" },
{ "classInvariant", "__invariant" },
{ "unitTest", "__unitTest" },
{ "require", "__require" },
Expand Down Expand Up @@ -104,7 +110,6 @@ Msgtable[] msgtable =
{ "_arguments" },
{ "_argptr" },
{ "destroy" },
{ "postblit" },
{ "xopEquals", "__xopEquals" },
{ "xopCmp", "__xopCmp" },
{ "xtoHash", "__xtoHash" },
Expand Down
2 changes: 1 addition & 1 deletion src/parse.c
Expand Up @@ -1470,7 +1470,7 @@ Dsymbol *Parser::parseCtor(PrefixAttributes *pAttrs)
if (stc & STCstatic)
error(loc, "postblit cannot be static");

PostBlitDeclaration *f = new PostBlitDeclaration(loc, Loc(), stc, Id::_postblit);
PostBlitDeclaration *f = new PostBlitDeclaration(loc, Loc(), stc, Id::postblit);
if (pAttrs)
pAttrs->storageClass = STCundefined;
Dsymbol *s = parseContracts(f);
Expand Down
8 changes: 5 additions & 3 deletions src/traits.c
Expand Up @@ -973,10 +973,12 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
//printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
if (sm->ident)
{
if (sm->ident != Id::ctor &&
if (sm->ident->string[0] == '_' && sm->ident->string[1] == '_' &&
sm->ident != Id::ctor &&
sm->ident != Id::dtor &&
sm->ident != Id::_postblit &&
memcmp(sm->ident->string, "__", 2) == 0)
sm->ident != Id::__xdtor &&
sm->ident != Id::postblit &&
sm->ident != Id::__xpostblit)
{
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions test/compilable/extra-files/json.out
Expand Up @@ -211,6 +211,10 @@
"overrides" : [
"json.Baz!(int, 2, null).Baz.t"
]
},
{
"name" : "__xdtor",
"kind" : "alias"
}
]
},
Expand Down
3 changes: 1 addition & 2 deletions test/fail_compilation/fail4421.d
Expand Up @@ -6,7 +6,7 @@ fail_compilation/fail4421.d(17): Error: destructor fail4421.U1.~this destructors
fail_compilation/fail4421.d(18): Error: function fail4421.U1.__invariant1 destructors, postblits and invariants are not allowed in union U1
fail_compilation/fail4421.d(14): Error: function fail4421.U1.__invariant destructors, postblits and invariants are not allowed in union U1
fail_compilation/fail4421.d(28): Error: destructor fail4421.U2.~this destructors, postblits and invariants are not allowed in union U2
fail_compilation/fail4421.d(28): Error: function fail4421.U2.__fieldPostBlit destructors, postblits and invariants are not allowed in union U2
fail_compilation/fail4421.d(28): Error: function fail4421.U2.__fieldPostblit destructors, postblits and invariants are not allowed in union U2
fail_compilation/fail4421.d(33): Error: struct fail4421.S2 destructors, postblits and invariants are not allowed in overlapping fields s1 and j
---
*/
Expand Down Expand Up @@ -38,4 +38,3 @@ struct S2
int j;
}
}

4 changes: 2 additions & 2 deletions test/runnable/traits.d
Expand Up @@ -427,7 +427,7 @@ void test14()
{
auto a = [__traits(derivedMembers, D14)];
writeln(a);
assert(a == ["__ctor","__dtor","foo"]);
assert(a == ["__ctor","__dtor","foo", "__xdtor"]);
}

/********************************************************/
Expand Down Expand Up @@ -1254,7 +1254,7 @@ struct S10096X
}
static assert(
[__traits(allMembers, S10096X)] ==
["str", "__ctor", "__postblit", "__dtor", "opAssign"]);
["str", "__ctor", "__postblit", "__dtor", "__xdtor", "__xpostblit", "opAssign"]);

// --------

Expand Down
86 changes: 86 additions & 0 deletions test/runnable/xdtor.d
@@ -0,0 +1,86 @@
// PERMUTE_ARGS:

struct Field
{
~this() @safe @nogc pure nothrow {}
}

struct Counter
{
static size_t cnt;
~this() @safe @nogc nothrow { ++cnt; }
}

struct Foo
{
~this() @safe @nogc pure nothrow {}
Field field;
}

class Bar
{
~this() @safe @nogc pure nothrow {}
Field field;
}

void test1() @safe @nogc pure nothrow
{
Foo foo;
foo.__xdtor();
scope bar = new Bar();
bar.__xdtor();
}

static assert(__traits(hasMember, Foo, "__xdtor"));
static assert(__traits(hasMember, Bar, "__xdtor"));

//

struct FieldDtor
{
Counter counter;
}

struct AggrDtor
{
static size_t cnt;
~this() @safe @nogc nothrow { ++cnt; }
}

struct MixedDtor
{
static size_t cnt;
Counter counter;
~this() @safe @nogc nothrow { ++cnt; }
}

struct SNoDtor {}
class CNoDtor {}

static assert(!__traits(hasMember, SNoDtor, "__xdtor"));
static assert(!__traits(hasMember, CNoDtor, "__xdtor"));

void test2() @safe @nogc nothrow
{
FieldDtor a;
assert(Counter.cnt == 0);
a.__xdtor();
assert(Counter.cnt == 1);
AggrDtor b;
assert(AggrDtor.cnt == 0);
b.__xdtor();
assert(AggrDtor.cnt == 1);
Counter.cnt = 0;
MixedDtor c;
assert(MixedDtor.cnt == 0);
assert(Counter.cnt == 0);
c.__xdtor();
assert(MixedDtor.cnt == 1);
assert(Counter.cnt == 1);
}

void main()
{
test1();
test2();
}
77 changes: 77 additions & 0 deletions test/runnable/xpostblit.d
@@ -0,0 +1,77 @@
// PERMUTE_ARGS:

struct Field
{
this(this) @safe @nogc pure nothrow {}
}

struct Counter
{
static size_t cnt;
this(this) @safe @nogc nothrow { ++cnt; }
}

struct Foo
{
this(this) @safe @nogc pure nothrow {}
Field field;
}

void test1() @safe @nogc pure nothrow
{
Foo foo;
foo.__xpostblit();
}

static assert(__traits(hasMember, Foo, "__xpostblit"));

//

struct FieldPostblit
{
Counter counter;
}

struct AggrPostblit
{
static size_t cnt;
this(this) @safe @nogc nothrow { ++cnt; }
}

struct MixedPostblit
{
static size_t cnt;
Counter counter;
this(this) @safe @nogc nothrow { ++cnt; }
}

struct SNoPostblit {}
class CNoPostblit {}

static assert(!__traits(hasMember, SNoPostblit, "__xpostblit"));
static assert(!__traits(hasMember, CNoPostblit, "__xpostblit"));

void test2() @safe @nogc nothrow
{
FieldPostblit a;
assert(Counter.cnt == 0);
a.__xpostblit();
assert(Counter.cnt == 1);
AggrPostblit b;
assert(AggrPostblit.cnt == 0);
b.__xpostblit();
assert(AggrPostblit.cnt == 1);
Counter.cnt = 0;
MixedPostblit c;
assert(MixedPostblit.cnt == 0);
assert(Counter.cnt == 0);
c.__xpostblit();
assert(MixedPostblit.cnt == 1);
assert(Counter.cnt == 1);
}

void main()
{
test1();
test2();
}

0 comments on commit 448ff39

Please sign in to comment.