aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/expression.c
diff options
authorDave Olien <dmo@osdl.org>2003-09-01 18:59:42 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:01:03 -0700
commit4622a094643f24e6723ffe82c58469f65363f042 (patch)
treefdd1ddf88fcc9d5c36e9a6ffcfe523c75c38e27e /expression.c
parent33145bbb99c171f5f118cd2d4a067048c74f2895 (diff)
downloadsparse-dev-4622a094643f24e6723ffe82c58469f65363f042.tar.gz
[PATCH] Make sparse understand complex initializers inside expressions
This patch makes a cast expression followed by an initializer list into a postfix expression that can be dereferenced as a structure or an array. There are approximately 7 instances of these expressions in the Linux kernel, that give warnings about "expected lvalue for member dereference". The approach involved introducing a new "stack-based temporary" symbol of the same type as the cast expression, and using this as the target of the initialization expression. The subsequent array or structure member dereferences are made to that temporary symbol. show-parse.c need modification to display a symbol expression with an initializer list that is NOT in a symbol declaration list. An example of this form with structure member dereference is: typedef struct { long t1; long t2; long t3; } longstruct_t; long test; int main(void) { int a, b, c; test = (longstruct_t){a, b, c}.t3; return 0; } An example of this form with array member dereference is: typedef int iarray[2]; int pgp; main(void) { int index; int a, b; pgp = (iarray){a,b}[index]; }
Diffstat (limited to 'expression.c')
-rw-r--r--expression.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/expression.c b/expression.c
index 90a006af..48414c3e 100644
--- a/expression.c
+++ b/expression.c
@@ -241,11 +241,17 @@ static struct token *expression_list(struct token *token, struct expression_list
return token;
}
-static struct token *postfix_expression(struct token *token, struct expression **tree)
+/*
+ * extend to deal with the ambiguous C grammar for parsing
+ * a cast expressions followed by an initializer.
+ */
+static struct token *postfix_expression(struct token *token, struct expression **tree, struct expression *cast_init_expr)
{
- struct expression *expr = NULL;
+ struct expression *expr = cast_init_expr;
+
+ if (!expr)
+ token = primary_expression(token, &expr);
- token = primary_expression(token, &expr);
while (expr && token_type(token) == TOKEN_SPECIAL) {
switch (token->special) {
case '[': { /* Array dereference */
@@ -343,13 +349,16 @@ static struct token *unary_expression(struct token *token, struct expression **t
}
- return postfix_expression(token, tree);
+ return postfix_expression(token, tree, NULL);
}
/*
* Ambiguity: a '(' can be either a cast-expression or
* a primary-expression depending on whether it is followed
* by a type or not.
+ *
+ * additional ambiguity: a "cast expression" followed by
+ * an initializer is really a postfix-expression.
*/
static struct token *cast_expression(struct token *token, struct expression **tree)
{
@@ -362,9 +371,11 @@ static struct token *cast_expression(struct token *token, struct expression **tr
token = typename(next, &sym);
cast->cast_type = sym->ctype.base_type;
token = expect(token, ')', "at end of cast operator");
+ if (match_op(token, '{')) {
+ token = initializer(&cast->cast_expression, token);
+ return postfix_expression(token, tree, cast);
+ }
*tree = cast;
- if (match_op(token, '{'))
- return initializer(&cast->cast_expression, token);
token = cast_expression(token, &cast->cast_expression);
return token;
}