Bug 4500 – scoped moves class after calling the constructor

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
Other
OS
Linux
Creation time
2010-07-23T23:59:00Z
Last change time
2011-09-07T22:27:06Z
Keywords
patch
Assigned to
andrei
Creator
kamm-removethis

Attachments

IDFilenameSummaryContent-TypeSize
933scoped.dFixed scopedapplication/octet-stream2105

Comments

Comment #0 by kamm-removethis — 2010-07-23T23:59:57Z
As far as I remember a class is not supposed to move. class A { this() { a = this; } this(int i) { a = this; } A a; void check() { writeln(this is a); } } void main() { auto a1 = scoped!A; a1.check(); // fails auto a2 = scoped!A(1); a2.check(); // fails a1.a = a1; a1.check(); // ok now }
Comment #1 by andrei — 2010-07-25T09:48:34Z
Thanks for the catch! This is a serious problem indeed.
Comment #2 by samukha — 2010-07-26T01:59:01Z
I didn't know D structs were allowed to be moved without calling the copy constructor. Is it really the case? FWIW, modern C++ implementations would optimize the copy out. For example, the following C++ test passes with a recent GNU C++: template <typename T> class Scoped { char data[sizeof(T)]; public: T* payload() { return reinterpret_cast<T*>(data); } Scoped(int i) { new(payload()) T(i); } ~Scoped() { payload()->~T(); } }; template <typename T> Scoped<T> scoped(int i) { Scoped<T> s(i); return s; } class A { public: A() { a = this; } A(int i) { a = this; } A *a; void check() { std::cout << (this == a ? "true" : "false") << std::endl; } ~A() { std::cout << "~A dtor" << std::endl; } }; int main(int argc, char *argv[]) { Scoped<A> a2 = scoped<A>(1); a2.payload()->check(); // ok } Anyway, it is not reasonable to base a fundamental feature like 'scoped' on RVO without having the latter in the language specification.
Comment #3 by andrei — 2010-07-26T03:19:53Z
The language specifies that returning a stack-allocated object by value from a function does not invoke the constructor. Currently the compiler is not up to the specification.
Comment #4 by samukha — 2010-07-26T04:01:35Z
But does it specify that the object should not be moved? Currently, the struct is constructed on the callee's frame and then blitted (moved) to the caller's frame, though the compiler can optimize the blit out (as GNU C++ does). If this kind of RVO is not specified, obviously 'scoped' cannot rely on it and will remain broken even if dmd will eventually be able to apply the optimization.
Comment #5 by k.hara.pg — 2011-03-23T18:02:28Z
Created attachment 933 Fixed scoped I tried to fix this issue. It succeeded, but resulting code includes ugly hack.
Comment #6 by k.hara.pg — 2011-03-23T18:11:08Z
(In reply to comment #5) > Created an attachment (id=933) [details] > Fixed scoped > > I tried to fix this issue. > It succeeded, but resulting code includes ugly hack. I worked on 64bit Windows 7.
Comment #7 by k.hara.pg — 2011-03-26T00:38:09Z
I posted issue 5777 and attached experimental dmd patch.
Comment #8 by k.hara.pg — 2011-07-17T06:54:56Z