digitalmars.D - Presence of struct destructor makes lvalue?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (66/66) Apr 08 2013 The following program has two assignments from two rvalues:
- Maxim Fomin (10/10) Apr 08 2013 DMD often inserts temporaries when they are unexpected (or users
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (30/39) Apr 08 2013 Have you manually typed those lines or is there a tool that outputs that...
- kenji hara (5/49) Apr 08 2013 This is definitely a bug.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/5) Apr 08 2013 Thank you! :) You've already fixed it! (Pending merge...)
The following program has two assignments from two rvalues: import std.stdio; import std.string; // version = destructor_defined; struct S { int i; string info() const { return format("%s(%s)", &i, i); } void opAssign(S rhs) { writefln("%s from Rvalue %s", this.info(), rhs.info()); } void opAssign(ref S rhs) { writefln("%s from Lvalue %s", this.info(), rhs.info()); } version (destructor_defined) { ~this() { writefln("destroying %s", this.info()); } } } S foo(int i) { return S(i); } void main() { auto s = S(1); // Assignment from two kinds of rvalues s = foo(2); s = S(3); } The output indicates that the two assignments go to the "rvalue assignment operator": 7FFF36AA0B20(1) from Rvalue 7FFF36AA0B24(2) 7FFF36AA0B20(1) from Rvalue 7FFF36AA0B28(3) However, when S.~this() is defined (by e.g. uncommenting the 'version =' line), the second assignment involves an lvalue: 7FFF9571E7F8(1) from Rvalue 7FFF9571E750(2) destroying 7FFF9571E750(2) 7FFF9571E7F8(1) from Lvalue 7FFF9571E804(3) <-- HERE destroying 7FFF9571E804(3) destroying 7FFF9571E7F8(1) I suspect this has something to do with the compiler generated assignment logic: http://dlang.org/struct.html [quote] Struct assignment t=s is defined to be semantically equivalent to: t.opAssign(s); where opAssign is a member function of S: S* opAssign(ref const S s) { ... bitcopy *this into tmp ... ... bitcopy s into *this ... ... call destructor on tmp ... return this; } [/quote] It is not clear how the presence of ~this() changes the semantics. Bug? Thank you, Ali
Apr 08 2013
DMD often inserts temporaries when they are unexpected (or users do not expect when they should). D main function in destructor case is rewritten as: S s = S(1); s.opAssign(foo(2)); s.opAssign((S __sl1779 = S(3); , __sl1779)) Hence, ref version is taken in account because '__sl1779' is a good lvalue. Troubles seems to come from https://github.com/D-Programming-Language/dmd/blob/master/src/expression.c#L4203
Apr 08 2013
On 04/08/2013 12:24 PM, Maxim Fomin wrote:DMD often inserts temporaries when they are unexpected (or users do not expect when they should). D main function in destructor case is rewritten as: S s = S(1); s.opAssign(foo(2)); s.opAssign((S __sl1779 = S(3); , __sl1779))Have you manually typed those lines or is there a tool that outputs that "preprocessor" ;) output?Hence, ref version is taken in account because '__sl1779' is a goodlvalue.Troubles seems to come fromhttps://github.com/D-Programming-Language/dmd/blob/master/sr /expression.c#L4203Thank you very much for finding the related line. :) Quoting: Expression *StructLiteralExp::semantic(Scope *sc) { Expression *e; // ... /* If struct requires a destructor, rewrite as: * (S tmp = S()),tmp * so that the destructor can be hung on tmp. */ if (sd->dtor && sc->func) { Identifier *idtmp = Lexer::uniqueId("__sl"); VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this)); tmp->storage_class |= STCctfe; Expression *ae = new DeclarationExp(loc, tmp); Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); e = e->semantic(sc); return e; } return this; } Is it because destructors cannot be "hung" on literals? It is inconsistent that function-returned rvalues do not behave the same as literal-rvalues. Ali
Apr 08 2013
This is definitely a bug. http://d.puremagic.com/issues/show_bug.cgi?id=3D9907 Kenji Hara 2013/4/9 Ali =C3=87ehreli <acehreli yahoo.com>On 04/08/2013 12:24 PM, Maxim Fomin wrote:md/blob/master/src/expression.c#L4203>DMD often inserts temporaries when they are unexpected (or users do not expect when they should). D main function in destructor case is rewritten as: S s =3D S(1); s.opAssign(foo(2)); s.opAssign((S __sl1779 =3D S(3); , __sl1779))Have you manually typed those lines or is there a tool that outputs that "preprocessor" ;) output?Hence, ref version is taken in account because '__sl1779' is a goodlvalue.Troubles seems to come from https://github.com/D-**Programming-Language/dmd/blob/**master/src/expression.c#L4203<https://github.com/D-Programming-Language/d=Thank you very much for finding the related line. :) Quoting: Expression *StructLiteralExp::semantic(**Scope *sc) { Expression *e; // ... /* If struct requires a destructor, rewrite as: * (S tmp =3D S()),tmp * so that the destructor can be hung on tmp. */ if (sd->dtor && sc->func) { Identifier *idtmp =3D Lexer::uniqueId("__sl"); VarDeclaration *tmp =3D new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this)); tmp->storage_class |=3D STCctfe; Expression *ae =3D new DeclarationExp(loc, tmp); Expression *e =3D new CommaExp(loc, ae, new VarExp(loc, tmp)); e =3D e->semantic(sc); return e; } return this; } Is it because destructors cannot be "hung" on literals? It is inconsistent that function-returned rvalues do not behave the same as literal-rvalues. Ali
Apr 08 2013
On 04/08/2013 07:13 PM, kenji hara wrote:> This is definitely a bug.http://d.puremagic.com/issues/show_bug.cgi?id=9907 Kenji HaraThank you! :) You've already fixed it! (Pending merge...) Ali
Apr 08 2013