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;
|
typedef struct Designator Designator;
|
||||||
struct Designator {
|
struct Designator {
|
||||||
Designator *next;
|
Designator *next;
|
||||||
int idx;
|
int idx; // array
|
||||||
|
Member *mem; // struct
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a node for an array access. For example, if var represents
|
// 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);
|
return new_var_node(var, tok);
|
||||||
|
|
||||||
Node *node = new_desg_node2(var, desg->next, 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);
|
node = new_add(node, new_num(desg->idx, tok), tok);
|
||||||
return new_unary(ND_DEREF, node, 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][1]=5;
|
||||||
// x[1][2]=6;
|
// 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
|
// There are a few special rules for ambiguous initializers and
|
||||||
// shorthand notations:
|
// shorthand notations:
|
||||||
//
|
//
|
||||||
|
@ -799,6 +810,27 @@ static Node *lvar_initializer2(Node *cur, Var *var, Type *ty, Designator *desg)
|
||||||
return cur;
|
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());
|
cur->next = new_desg_node(var, desg, assign());
|
||||||
return cur->next;
|
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(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(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");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue