mirror of https://github.com/rui314/chibicc
Allow to initialize struct flexible array member
This commit is contained in:
parent
824543bb2f
commit
cd688a89b8
|
@ -243,6 +243,7 @@ struct Type {
|
|||
|
||||
// Struct
|
||||
Member *members;
|
||||
bool is_flexible;
|
||||
|
||||
// Function type
|
||||
Type *return_ty;
|
||||
|
|
45
parse.c
45
parse.c
|
@ -256,8 +256,16 @@ static Initializer *new_initializer(Type *ty, bool is_flexible) {
|
|||
|
||||
init->children = calloc(len, sizeof(Initializer *));
|
||||
|
||||
for (Member *mem = ty->members; mem; mem = mem->next)
|
||||
init->children[mem->idx] = new_initializer(mem->ty, false);
|
||||
for (Member *mem = ty->members; mem; mem = mem->next) {
|
||||
if (is_flexible && ty->is_flexible && !mem->next) {
|
||||
Initializer *child = calloc(1, sizeof(Initializer));
|
||||
child->ty = mem->ty;
|
||||
child->is_flexible = true;
|
||||
init->children[mem->idx] = child;
|
||||
} else {
|
||||
init->children[mem->idx] = new_initializer(mem->ty, false);
|
||||
}
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
|
@ -814,9 +822,38 @@ static void initializer2(Token **rest, Token *tok, Initializer *init) {
|
|||
init->expr = assign(rest, tok);
|
||||
}
|
||||
|
||||
static Type *copy_struct_type(Type *ty) {
|
||||
ty = copy_type(ty);
|
||||
|
||||
Member head = {};
|
||||
Member *cur = &head;
|
||||
for (Member *mem = ty->members; mem; mem = mem->next) {
|
||||
Member *m = calloc(1, sizeof(Member));
|
||||
*m = *mem;
|
||||
cur = cur->next = m;
|
||||
}
|
||||
|
||||
ty->members = head.next;
|
||||
return ty;
|
||||
}
|
||||
|
||||
static Initializer *initializer(Token **rest, Token *tok, Type *ty, Type **new_ty) {
|
||||
Initializer *init = new_initializer(ty, true);
|
||||
initializer2(rest, tok, init);
|
||||
|
||||
if ((ty->kind == TY_STRUCT || ty->kind == TY_UNION) && ty->is_flexible) {
|
||||
ty = copy_struct_type(ty);
|
||||
|
||||
Member *mem = ty->members;
|
||||
while (mem->next)
|
||||
mem = mem->next;
|
||||
mem->ty = init->children[mem->idx]->ty;
|
||||
ty->size += mem->ty->size;
|
||||
|
||||
*new_ty = ty;
|
||||
return init;
|
||||
}
|
||||
|
||||
*new_ty = init->ty;
|
||||
return init;
|
||||
}
|
||||
|
@ -1709,8 +1746,10 @@ static void struct_members(Token **rest, Token *tok, Type *ty) {
|
|||
// If the last element is an array of incomplete type, it's
|
||||
// called a "flexible array member". It should behave as if
|
||||
// if were a zero-sized array.
|
||||
if (cur != &head && cur->ty->kind == TY_ARRAY && cur->ty->array_len < 0)
|
||||
if (cur != &head && cur->ty->kind == TY_ARRAY && cur->ty->array_len < 0) {
|
||||
cur->ty = array_of(cur->ty->base, 0);
|
||||
ty->is_flexible = true;
|
||||
}
|
||||
|
||||
*rest = tok->next;
|
||||
ty->members = head.next;
|
||||
|
|
|
@ -28,6 +28,14 @@ struct {int a[2];} g41[2] = {1, 2, 3, 4};
|
|||
char g43[][4] = {'f', 'o', 'o', 0, 'b', 'a', 'r', 0};
|
||||
char *g44 = {"foo"};
|
||||
|
||||
typedef char T60[];
|
||||
T60 g60 = {1, 2, 3};
|
||||
T60 g61 = {1, 2, 3, 4, 5, 6};
|
||||
|
||||
typedef struct { char a, b[]; } T65;
|
||||
T65 g65 = {'f','o','o',0};
|
||||
T65 g66 = {'f','o','o','b','a','r',0};
|
||||
|
||||
int main() {
|
||||
ASSERT(1, ({ int x[3]={1,2,3}; x[0]; }));
|
||||
ASSERT(2, ({ int x[3]={1,2,3}; x[1]; }));
|
||||
|
@ -165,6 +173,14 @@ int main() {
|
|||
ASSERT(1, ({ union {int a; char b;} x={1,}; x.a; }));
|
||||
ASSERT(2, ({ enum {x,y,z,}; z; }));
|
||||
|
||||
ASSERT(3, sizeof(g60));
|
||||
ASSERT(6, sizeof(g61));
|
||||
|
||||
ASSERT(4, sizeof(g65));
|
||||
ASSERT(7, sizeof(g66));
|
||||
ASSERT(0, strcmp(g65.b, "oo"));
|
||||
ASSERT(0, strcmp(g66.b, "oobar"));
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue