mirror of https://github.com/rui314/chibicc
Handle struct initializers for local variables
This commit is contained in:
parent
b15b929b53
commit
4fc741d109
34
parse.c
34
parse.c
|
@ -682,7 +682,8 @@ static void global_var(void) {
|
|||
typedef struct Designator Designator;
|
||||
struct Designator {
|
||||
Designator *next;
|
||||
int idx;
|
||||
int idx; // array
|
||||
Member *mem; // struct
|
||||
};
|
||||
|
||||
// Creates a node for an array access. For example, if var represents
|
||||
|
@ -693,6 +694,13 @@ static Node *new_desg_node2(Var *var, Designator *desg, Token *tok) {
|
|||
return new_var_node(var, tok);
|
||||
|
||||
Node *node = new_desg_node2(var, desg->next, tok);
|
||||
|
||||
if (desg->mem) {
|
||||
node = new_unary(ND_MEMBER, node, desg->mem->tok);
|
||||
node->member = desg->mem;
|
||||
return node;
|
||||
}
|
||||
|
||||
node = new_add(node, new_num(desg->idx, tok), tok);
|
||||
return new_unary(ND_DEREF, node, tok);
|
||||
}
|
||||
|
@ -730,6 +738,9 @@ static Node *lvar_init_zero(Node *cur, Var *var, Type *ty, Designator *desg) {
|
|||
// x[1][1]=5;
|
||||
// x[1][2]=6;
|
||||
//
|
||||
// Struct members are initialized in declaration order. For example,
|
||||
// `struct { int a; int b; } x = {1, 2}` sets x.a to 1 and x.b to 2.
|
||||
//
|
||||
// There are a few special rules for ambiguous initializers and
|
||||
// shorthand notations:
|
||||
//
|
||||
|
@ -799,6 +810,27 @@ static Node *lvar_initializer2(Node *cur, Var *var, Type *ty, Designator *desg)
|
|||
return cur;
|
||||
}
|
||||
|
||||
if (ty->kind == TY_STRUCT) {
|
||||
expect("{");
|
||||
Member *mem = ty->members;
|
||||
|
||||
if (!peek("}")) {
|
||||
do {
|
||||
Designator desg2 = {desg, 0, mem};
|
||||
cur = lvar_initializer2(cur, var, mem->ty, &desg2);
|
||||
mem = mem->next;
|
||||
} while (!peek_end() && consume(","));
|
||||
}
|
||||
expect_end();
|
||||
|
||||
// Set excess struct elements to zero.
|
||||
for (; mem; mem = mem->next) {
|
||||
Designator desg2 = {desg, 0, mem};
|
||||
cur = lvar_init_zero(cur, var, mem->ty, &desg2);
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
cur->next = new_desg_node(var, desg, assign());
|
||||
return cur->next;
|
||||
}
|
||||
|
|
17
tests
17
tests
|
@ -506,6 +506,23 @@ int main() {
|
|||
assert(16, ({ int x[]={1,2,3,4}; sizeof(x); }), "int x[]={1,2,3,4}; sizeof(x);");
|
||||
assert(4, ({ char x[]="foo"; sizeof(x); }), "char x[]=\"foo\"; sizeof(x); }");
|
||||
|
||||
assert(1, ({ struct {int a; int b; int c;} x={1,2,3}; x.a; }), "struct {int a; int b; int c;} x={1,2,3}; x.a;");
|
||||
assert(2, ({ struct {int a; int b; int c;} x={1,2,3}; x.b; }), "struct {int a; int b; int c;} x={1,2,3}; x.b;");
|
||||
assert(3, ({ struct {int a; int b; int c;} x={1,2,3}; x.c; }), "struct {int a; int b; int c;} x={1,2,3}; x.c;");
|
||||
assert(1, ({ struct {int a; int b; int c;} x={1}; x.a; }), "struct {int a; int b; int c;} x={1}; x.a;");
|
||||
assert(0, ({ struct {int a; int b; int c;} x={1}; x.b; }), "struct {int a; int b; int c;} x={1}; x.b;");
|
||||
assert(0, ({ struct {int a; int b; int c;} x={1}; x.c; }), "struct {int a; int b; int c;} x={1}; x.c;");
|
||||
|
||||
assert(1, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].a; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].a;");
|
||||
assert(2, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].b; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].b;");
|
||||
assert(3, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].a; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].a;");
|
||||
assert(4, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].b; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].b;");
|
||||
|
||||
assert(0, ({ struct {int a; int b;} x[2]={{1,2}}; x[1].b; }), "struct {int a; int b;} x[2]={{1,2}}; x[1].b;");
|
||||
|
||||
assert(0, ({ struct {int a; int b;} x={}; x.a; }), "struct {int a; int b;} x={}; x.a;");
|
||||
assert(0, ({ struct {int a; int b;} x={}; x.b; }), "struct {int a; int b;} x={}; x.b;");
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue