aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@ZenIV.linux.org.uk>2009-02-02 07:31:51 +0000
committerChristopher Li <sparse@chrisli.org>2009-07-17 23:06:22 +0000
commitf7d10fe6c183448a48e2c4dc8d805c3524ccab45 (patch)
tree1226f0881cf275a95783d942a356b03be0319421
parentfun with declarations and definitions (diff)
downloadsparse-f7d10fe6c183448a48e2c4dc8d805c3524ccab45.tar.gz
sparse-f7d10fe6c183448a48e2c4dc8d805c3524ccab45.tar.bz2
sparse-f7d10fe6c183448a48e2c4dc8d805c3524ccab45.zip
Fix type_info_expression()
sizeof (typename){initializers}.foo is nice and valid C99 - it's parsed as sizeof primary.foo <- sizeof postfix.foo <- sizeof postfix <- sizeof unary <- unary. Current type_info_expression() stops too early. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Christopher Li <sparse@chrisli.org>
-rw-r--r--expression.c12
-rw-r--r--validation/sizeof-compound-postfix.c8
2 files changed, 18 insertions, 2 deletions
diff --git a/expression.c b/expression.c
index f634b07..124a8ec 100644
--- a/expression.c
+++ b/expression.c
@@ -594,12 +594,14 @@ static struct token *type_info_expression(struct token *token,
struct expression **tree, int type)
{
struct expression *expr = alloc_expression(token->pos, type);
+ struct token *p;
*tree = expr;
expr->flags = Int_const_expr; /* XXX: VLA support will need that changed */
token = token->next;
if (!match_op(token, '(') || !lookup_type(token->next))
return unary_expression(token, &expr->cast_expression);
+ p = token;
token = typename(token->next, &expr->cast_type, 0);
if (!match_op(token, ')')) {
@@ -616,8 +618,14 @@ static struct token *type_info_expression(struct token *token,
* C99 ambiguity: the typename might have been the beginning
* of a typed initializer expression..
*/
- if (match_op(token, '{'))
- token = initializer(&expr->cast_expression, token);
+ if (match_op(token, '{')) {
+ struct expression *cast = alloc_expression(p->pos, EXPR_CAST);
+ cast->cast_type = expr->cast_type;
+ expr->cast_type = NULL;
+ expr->cast_expression = cast;
+ token = initializer(&cast->cast_expression, token);
+ token = postfix_expression(token, &expr->cast_expression, cast);
+ }
return token;
}
diff --git a/validation/sizeof-compound-postfix.c b/validation/sizeof-compound-postfix.c
new file mode 100644
index 0000000..3b716fe
--- /dev/null
+++ b/validation/sizeof-compound-postfix.c
@@ -0,0 +1,8 @@
+struct foo {int x, y;};
+static int a(void)
+{
+ return sizeof (struct foo){0,1}.y;
+}
+/*
+ * check-name: Handling of sizeof compound-literal . member
+ */