mirror of https://github.com/rui314/chibicc
Allow parentheses in initializers to be omitted
This commit is contained in:
parent
1eae5ae367
commit
efa0f3366d
57
parse.c
57
parse.c
|
@ -666,8 +666,8 @@ static int count_array_init_elements(Token *tok, Type *ty) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// array-initializer = "{" initializer ("," initializer)* "}"
|
// array-initializer1 = "{" initializer ("," initializer)* "}"
|
||||||
static void array_initializer(Token **rest, Token *tok, Initializer *init) {
|
static void array_initializer1(Token **rest, Token *tok, Initializer *init) {
|
||||||
tok = skip(tok, "{");
|
tok = skip(tok, "{");
|
||||||
|
|
||||||
if (init->is_flexible) {
|
if (init->is_flexible) {
|
||||||
|
@ -686,8 +686,23 @@ static void array_initializer(Token **rest, Token *tok, Initializer *init) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct-initializer = "{" initializer ("," initializer)* "}"
|
// array-initializer2 = initializer ("," initializer)*
|
||||||
static void struct_initializer(Token **rest, Token *tok, Initializer *init) {
|
static void array_initializer2(Token **rest, Token *tok, Initializer *init) {
|
||||||
|
if (init->is_flexible) {
|
||||||
|
int len = count_array_init_elements(tok, init->ty);
|
||||||
|
*init = *new_initializer(array_of(init->ty->base, len), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < init->ty->array_len && !equal(tok, "}"); i++) {
|
||||||
|
if (i > 0)
|
||||||
|
tok = skip(tok, ",");
|
||||||
|
initializer2(&tok, tok, init->children[i]);
|
||||||
|
}
|
||||||
|
*rest = tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct-initializer1 = "{" initializer ("," initializer)* "}"
|
||||||
|
static void struct_initializer1(Token **rest, Token *tok, Initializer *init) {
|
||||||
tok = skip(tok, "{");
|
tok = skip(tok, "{");
|
||||||
|
|
||||||
Member *mem = init->ty->members;
|
Member *mem = init->ty->members;
|
||||||
|
@ -705,12 +720,28 @@ static void struct_initializer(Token **rest, Token *tok, Initializer *init) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct-initializer2 = initializer ("," initializer)*
|
||||||
|
static void struct_initializer2(Token **rest, Token *tok, Initializer *init) {
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for (Member *mem = init->ty->members; mem && !equal(tok, "}"); mem = mem->next) {
|
||||||
|
if (!first)
|
||||||
|
tok = skip(tok, ",");
|
||||||
|
first = false;
|
||||||
|
initializer2(&tok, tok, init->children[mem->idx]);
|
||||||
|
}
|
||||||
|
*rest = tok;
|
||||||
|
}
|
||||||
|
|
||||||
static void union_initializer(Token **rest, Token *tok, Initializer *init) {
|
static void union_initializer(Token **rest, Token *tok, Initializer *init) {
|
||||||
// Unlike structs, union initializers take only one initializer,
|
// Unlike structs, union initializers take only one initializer,
|
||||||
// and that initializes the first union member.
|
// and that initializes the first union member.
|
||||||
tok = skip(tok, "{");
|
if (equal(tok, "{")) {
|
||||||
initializer2(&tok, tok, init->children[0]);
|
initializer2(&tok, tok->next, init->children[0]);
|
||||||
*rest = skip(tok, "}");
|
*rest = skip(tok, "}");
|
||||||
|
} else {
|
||||||
|
initializer2(rest, tok, init->children[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializer = string-initializer | array-initializer
|
// initializer = string-initializer | array-initializer
|
||||||
|
@ -723,24 +754,30 @@ static void initializer2(Token **rest, Token *tok, Initializer *init) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init->ty->kind == TY_ARRAY) {
|
if (init->ty->kind == TY_ARRAY) {
|
||||||
array_initializer(rest, tok, init);
|
if (equal(tok, "{"))
|
||||||
|
array_initializer1(rest, tok, init);
|
||||||
|
else
|
||||||
|
array_initializer2(rest, tok, init);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init->ty->kind == TY_STRUCT) {
|
if (init->ty->kind == TY_STRUCT) {
|
||||||
|
if (equal(tok, "{")) {
|
||||||
|
struct_initializer1(rest, tok, init);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// A struct can be initialized with another struct. E.g.
|
// A struct can be initialized with another struct. E.g.
|
||||||
// `struct T x = y;` where y is a variable of type `struct T`.
|
// `struct T x = y;` where y is a variable of type `struct T`.
|
||||||
// Handle that case first.
|
// Handle that case first.
|
||||||
if (!equal(tok, "{")) {
|
|
||||||
Node *expr = assign(rest, tok);
|
Node *expr = assign(rest, tok);
|
||||||
add_type(expr);
|
add_type(expr);
|
||||||
if (expr->ty->kind == TY_STRUCT) {
|
if (expr->ty->kind == TY_STRUCT) {
|
||||||
init->expr = expr;
|
init->expr = expr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct_initializer(rest, tok, init);
|
struct_initializer2(rest, tok, init);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ long g6 = 6;
|
||||||
int g9[3] = {0, 1, 2};
|
int g9[3] = {0, 1, 2};
|
||||||
struct {char a; int b;} g11[2] = {{1, 2}, {3, 4}};
|
struct {char a; int b;} g11[2] = {{1, 2}, {3, 4}};
|
||||||
struct {int a[2];} g12[2] = {{{1, 2}}};
|
struct {int a[2];} g12[2] = {{{1, 2}}};
|
||||||
union { int a; char b[8]; } g13[2] = {{0x01020304}, {0x05060708}};
|
union { int a; char b[8]; } g13[2] = {0x01020304, 0x05060708};
|
||||||
char g17[] = "foobar";
|
char g17[] = "foobar";
|
||||||
char g18[10] = "foobar";
|
char g18[10] = "foobar";
|
||||||
char g19[3] = "foobar";
|
char g19[3] = "foobar";
|
||||||
|
@ -23,6 +23,9 @@ int *g28 = &g11[1].a;
|
||||||
long g29 = (long)(long)g26;
|
long g29 = (long)(long)g26;
|
||||||
struct { struct { int a[3]; } a; } g30 = {{{1,2,3}}};
|
struct { struct { int a[3]; } a; } g30 = {{{1,2,3}}};
|
||||||
int *g31=g30.a.a;
|
int *g31=g30.a.a;
|
||||||
|
struct {int a[2];} g40[2] = {{1, 2}, 3, 4};
|
||||||
|
struct {int a[2];} g41[2] = {1, 2, 3, 4};
|
||||||
|
char g43[][4] = {'f', 'o', 'o', 0, 'b', 'a', 'r', 0};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ASSERT(1, ({ int x[3]={1,2,3}; x[0]; }));
|
ASSERT(1, ({ int x[3]={1,2,3}; x[0]; }));
|
||||||
|
@ -136,6 +139,25 @@ int main() {
|
||||||
ASSERT(2, g31[1]);
|
ASSERT(2, g31[1]);
|
||||||
ASSERT(3, g31[2]);
|
ASSERT(3, g31[2]);
|
||||||
|
|
||||||
|
ASSERT(1, g40[0].a[0]);
|
||||||
|
ASSERT(2, g40[0].a[1]);
|
||||||
|
ASSERT(3, g40[1].a[0]);
|
||||||
|
ASSERT(4, g40[1].a[1]);
|
||||||
|
|
||||||
|
ASSERT(1, g41[0].a[0]);
|
||||||
|
ASSERT(2, g41[0].a[1]);
|
||||||
|
ASSERT(3, g41[1].a[0]);
|
||||||
|
ASSERT(4, g41[1].a[1]);
|
||||||
|
|
||||||
|
ASSERT(0, ({ int x[2][3]={0,1,2,3,4,5}; x[0][0]; }));
|
||||||
|
ASSERT(3, ({ int x[2][3]={0,1,2,3,4,5}; x[1][0]; }));
|
||||||
|
|
||||||
|
ASSERT(0, ({ struct {int a; int b;} x[2]={0,1,2,3}; x[0].a; }));
|
||||||
|
ASSERT(2, ({ struct {int a; int b;} x[2]={0,1,2,3}; x[1].a; }));
|
||||||
|
|
||||||
|
ASSERT(0, strcmp(g43[0], "foo"));
|
||||||
|
ASSERT(0, strcmp(g43[1], "bar"));
|
||||||
|
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue