diff --git a/parse.c b/parse.c index ca06a79..77144d7 100644 --- a/parse.c +++ b/parse.c @@ -890,21 +890,45 @@ static void designation(Token **rest, Token *tok, Initializer *init) { initializer2(rest, tok, init); } +// An array length can be omitted if an array has an initializer +// (e.g. `int x[] = {1,2,3}`). If it's omitted, count the number +// of initializer elements. static int count_array_init_elements(Token *tok, Type *ty) { - Initializer *dummy = new_initializer(ty->base, false); - int i = 0; + bool first = true; + Initializer *dummy = new_initializer(ty->base, true); - for (; !consume_end(&tok, tok); i++) { - if (i > 0) + int i = 0, max = 0; + + while (!consume_end(&tok, tok)) { + if (!first) tok = skip(tok, ","); - initializer2(&tok, tok, dummy); + first = false; + + if (equal(tok, "[")) { + i = const_expr(&tok, tok->next); + if (equal(tok, "...")) + i = const_expr(&tok, tok->next); + tok = skip(tok, "]"); + designation(&tok, tok, dummy); + } else { + initializer2(&tok, tok, dummy); + } + + i++; + max = MAX(max, i); } - return i; + return max; } // array-initializer1 = "{" initializer ("," initializer)* ","? "}" static void array_initializer1(Token **rest, Token *tok, Initializer *init) { tok = skip(tok, "{"); + + if (init->is_flexible) { + int len = count_array_init_elements(tok, init->ty); + *init = *new_initializer(array_of(init->ty->base, len), false); + } + bool first = true; if (init->is_flexible) { diff --git a/test/initializer.c b/test/initializer.c index 2312ac6..c13e379 100644 --- a/test/initializer.c +++ b/test/initializer.c @@ -202,6 +202,17 @@ int main() { ASSERT(7, ((int[10]){ [3]=7 })[3]); ASSERT(0, ((int[10]){ [3]=7 })[4]); + ASSERT(10, ({ char x[]={[10-3]=1,2,3}; sizeof(x); })); + ASSERT(20, ({ char x[][2]={[8][1]=1,2}; sizeof(x); })); + + 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; }