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








=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com>