Skip to content

Commit

Permalink
Merge pull request #6816 from WalterBright/fix14246
Browse files Browse the repository at this point in the history
fix Issue 14246 - RAII - proper destruction of partially constructed …
merged-on-behalf-of: Andrei Alexandrescu <andralex@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Jun 11, 2017
2 parents c6c3c11 + 1e755c6 commit 6b3d406
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/ddmd/aggregate.d
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
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
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
Expand Up @@ -1102,7 +1102,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 @@ -4691,6 +4691,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
Expand Up @@ -4222,6 +4222,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 @@ -4605,6 +4637,7 @@ int main()
test14815();
test16197();
test14860();
test14246();
test14696();
test14838();
test63();
Expand Down

0 comments on commit 6b3d406

Please sign in to comment.