Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/ddmd/clone.d
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ extern (C++) FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
* all the members.
* Note the close similarity with AggregateDeclaration::buildDtor(),
* and the ordering changes (runs forward instead of backwards).
* buildInv() should be run first.
*/
extern (C++) FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
{
Expand Down Expand Up @@ -1088,13 +1089,21 @@ extern (C++) FuncDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
switch (ad.dtors.dim)
{
case 0:
/* If running invariant, need a destructor to hang it on,
* but only do for root modules, as ones in the library may not
* have been compiled with useInvariants
*/
if (global.params.useInvariants && ad.inv && sc._module.isRoot())
goto Ldefault;

break;

case 1:
xdtor = ad.dtors[0];
break;

default:
Ldefault:
e = null;
stc = STCsafe | STCnothrow | STCpure | STCnogc;
for (size_t i = 0; i < ad.dtors.dim; i++)
Expand Down
23 changes: 23 additions & 0 deletions src/ddmd/dclass.d
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,29 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
}
}

version (none) // Controversial - see Bugzilla 519
{
/* If class has no constructor, but does have an invariant, create a default constructor merely
* as a place where the invariant call will be added.
*/
if (!ctor && global.params.useInvariants && inv && !isCPPclass())
{
auto tf = new TypeFunction(null, null, 0, LINKd, inv.storage_class);
auto btf = cast(TypeFunction)inv.type;
tf.purity = btf.purity;
tf.isnothrow = btf.isnothrow;
tf.isnogc = btf.isnogc;
tf.trust = btf.trust;
auto ctor = new CtorDeclaration(loc, Loc(), 0, tf);
ctor.fbody = new CompoundStatement(Loc(), new Statements());
members.push(ctor);
ctor.addMember(sc, this, 1);
ctor.semantic(sc2);
this.ctor = ctor;
defaultCtor = ctor;
}
}

dtor = buildDtor(this, sc2);

if (auto f = hasIdentityOpAssign(this, sc2))
Expand Down
3 changes: 1 addition & 2 deletions src/ddmd/dstruct.d
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
*/
aggNew = cast(NewDeclaration)search(Loc(), Id.classNew);
aggDelete = cast(DeleteDeclaration)search(Loc(), Id.classDelete);
inv = buildInv(this, sc2);

// Look for the constructor
ctor = searchCtor();
Expand All @@ -417,8 +418,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
xcmp = buildXopCmp(this, sc2);
xhash = buildXtoHash(this, sc2);

inv = buildInv(this, sc2);

Module.dprogress++;
semanticRun = PASSsemanticdone;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
Expand Down
12 changes: 12 additions & 0 deletions src/ddmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -5686,6 +5686,18 @@ private elem *toElemStructLit(StructLiteralExp sle, IRState *irs, TOK op, Symbol
e = el_combine(e, e1);
}

if (global.params.useInvariants && sle.sd.inv)
{
/* If there are no arguments, then this is default initialization and shouldn't call invariant.
*/
if (dim)
{
FuncDeclaration inv = sle.sd.inv;
elem *einv = callfunc(sle.loc, irs, 1, inv.type.nextOf(), el_ptr(stmp), sle.sd.type.pointerTo(), inv, inv.type, null, null);
e = el_combine(e, einv);
}
}

elem *ev = el_var(stmp);
ev.ET = Type_toCtype(sle.sd.type);
e = el_combine(e, ev);
Expand Down
4 changes: 3 additions & 1 deletion test/runnable/testdstress.d
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,12 @@ class Parent40{

invariant()
{
assert(!checked40);
if (!checked40)
{
checked40=true;
// even number
assert((x&1u)==0);
}
}
}

Expand Down
72 changes: 72 additions & 0 deletions test/runnable/testinvariant.d
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,75 @@ void test13147()
}


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

class C519 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tabs or otherwise weird indentation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fixed, but apparently github doesn't realize it.

invariant {
++x;
}
__gshared int x;
}

void test519a() {
auto s = new C519();
assert(C519.x == 0);
delete s;
assert(C519.x == 1);
}

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

struct S519 {
invariant() {
printf("S519.invariant\n");
++x;
}
__gshared int x;
}

void test519b() {
{
auto foo = new S519();
printf("lifetime of foo\n");
delete foo;
assert(S519.x == 1);
}
printf("test2\n");
{
auto foo = S519();
printf("lifetime of foo\n");
}
assert(S519.x == 2);
}


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

struct S519c {
invariant() {
printf("S519c.invariant\n");
++x;
}
__gshared int x;
int y;
}

void test519c() {
{
auto foo = new S519c(1);
printf("lifetime of foo\n");
delete foo;
assert(S519c.x == 2);
}
printf("test2\n");
{
auto foo = S519c(1);
printf("lifetime of foo\n");
}
assert(S519c.x == 4);
}


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

void main()
Expand All @@ -185,4 +254,7 @@ void main()
test6453();
test13113();
test13147();
test519a();
test519b();
test519c();
}