Bug 11394 – NRVO should work for object field initialization in constructor

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-30T19:18:00Z
Last change time
2013-11-08T00:57:24Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
k.hara.pg

Comments

Comment #0 by k.hara.pg — 2013-10-30T19:18:09Z
Spin-off issue from http://d.puremagic.com/issues/show_bug.cgi?id=11343#c15 At the line 18, NRVO should work, then p1, p2, p3 should print same address. extern(C) int printf(const char*, ...); static int[3] make(in int x, out const(int)* p) pure { typeof(return) a; a[0] = x; a[1] = x + 1; a[2] = x + 2; p = a.ptr; return a; } struct Bar { immutable int[3] arr; this(int x, out const(int)* p2) { const(int)* p1; this.arr = make(x, p1); // Line 18: NRVO should work p2 = this.arr.ptr; printf("p1 = %p\np2 = %p\n", p1, p2); //assert(p1 == p2); } } void main() { const(int)* p2; auto b = Bar(5, p2); const(int)* p3 = b.arr.ptr; printf("p3 = %p\n", p3); //assert(p2 == p3); }
Comment #1 by k.hara.pg — 2013-11-01T09:05:53Z
Sorry the OP code is incorrect, because the make function cannot have strong purity. Correct test case is: debug = NRVO; debug(NRVO) static void* pa, pb, pc; static int[3] make(in int x) pure { typeof(return) a; a[0] = x; a[1] = x + 1; a[2] = x + 2; debug(NRVO) pa = cast(void*)a.ptr; return a; } struct Bar { immutable int[3] arr; this(int x) { this.arr = make(x); // NRVO should work debug(NRVO) pb = cast(void*)this.arr.ptr; } } void main() { auto b = Bar(5); debug(NRVO) pc = cast(void*)b.arr.ptr; debug(NRVO) assert(pa == pb); debug(NRVO) assert(pb == pc); }
Comment #2 by k.hara.pg — 2013-11-01T09:06:04Z
Comment #3 by github-bugzilla — 2013-11-08T00:06:39Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/6f80983044a55580e81e7f723e5b71f05650caa4 fix Issue 11394 - NRVO should work for object field initialization in constructor
Comment #4 by bearophile_hugs — 2013-11-08T00:57:24Z
(In reply to comment #3) > Commit pushed to master at https://github.com/D-Programming-Language/dmd > > https://github.com/D-Programming-Language/dmd/commit/6f80983044a55580e81e7f723e5b71f05650caa4 > fix Issue 11394 - NRVO should work for object field initialization in > constructor The asm of two constructors isn't equal, but the situation has improved and now there is no call to the array copy: import std.traits: Unqual; struct Foo { int[3] arr; this(int x) pure nothrow { arr[0] = x; arr[1] = x + 1; arr[2] = x + 2; } } struct Bar { immutable int[3] arr; this(int x) pure nothrow { static Unqual!(typeof(arr)) make(in int x) pure nothrow { typeof(return) a; a[0] = x; a[1] = x + 1; a[2] = x + 2; return a; } this.arr = make(x); // NRVO works? } } void main() { auto f = Foo(5); auto b = Bar(5); } Foo.__ctor: push EBX mov EDX, EAX mov EBX, 8[ESP] push ESI lea ECX, 1[EBX] lea ESI, 2[EBX] mov [EDX], EBX mov 4[EDX], ECX mov 8[EDX], ESI pop ESI pop EBX ret 4 Bar.__ctor: push EBX mov EBX, 8[ESP] xor ECX, ECX push ESI mov EDX, EAX lea ESI, 1[EBX] push EDI lea EDI, 2[EBX] mov [EAX], ECX mov 4[EAX], ECX mov 8[EAX], ECX mov [EDX], EBX mov 4[EDX], ESI mov 8[EDX], EDI pop EDI pop ESI pop EBX ret 4