diff --git a/parse.c b/parse.c index 0699f9fb559af13429d0cec980ef6602c266894e..8f83690af53165a1b7f3007a626c7f652005e731 100644 --- a/parse.c +++ b/parse.c @@ -700,8 +700,21 @@ static Node *new_desg_node(Var *var, Designator *desg, Node *rhs) { return new_unary(ND_EXPR_STMT, node, rhs->tok); } +static Node *lvar_init_zero(Node *cur, Var *var, Type *ty, Designator *desg) { + if (ty->kind == TY_ARRAY) { + for (int i = 0; i < ty->array_len; i++) { + Designator desg2 = {desg, i++}; + cur = lvar_init_zero(cur, var, ty->base, &desg2); + } + return cur; + } + + cur->next = new_desg_node(var, desg, new_num(0, token)); + return cur->next; +} + // lvar-initializer2 = assign -// | "{" lvar-initializer2 ("," lvar-initializer2)* ","? "}" +// | "{" (lvar-initializer2 ("," lvar-initializer2)* ","?)? "}" // // An initializer for a local variable is expanded to multiple // assignments. For example, this function creates the following @@ -713,17 +726,27 @@ static Node *new_desg_node(Var *var, Designator *desg, Node *rhs) { // x[1][0]=4; // x[1][1]=5; // x[1][2]=6; +// +// If an initializer list is shorter than an array, excess array +// elements are initialized with 0. static Node *lvar_initializer2(Node *cur, Var *var, Type *ty, Designator *desg) { if (ty->kind == TY_ARRAY) { expect("{"); int i = 0; - do { - Designator desg2 = {desg, i++}; - cur = lvar_initializer2(cur, var, ty->base, &desg2); - } while (!peek_end() && consume(",")); - + if (!peek("}")) { + do { + Designator desg2 = {desg, i++}; + cur = lvar_initializer2(cur, var, ty->base, &desg2); + } while (!peek_end() && consume(",")); + } expect_end(); + + // Set excess array elements to zero. + while (i < ty->array_len) { + Designator desg2 = {desg, i++}; + cur = lvar_init_zero(cur, var, ty->base, &desg2); + } return cur; } diff --git a/tests b/tests index 748803bd081446d7a1c28f9096e61886b6011003..1bdd9aa952a6765ebc1d62ed9fca70490cd87b0a 100644 --- a/tests +++ b/tests @@ -482,10 +482,18 @@ int main() { assert(3, ({ int x[3]={1,2,3}; x[2]; }), "int x[3]={1,2,3}; x[0];"); assert(3, ({ int x[3]={1,2,3,}; x[2]; }), "int x[3]={1,2,3}; x[0];"); + assert(0, ({ int x[3]={}; x[0]; }), "int x[3]={}; x[0];"); + assert(0, ({ int x[3]={}; x[1]; }), "int x[3]={}; x[1];"); + assert(0, ({ int x[3]={}; x[2]; }), "int x[3]={}; x[2];"); + assert(2, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[0][1]; }), "int x[2][3]={{1,2,3},{4,5,6}}; x[0][1];"); assert(4, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[1][0]; }), "int x[2][3]={{1,2,3},{4,5,6}}; x[1][0];"); assert(6, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[1][2]; }), "int x[2][3]={{1,2,3},{4,5,6}}; x[1][2];"); + assert(2, ({ int x[2][3]={{1,2}}; x[0][1]; }), "int x[2][3]={{1,2}}; x[0][1];"); + assert(0, ({ int x[2][3]={{1,2}}; x[1][0]; }), "int x[2][3]={{1,2}}; x[1][0];"); + assert(0, ({ int x[2][3]={{1,2}}; x[1][2]; }), "int x[2][3]={{1,2}}; x[1][2];"); + printf("OK\n"); return 0; }