Skip to content

Commit

Permalink
fix Issue 23348 - not handling braceless sub structs in initializers (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Sep 20, 2022
1 parent 194182a commit 58968d3
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 6 deletions.
53 changes: 47 additions & 6 deletions compiler/src/dmd/initsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
* index = index into ci.initializer, updated
* Returns: struct initializer for this substruct
*/
Initializer subStruct(TypeStruct ts, ref size_t index)
Initializer subStruct()(TypeStruct ts, ref size_t index)
{
//printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index);

Expand All @@ -739,19 +739,60 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
index = ci.initializerList.length;
return err();
}
const nfields = sd.nonHiddenFields();
const nfields = sd.fields.length;

foreach (n; 0 .. nfields)
foreach (fieldi; 0 .. nfields)
{
if (index >= ci.initializerList.length)
break; // ran out of initializers
auto di = ci.initializerList[index];
if (di.designatorList && n != 0)
if (di.designatorList && fieldi != 0)
break; // back to top level
else
{
si.addInit(null, di.initializer);
++index;
VarDeclaration field;
while (1) // skip field if it overlaps with previously seen fields
{
field = sd.fields[fieldi];
++fieldi;
if (!overlaps(field, sd.fields[], si))
break;
if (fieldi == nfields)
break;
}
auto tn = field.type.toBasetype();
auto tnsa = tn.isTypeSArray();
auto tns = tn.isTypeStruct();
auto ix = di.initializer;
if (tnsa && ix.isExpInitializer())
{
ExpInitializer ei = ix.isExpInitializer();
if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
{
si.addInit(field.ident, ei);
++index;
}
else
si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template
}
else if (tns && ix.isExpInitializer())
{
/* Disambiguate between an exp representing the entire
* struct, and an exp representing the first field of the struct
*/
if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
{
si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
++index;
}
else // field initializers for struct
si.addInit(field.ident, subStruct(tns, index)); // the first field
}
else
{
si.addInit(field.ident, ix);
++index;
}
}
}
//printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index);
Expand Down
28 changes: 28 additions & 0 deletions compiler/test/runnable/initializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,33 @@ void test45()
assert(t45.b[1] == 'c', __LINE__);
}

/*******************************************/
// https://issues.dlang.org/show_bug.cgi?id=23348

struct SS46 {
char a, b[2];
};

struct S46 {
struct SS46 ss;
char d;
};

static struct S46 s46 = { 1, 2, 3, 4 };
static struct S46 t46 = { 'a', "bc", 'd' };

void test46()
{
assert(s46.ss.a == 1, __LINE__);
assert(s46.ss.b[0] == 2, __LINE__);
assert(s46.ss.b[1] == 3, __LINE__);
assert(s46.d == 4, __LINE__);
assert(t46.ss.a == 'a', __LINE__);
assert(t46.ss.b[0] == 'b', __LINE__);
assert(t46.ss.b[1] == 'c', __LINE__);
assert(t46.d == 'd', __LINE__);
}

/*******************************************/

int main()
Expand Down Expand Up @@ -826,6 +853,7 @@ int main()
test43();
test44();
test45();
test46();

return 0;
}

0 comments on commit 58968d3

Please sign in to comment.