Skip to content

Commit

Permalink
make inclusive __xdtor accessible
Browse files Browse the repository at this point in the history
- needed for attribute correct destruction of structs and classes
- same function as used by TypeInfo_Struct::xdtor
  • Loading branch information
MartinNowak committed May 15, 2015
1 parent 0e700a5 commit c42dbb9
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 10 deletions.
22 changes: 17 additions & 5 deletions src/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,20 +969,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 +1003,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
3 changes: 3 additions & 0 deletions src/idgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Msgtable[] msgtable =
{ "super" },
{ "ctor", "__ctor" },
{ "dtor", "__dtor" },
{ "__xdtor", "__xdtor" },
{ "__fieldDtor", "__fieldDtor" },
{ "__aggrDtor", "__aggrDtor" },
{ "_postblit", "__postblit" },
{ "classInvariant", "__invariant" },
{ "unitTest", "__unitTest" },
Expand Down
7 changes: 4 additions & 3 deletions src/traits.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,10 +973,11 @@ 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)
{
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions test/compilable/extra-files/json.out
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@
"overrides" : [
"json.Baz!(int, 2, null).Baz.t"
]
},
{
"name" : "__xdtor",
"kind" : "alias"
}
]
},
Expand Down
4 changes: 2 additions & 2 deletions test/runnable/traits.d
Original file line number Diff line number Diff line change
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", "opAssign"]);

// --------

Expand Down
86 changes: 86 additions & 0 deletions test/runnable/xdtor.d
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit c42dbb9

Please sign in to comment.