Bug 2931 – Initialization struct with array from another struct

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Linux
Creation time
2009-05-03T18:12:00Z
Last change time
2017-08-09T15:04:48Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
mihail.zenkov

Comments

Comment #0 by mihail.zenkov — 2009-05-03T18:12:58Z
This example work fine: import std.stdio: writefln; struct D2 { double val[2]; } void main() { D2 p = { 1 }; double zoom = 2; double move = 3; double scale = 4; writefln("p.val[0]=", p.val[0]); writefln("p.val[1]=", p.val[1]); writefln("zoom=", zoom); writefln("move=", move); writefln("scale=", scale); } and return: p.val[0]=1 p.val[1]=1 zoom=2 move=3 scale=4 But if i try same in struct: import std.stdio: writefln; struct D2 { double val[2]; } struct view { D2 p = { 1 }; double zoom = 2; double move = 3; double scale = 4; } void main() { view v; writefln("p.val[0]=", v.p.val[0]); writefln("p.val[1]=", v.p.val[1]); writefln("zoom=", v.zoom); writefln("move=", v.move); writefln("scale=", v.scale); } i have: p.val[0]=1 p.val[1]=nan zoom=nan move=2 scale=3
Comment #1 by clugdbug — 2010-07-28T05:34:56Z
Here's a reduced test case. The fact that the static assert passes shows that it's not a front-end bug. The bug only happens when an array is block-initialized. -------- struct Bug2931 { int val[3][4]; } struct Outer2931 { Bug2931 p = Bug2931(67); // Applies to struct static initializers too int zoom = 2; int move = 3; int scale = 4; } int bug2931() { Outer2931 v; assert(v.move==3); return v.zoom; } static assert(bug2931()==2); void main() { assert(bug2931()==2); } CAUSE: todt.c, StructLiteralExp::toDt() contains code which seems to be completely erroneous. It duplicates the array initializer multiple times. The test suite still passes when it is removed. PATCH: todt.c, Line 690, in svn 589. if (v->offset < offset) error("duplicate union initialization for %s", v->toChars()); else { unsigned sz = dt_size(d); unsigned vsz = v->type->size(); unsigned voffset = v->offset; assert(sz <= vsz); - unsigned dim = 1; - for (Type *vt = v->type->toBasetype(); - vt->ty == Tsarray; - vt = vt->nextOf()->toBasetype()) - { TypeSArray *tsa = (TypeSArray *)vt; - dim *= tsa->dim->toInteger(); - } - for (size_t i = 0; i < dim; i++) - { if (offset < voffset) pdt = dtnzeros(pdt, voffset - offset); if (!d) { if (v->init) d = v->init->toDt(); else v->type->toDt(&d); } pdt = dtcat(pdt, d); d = NULL; offset = voffset + sz; voffset += vsz / dim; if (sz == vsz) break; - }
Comment #2 by bugzilla — 2010-08-05T20:34:54Z
The problem is that the rest of the array is filled in with the array initializer, rather than the element initializer. This overflows the array. http://www.dsource.org/projects/dmd/changeset/602
Comment #3 by bugzilla — 2010-08-13T01:47:24Z
Fixed DMD 2.048
Comment #4 by github-bugzilla — 2017-08-09T15:04:48Z