D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 2931 - Initialization struct with array from another struct
Summary: Initialization struct with array from another struct
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: x86 Linux
: P2 normal
Assignee: No Owner
URL:
Keywords: patch, wrong-code
Depends on:
Blocks:
 
Reported: 2009-05-03 18:12 UTC by Mihail Zenkov
Modified: 2017-08-09 15:04 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Mihail Zenkov 2009-05-03 18:12:58 UTC
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 Don 2010-07-28 05:34:56 UTC
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 Walter Bright 2010-08-05 20:34:54 UTC
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 Lars T. Kyllingstad 2010-08-13 01:47:24 UTC
Fixed DMD 2.048
Comment 4 github-bugzilla 2017-08-09 15:04:48 UTC
Commit pushed to newCTFE at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/dd2a04b1314a6a90b30c19691ed6d8bc2bfe1cd6
add bug2931 to function-blacklist