Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/ddmd/aggregate.d
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol

FuncDeclarations dtors; // Array of destructors
FuncDeclaration dtor; // aggregate destructor
FuncDeclaration fieldDtor; // aggregate destructor for just the fields

Expression getRTInfo; // pointer to GC info generated by object.RTInfo(this)

Expand Down
1 change: 1 addition & 0 deletions src/ddmd/aggregate.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class AggregateDeclaration : public ScopeDsymbol

FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
FuncDeclaration *fieldDtor; // aggregate destructor for just the fields

Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)

Expand Down
1 change: 1 addition & 0 deletions src/ddmd/clone.d
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,7 @@ extern (C++) FuncDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
ad.dtors.shift(dd);
ad.members.push(dd);
dd.semantic(sc);
ad.fieldDtor = dd;
}

FuncDeclaration xdtor = null;
Expand Down
31 changes: 30 additions & 1 deletion src/ddmd/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@ extern (C++) class FuncDeclaration : Declaration
}

// Do the semantic analysis on the internals of the function.
override final void semantic3(Scope* sc)
override void semantic3(Scope* sc)
{
VarDeclaration _arguments = null;

Expand Down Expand Up @@ -4678,6 +4678,35 @@ extern (C++) final class CtorDeclaration : FuncDeclaration
}
}

override final void semantic3(Scope* sc)
{
if (semanticRun >= PASSsemantic3)
return;

/* If any of the fields of the struct have a destructor, add
* scope (failure) { this.fieldDtor(); }
* as the first statement. It is not necessary to add it after
* each initialization of a field, because destruction of .init constructed
* structs should be benign.
*/
AggregateDeclaration ad = toParent2().isAggregateDeclaration();
if (ad && ad.fieldDtor)
{
/* Generate:
* scope (failure) { this.fieldDtor(); }
*/
Expression e = new ThisExp(loc);
e.type = ad.type.mutableOf();
e = new DotVarExp(loc, e, ad.fieldDtor, false);
e = new CallExp(loc, e);
auto sexp = new ExpStatement(loc, e);
auto s = new OnScopeStatement(loc, TOKon_scope_failure, sexp);

fbody = new CompoundStatement(loc, s, fbody);
}
FuncDeclaration.semantic3(sc);
}

override const(char)* kind() const
{
return "constructor";
Expand Down
33 changes: 33 additions & 0 deletions test/runnable/sdtor.d
Original file line number Diff line number Diff line change
Expand Up @@ -4195,6 +4195,38 @@ int test14860()
}
static assert(test14860());

/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=14246

struct A14246 {
int a = 3;
static string s;
this( int var ) { printf("A()\n"); a += var; s ~= "a"; }

~this() { printf("~A()\n"); s ~= "b"; }
}

struct B14246 {
int i;
A14246 a;

this( int var ) {
A14246.s ~= "c";
a = A14246(var+1);
throw new Exception("An exception");
}
}

void test14246() {
try {
auto b = B14246(2);
} catch( Exception ex ) {
printf("Caught ex\n");
A14246.s ~= "d";
}
assert(A14246.s == "cabd");
}

/**********************************/
// 14696

Expand Down Expand Up @@ -4577,6 +4609,7 @@ int main()
test14815();
test16197();
test14860();
test14246();
test14696();
test14838();
test63();
Expand Down