Merge pull request #15898 from WalterBright/fix24274

fix Issue 24274 - [REG master] ImportC: unrecognized C initializer wi…
This commit is contained in:
Dennis 2023-12-11 15:46:29 +01:00 committed by GitHub
commit 603be63f97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 25 deletions

View file

@ -572,7 +572,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null");
printf(" stc = x%llx\n", dsym.storage_class);
printf(" storage_class = x%llx\n", dsym.storage_class);
printf("linkage = %d\n", dsym.linkage);
printf("linkage = %d\n", dsym._linkage);
//if (strcmp(toChars(), "mul") == 0) assert(0);
}
//if (semanticRun > PASS.initial)

View file

@ -803,9 +803,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
Loop1:
for (size_t index = 0; index < ci.initializerList.length; )
{
CInitializer cprev;
size_t indexprev;
L1:
DesigInit di = ci.initializerList[index];
Designators* dlist = di.designatorList;
if (dlist)
@ -833,15 +830,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
continue Loop1;
}
}
if (cprev)
{
/* The peeling didn't work, so unpeel it
*/
ci = cprev;
index = indexprev;
di = ci.initializerList[index];
goto L2;
}
error(ci.loc, "`.%s` is not a field of `%s`\n", id.toChars(), sd.toChars());
return err();
}
@ -849,18 +837,55 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
if (fieldi == nfields)
break;
if (index + 1 == ci.initializerList.length && di.initializer.isCInitializer())
auto ix = di.initializer;
/* If a C initializer is wrapped in a C initializer, with no designators,
* peel off the outer one
*/
if (ix.isCInitializer())
{
/* Try peeling off this set of { } and see if it works
*/
cprev = ci;
ci = di.initializer.isCInitializer();
indexprev = index;
index = 0;
goto L1;
CInitializer cix = ix.isCInitializer();
if (cix.initializerList.length == 1)
{
DesigInit dix = cix.initializerList[0];
if (!dix.designatorList)
{
Initializer inix = dix.initializer;
if (inix.isCInitializer())
ix = inix;
}
}
}
if (auto cix = ix.isCInitializer())
{
/* ImportC loses the structure from anonymous structs, but this is retained
* by the initializer syntax. if a CInitializer has a Designator, it is probably
* a nested anonymous struct
*/
if (cix.initializerList.length)
{
DesigInit dix = cix.initializerList[0];
Designators* dlistx = dix.designatorList;
if (dlistx && (*dlistx).length == 1 && (*dlistx)[0].ident)
{
auto id = (*dlistx)[0].ident;
foreach (k, f; sd.fields[]) // linear search for now
{
if (f.ident == id)
{
fieldi = k;
si.addInit(id, dix.initializer);
++fieldi;
++index;
continue Loop1;
}
}
}
}
}
L2:
VarDeclaration field;
while (1) // skip field if it overlaps with previously seen fields
{
@ -871,10 +896,11 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
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();
@ -1013,7 +1039,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
else
{
error(ci.loc, "unrecognized C initializer `%s`", toChars(ci));
error(ci.loc, "unrecognized C initializer `%s` for type `%s`", toChars(ci), t.toChars());
return err();
}
}

View file

@ -55,10 +55,75 @@ struct S3
void test3()
{
struct S3 tn = (struct S3) {{0}, 4};
struct S3 tn = (struct S3) {{1}, 4};
assert(tn.context[0] == 1);
assert(tn.context[1] == 0);
assert(tn.context[2] == 0);
assert(tn.context[3] == 0);
assert(tn.id == 4);
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=24274
struct S0
{
struct
{
char short_data[24];
};
int length;
};
void test4()
{
struct S0 s0 = { {.short_data = {1}}, .length = 2};
assert(s0.short_data[0] == 1);
assert(s0.length == 2);
}
/**************************************/
struct S1
{
struct
{
int long_data;
char short_data[24];
};
int length;
};
void test5()
{
struct S1 s1 = { {.short_data = {7}}, .length = 8};
assert(s1.long_data == 0);
assert(s1.short_data[0] == 7);
assert(s1.length == 8);
}
/**************************************/
struct S6
{
int abc[4];
};
void test6()
{
struct S6 s = {{4},5,6,7};
assert(s.abc[0] == 4);
assert(s.abc[1] == 0);
assert(s.abc[2] == 0);
assert(s.abc[3] == 0);
struct S6 t = {4,{5},6,7};
assert(t.abc[0] == 4);
assert(t.abc[1] == 5);
assert(t.abc[2] == 6);
assert(t.abc[3] == 7);
}
/**************************************/
int main()
@ -66,5 +131,8 @@ int main()
test1();
test2();
test3();
test4();
test5();
test6();
return 0;
}