[GNU] Support array range designator

This commit is contained in:
Rui Ueyama 2020-09-20 15:39:38 +09:00
parent d90c73b605
commit 3d5550e29a
2 changed files with 34 additions and 11 deletions

42
parse.c
View File

@ -975,13 +975,22 @@ static void string_initializer(Token **rest, Token *tok, Initializer *init) {
// struct { int a, b, c; } x = { .c=5 };
//
// The above initializer sets x.c to 5.
static int array_designator(Token **rest, Token *tok, Type *ty) {
Token *start = tok;
int i = const_expr(&tok, tok->next);
if (i >= ty->array_len)
error_tok(start, "array designator index exceeds array bounds");
static void array_designator(Token **rest, Token *tok, Type *ty, int *begin, int *end) {
*begin = const_expr(&tok, tok->next);
if (*begin >= ty->array_len)
error_tok(tok, "array designator index exceeds array bounds");
if (equal(tok, "...")) {
*end = const_expr(&tok, tok->next);
if (*end >= ty->array_len)
error_tok(tok, "array designator index exceeds array bounds");
if (*end < *begin)
error_tok(tok, "array designator range [%d, %d] is empty", *begin, *end);
} else {
*end = *begin;
}
*rest = skip(tok, "]");
return i;
}
// struct-designator = "." ident
@ -1016,9 +1025,14 @@ static void designation(Token **rest, Token *tok, Initializer *init) {
if (equal(tok, "[")) {
if (init->ty->kind != TY_ARRAY)
error_tok(tok, "array index in non-array initializer");
int i = array_designator(&tok, tok, init->ty);
designation(&tok, tok, init->children[i]);
array_initializer2(rest, tok, init, i + 1);
int begin, end;
array_designator(&tok, tok, init->ty, &begin, &end);
Token *tok2;
for (int i = begin; i <= end; i++)
designation(&tok2, tok, init->children[i]);
array_initializer2(rest, tok2, init, begin + 1);
return;
}
@ -1097,8 +1111,14 @@ static void array_initializer1(Token **rest, Token *tok, Initializer *init) {
first = false;
if (equal(tok, "[")) {
i = array_designator(&tok, tok, init->ty);
designation(&tok, tok, init->children[i]);
int begin, end;
array_designator(&tok, tok, init->ty, &begin, &end);
Token *tok2;
for (int j = begin; j <= end; j++)
designation(&tok2, tok, init->children[j]);
tok = tok2;
i = end;
continue;
}

View File

@ -259,6 +259,9 @@ int main() {
ASSERT(4, ({ struct { struct { int a; struct { int b; }; }; int c; } x={1,2,3,.b=4,5}; x.b; }));
ASSERT(5, ({ struct { struct { int a; struct { int b; }; }; int c; } x={1,2,3,.b=4,5}; x.c; }));
ASSERT(16, ({ char x[]={[2 ... 10]='a', [7]='b', [15 ... 15]='c', [3 ... 5]='d'}; sizeof(x); }));
ASSERT(0, ({ char x[]={[2 ... 10]='a', [7]='b', [15 ... 15]='c', [3 ... 5]='d'}; memcmp(x, "\0\0adddabaaa\0\0\0\0c", 16); }));
printf("OK\n");
return 0;
}