aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--evaluate.c19
-rw-r--r--expression.c23
-rw-r--r--show-parse.c11
3 files changed, 45 insertions, 8 deletions
diff --git a/evaluate.c b/evaluate.c
index d887ab6..ad8f15f 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1225,9 +1225,26 @@ static struct symbol *evaluate_cast(struct expression *expr)
* initializer, in which case we need to pass
* the type value down to that initializer rather
* than trying to evaluate it as an expression
+ *
+ * A more complex case is when the initializer is
+ * dereferenced as part of a post-fix expression.
+ * We need to produce an expression that can be dereferenced.
*/
if (target->type == EXPR_INITIALIZER) {
- evaluate_initializer(ctype, &expr->cast_expression, 0);
+ struct symbol *sym = alloc_symbol(expr->pos, SYM_NODE);
+ struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL);
+
+ sym->ctype.base_type = ctype;
+ sym->initializer = expr->cast_expression;
+ evaluate_symbol(sym);
+
+ addr->ctype = &ptr_ctype;
+ addr->symbol = sym;
+
+ expr->type = EXPR_PREOP;
+ expr->op = '*';
+ expr->unop = addr;
+ expr->ctype = ctype;
return ctype;
}
diff --git a/expression.c b/expression.c
index 90a006a..48414c3 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;
}
diff --git a/show-parse.c b/show-parse.c
index 0d7084b..14b06bb 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -913,6 +913,15 @@ static int show_initializer_expr(struct expression *expr, struct symbol *ctype)
return 0;
}
+int show_symbol_expr_init(struct symbol *sym)
+{
+ struct expression *expr = sym->initializer;
+
+ if (expr)
+ show_initializer_expr(expr, expr->ctype);
+ return show_symbol_expr(sym);
+}
+
/*
* Print out an expression. Return the pseudo that contains the
* variable.
@@ -947,7 +956,7 @@ int show_expression(struct expression *expr)
case EXPR_POSTOP:
return show_postop(expr);
case EXPR_SYMBOL:
- return show_symbol_expr(expr->symbol);
+ return show_symbol_expr_init(expr->symbol);
case EXPR_DEREF:
case EXPR_SIZEOF:
warn(expr->pos, "invalid expression after evaluation");