www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Presence of struct destructor makes lvalue?

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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 good 

 Troubles seems to come from
 


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 = 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
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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 Hara

Thank you! :) You've already fixed it! (Pending merge...) Ali
Apr 08 2013
prev sibling parent kenji hara <k.hara.pg gmail.com> writes:
--f46d0435c01097a7fd04d9e41a45
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

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:

 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 good

 Troubles seems to come from
 https://github.com/D-**Programming-Language/dmd/blob/**



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

--f46d0435c01097a7fd04d9e41a45 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div>This is definitely a bug.<br></div><div><br></div><di= v><a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D9907">http://d= .puremagic.com/issues/show_bug.cgi?id=3D9907</a>=C2=A0<br></div><div class= =3D"gmail_extra"> <br></div><div class=3D"gmail_extra">Kenji Hara<br><br><div class=3D"gmail_= quote">2013/4/9 Ali =C3=87ehreli <span dir=3D"ltr">&lt;<a href=3D"mailto:ac= ehreli yahoo.com" target=3D"_blank">acehreli yahoo.com</a>&gt;</span><br><b= lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px = #ccc solid;padding-left:1ex"> <div class=3D"im">On 04/08/2013 12:24 PM, Maxim Fomin wrote:<br> <br> &gt; DMD often inserts temporaries when they are unexpected (or users do no= t<br> &gt; expect when they should).<br> &gt;<br> &gt; D main function in destructor case is rewritten as:<br> &gt;<br> &gt; =C2=A0 =C2=A0 S s =3D S(1);<br> &gt; =C2=A0 =C2=A0 s.opAssign(foo(2));<br> &gt; =C2=A0 =C2=A0 s.opAssign((S __sl1779 =3D S(3); , __sl1779))<br> <br></div> Have you manually typed those lines or is there a tool that outputs that &q= uot;preprocessor&quot; ;) output?<div class=3D"im"><br> <br> &gt;<br> &gt; Hence, ref version is taken in account because &#39;__sl1779&#39; is a= good lvalue.<br> &gt;<br> &gt; Troubles seems to come from<br> &gt; <a href=3D"https://github.com/D-Programming-Language/dmd/blob/master/s= rc/expression.c#L4203" target=3D"_blank">https://github.com/D-<u></u>Progra= mming-Language/dmd/blob/<u></u>master/src/expression.c#L4203</a> <br> &gt;<br> <br></div> Thank you very much for finding the related line. :) Quoting:<br> <br> Expression *StructLiteralExp::semantic(<u></u>Scope *sc)<br> { Expression *e;<br> <br> // ...<br> <br> =C2=A0 =C2=A0 /* If struct requires a destructor, rewrite as:<br> =C2=A0 =C2=A0 =C2=A0* (S tmp =3D S()),tmp<br> =C2=A0 =C2=A0 =C2=A0* so that the destructor can be hung on tmp.<br> =C2=A0 =C2=A0 =C2=A0*/<br> =C2=A0 =C2=A0 if (sd-&gt;dtor &amp;&amp; sc-&gt;func)<br> =C2=A0 =C2=A0 {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Identifier *idtmp =3D Lexer::uniqueId(&quot;__s= l&quot;);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 VarDeclaration *tmp =3D new VarDeclaration(loc,= type, idtmp, new ExpInitializer(0, this));<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 tmp-&gt;storage_class |=3D STCctfe;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Expression *ae =3D new DeclarationExp(loc, tmp)= ;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Expression *e =3D new CommaExp(loc, ae, new Var= Exp(loc, tmp));<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 e =3D e-&gt;semantic(sc);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 return e;<br> =C2=A0 =C2=A0 }<br> <br> =C2=A0 =C2=A0 return this;<br> }<br> <br> Is it because destructors cannot be &quot;hung&quot; on literals?<br> <br> It is inconsistent that function-returned rvalues do not behave the same as= literal-rvalues.<span class=3D"HOEnZb"><font color=3D"#888888"><br> <br> Ali<br> <br> </font></span></blockquote></div><br></div></div> --f46d0435c01097a7fd04d9e41a45--
Apr 08 2013