aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorAlexander Viro <viro@parcelfarce.linux.theplanet.co.uk>2004-10-05 08:50:05 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:03:28 -0700
commit12dc7e4bb89a432d397206b0cf547c351173b97f (patch)
treebc058d3573a4df3d5041608fccf63e26b7bda54f
parente95028ed6a5b8c9a35e5ce2af136c5781799308a (diff)
downloadsparse-dev-12dc7e4bb89a432d397206b0cf547c351173b97f.tar.gz
[PATCH] graceful handling of old-style array initializers
The current gcc initializer code is too permissive, AFAICS - [0][0] 1 will be rejected by gcc too, so we shouldn't consider it "broken gcc syntax". There was another bug in there - *ep = NULL; token = initializer(ep, token); if (!expr) break; add_expression(list, expr); would not catch the case when we have e.g. .foo = <bad expression> and we end up with list polluted by EXPR_IDENTIFIER with NULL ->ident_expression. Should be if (!*ep) instead. This also cleans it up by splitting the list handling case up from the loop, and making the single initializer parsing a function of its own.
-rw-r--r--parse.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/parse.c b/parse.c
index 96dfe54c..3beeb4b9 100644
--- a/parse.c
+++ b/parse.c
@@ -1403,26 +1403,30 @@ static struct expression *index_expression(struct expression *from, struct expre
return expr;
}
-static struct token *initializer_list(struct expression_list **list, struct token *token)
+static struct token *single_initializer(struct expression **ep, struct token *token)
{
- int expect_equal = 0, old_style = 0;
- struct expression *expr, **ep = &expr;
-
- for (;;) {
- struct token *next = token->next;
+ int expect_equal = 0;
+ struct token *next = token->next;
+ struct expression **tail = ep;
+ int nested;
+
+ *ep = NULL;
+
+ if ((token_type(token) == TOKEN_IDENT) && match_op(next, ':')) {
+ struct expression *expr = identifier_expression(token);
+ warning(token->pos, "obsolete struct initializer, use C99 syntax");
+ token = initializer(&expr->ident_expression, next->next);
+ if (expr->ident_expression)
+ *ep = expr;
+ return token;
+ }
+ for (tail = ep, nested = 0; ; nested++, next = token->next) {
if (match_op(token, '.') && (token_type(next) == TOKEN_IDENT)) {
struct expression *expr = identifier_expression(next);
- *ep = expr;
- ep = &expr->ident_expression;
- token = next->next;
+ *tail = expr;
+ tail = &expr->ident_expression;
expect_equal = 1;
- continue;
- } else if (!expect_equal && (token_type(token) == TOKEN_IDENT) && match_op(next, ':')) {
- struct expression *expr = identifier_expression(token);
- *ep = expr;
- ep = &expr->ident_expression;
- old_style = 1;
token = next->next;
} else if (match_op(token, '[')) {
struct expression *from = NULL, *to = NULL, *expr;
@@ -1430,32 +1434,42 @@ static struct token *initializer_list(struct expression_list **list, struct toke
if (match_op(token, SPECIAL_ELLIPSIS))
token = constant_expression(token->next, &to);
expr = index_expression(from, to);
- *ep = expr;
- ep = &expr->idx_expression;
+ *tail = expr;
+ tail = &expr->idx_expression;
token = expect(token, ']', "at end of initializer index");
- expect_equal = 1;
- continue;
- }
- if (expect_equal) {
- old_style = 1;
- if (match_op(token, '=')) {
- old_style = 0;
- token = token->next;
- }
+ if (nested)
+ expect_equal = 1;
+ } else {
+ break;
}
- if (old_style)
- warning(token->pos, "Old-style gcc initializer - please us C99 syntax");
+ }
+ if (nested && !expect_equal) {
+ if (!match_op(token, '='))
+ warning(token->pos, "obsolete array initializer, use C99 syntax");
+ else
+ expect_equal = 1;
+ }
+ if (expect_equal)
+ token = expect(token, '=', "at end of initializer index");
+ token = initializer(tail, token);
+ if (!*tail)
*ep = NULL;
- token = initializer(ep, token);
+ return token;
+}
+
+static struct token *initializer_list(struct expression_list **list, struct token *token)
+{
+ struct expression *expr;
+
+ for (;;) {
+ token = single_initializer(&expr, token);
if (!expr)
break;
add_expression(list, expr);
if (!match_op(token, ','))
break;
token = token->next;
- expect_equal = 0;
- ep = &expr;
}
return token;
}