aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@penguin.transmeta.com>2003-04-14 15:47:21 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:31 -0700
commitcc46ef1b775fec69be90f891463617f4187a9146 (patch)
tree079f25765e923b5ee6d02575eda0ea7ff63e104e
parent89afb737679fa312e01005555ebde306759eba68 (diff)
downloadsparse-dev-cc46ef1b775fec69be90f891463617f4187a9146.tar.gz
Evaluate array initializers (type fixing and array index
calculations).
-rw-r--r--evaluate.c44
-rw-r--r--parse.c3
2 files changed, 28 insertions, 19 deletions
diff --git a/evaluate.c b/evaluate.c
index 5a60fee7..06c2defc 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -881,11 +881,11 @@ static struct symbol *evaluate_dereference(struct expression *expr)
struct symbol *ctype = op->ctype, *sym;
sym = alloc_symbol(expr->pos, SYM_NODE);
- sym->ctype = ctype->ctype;
if (ctype->type == SYM_NODE) {
ctype = ctype->ctype.base_type;
merge_type(sym, ctype);
}
+ sym->ctype = ctype->ctype;
if (ctype->type != SYM_PTR && ctype->type != SYM_ARRAY) {
warn(expr->pos, "cannot derefence this type");
return 0;
@@ -1177,24 +1177,29 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head)
return 1;
}
-/*
- * FIXME! This is bogus: we need to take array index
- * entries into account when calculating the size of
- * the array.
- */
-static int count_array_initializer(struct expression *expr)
+static int evaluate_array_initializer(struct symbol *ctype, struct expression *expr)
{
- struct expression_list *list;
+ struct expression *entry;
+ int current = 0;
+ int max = 0;
- if (expr->type != EXPR_INITIALIZER)
- return 1;
- list = expr->expr_list;
- return expression_list_size(list);
-}
+ FOR_EACH_PTR(expr->expr_list, entry) {
+ struct expression **p = THIS_ADDRESS(entry);
+ struct symbol *rtype;
-static int evaluate_array_initializer(struct symbol *ctype, struct expression *expr)
-{
- return count_array_initializer(expr);
+ if (entry->type == EXPR_INDEX) {
+ current = entry->idx_to;
+ continue;
+ }
+ rtype = evaluate_expression(entry);
+ if (!rtype)
+ continue;
+ compatible_assignment_types(entry, ctype, p, rtype, "array initializer");
+ current++;
+ if (current > max)
+ max = current;
+ } END_FOR_EACH_PTR;
+ return max;
}
static int evaluate_struct_or_union_initializer(struct symbol *ctype, struct expression *expr, int multiple)
@@ -1228,10 +1233,13 @@ static int evaluate_initializer(struct symbol *ctype, struct expression **ep)
}
expr->ctype = ctype;
+ if (ctype->type = SYM_NODE)
+ ctype = ctype->ctype.base_type;
+
switch (ctype->type) {
case SYM_ARRAY:
case SYM_PTR:
- return evaluate_array_initializer(ctype, expr);
+ return evaluate_array_initializer(ctype->ctype.base_type, expr);
case SYM_UNION:
return evaluate_struct_or_union_initializer(ctype, expr, 0);
case SYM_STRUCT:
@@ -1434,7 +1442,7 @@ struct symbol *evaluate_symbol(struct symbol *sym)
/* Evaluate the initializers */
if (sym->initializer) {
- int count = evaluate_initializer(base_type, &sym->initializer);
+ int count = evaluate_initializer(sym, &sym->initializer);
if (base_type->type == SYM_ARRAY && base_type->array_size < 0) {
int bit_size = count * base_type->ctype.base_type->bit_size;
base_type->array_size = count;
diff --git a/parse.c b/parse.c
index 245d92f2..a02aaddd 100644
--- a/parse.c
+++ b/parse.c
@@ -850,7 +850,7 @@ static struct expression *index_expression(struct expression *from, struct expre
idx_to = idx_from;
if (to) {
idx_to = get_expression_value(to);
- if (idx_to < idx_from)
+ if (idx_to < idx_from || idx_from < 0)
warn(from->pos, "nonsense array initializer index range");
}
expr->idx_from = idx_from;
@@ -877,6 +877,7 @@ static struct token *initializer_list(struct expression_list **list, struct toke
token = constant_expression(token->next, &to);
add_expression(list, index_expression(from, to));
token = expect(token, ']', "at end of initializer index");
+ token = expect(token, '=', "at end of initializer index");
}
expr = NULL;