From 5a235b87ddbbdd01e08106ce099f31c72b670043 Mon Sep 17 00:00:00 2001 From: k-hara Date: Wed, 10 Feb 2016 00:05:54 +0900 Subject: [PATCH] fix Issue 15661 - Destructor called while object still alive By the PR #4078, some preparation code has been inserted before a constructor call expression. Then, `AssignExp` had failed to recognize the ctor call form. --- src/expression.d | 19 ++++++++++++----- test/runnable/sdtor.d | 47 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/expression.d b/src/expression.d index 19441c2b4c27..a90b3894b191 100644 --- a/src/expression.d +++ b/src/expression.d @@ -1660,7 +1660,7 @@ extern (C++) bool functionParameters(Loc loc, Scope* sc, TypeFunction tf, Type t } if (tb.ty == Tstruct) { - // arg = callCpCtor(sc, arg); + //arg = callCpCtor(sc, arg); } // Give error for overloaded function addresses if (arg.op == TOKsymoff) @@ -11918,13 +11918,18 @@ public: Type t2 = e2x.type.toBasetype(); if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym) { + // Bugzilla 15661: Look for the form from last of comma chain. + auto e2y = e2x; + while (e2y.op == TOKcomma) + e2y = (cast(CommaExp)e2y).e2; + CallExp ce; DotVarExp dve; if (sd.ctor && - e2x.op == TOKcall && - (ce = cast(CallExp)e2x, ce.e1.op == TOKdotvar) && + e2y.op == TOKcall && + (ce = cast(CallExp)e2y, ce.e1.op == TOKdotvar) && (dve = cast(DotVarExp)ce.e1, dve.var.isCtorDeclaration()) && - e2x.type.implicitConvTo(t1)) + e2y.type.implicitConvTo(t1)) { /* Look for form of constructor call which is: * __ctmp.ctor(arguments...) @@ -11956,7 +11961,11 @@ public: CallExp cx = cast(CallExp)ce.copy(); cx.e1 = dvx; - Expression e = new CommaExp(loc, ae, cx); + Expression e0; + extractLast(e2x, &e0); + + auto e = combine(ae, cx); + e = combine(e0, e); e = e.semantic(sc); return e; } diff --git a/test/runnable/sdtor.d b/test/runnable/sdtor.d index 97208a96bdbb..7a7a17b9557f 100644 --- a/test/runnable/sdtor.d +++ b/test/runnable/sdtor.d @@ -4178,8 +4178,8 @@ struct S63 this(int x) { - assert(p == 87); - p += x; + assert(p == 87); + p += x; } ~this() { } @@ -4190,7 +4190,7 @@ struct S63 static void tester() { - S63(3).funky(); + S63(3).funky(); } } @@ -4199,6 +4199,46 @@ void test63() S63.tester(); } +/**********************************/ +// 15661 + +struct X15661 +{ + ~this() {} +} + +X15661 createX15661() { return X15661(); } + +struct Y15661 +{ + static int dtor; + + @disable this(); + @disable this(this); + this(X15661 a1, X15661 a2) {} + ~this() { ++dtor; } +} + +struct Z15661 +{ + this(int) + { + b = Y15661(createX15661(), createX15661()); + assert(Y15661.dtor == 0); + } + + private Y15661 b; +} + +void test15661() +{ + { + auto v = Z15661(5); + assert(Y15661.dtor == 0); + } + assert(Y15661.dtor == 1); +} + /**********************************/ int main() @@ -4320,6 +4360,7 @@ int main() test14696(); test14838(); test63(); + test15661(); printf("Success\n"); return 0;