compile-i386.c | 10 ---------- evaluate.c | 30 +++++++++++++++++++++++++----- show-parse.c | 9 --------- symbol.h | 1 + 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/compile-i386.c b/compile-i386.c index b47095252053..31d3dbca1060 100644 --- a/compile-i386.c +++ b/compile-i386.c @@ -176,7 +176,6 @@ static const char *current_section; static void emit_comment(const char * fmt, ...) FORMAT_ATTR(1); static void emit_move(struct storage *src, struct storage *dest, struct symbol *ctype, const char *comment); -static int type_is_signed(struct symbol *sym); static struct storage *x86_address_gen(struct expression *expr); static struct storage *x86_symbol_expr(struct symbol *sym); static void x86_symbol(struct symbol *sym); @@ -2250,15 +2249,6 @@ static void x86_symbol_init(struct symbol *sym) priv->addr = new; } -static int type_is_signed(struct symbol *sym) -{ - if (sym->type == SYM_NODE) - sym = sym->ctype.base_type; - if (sym->type == SYM_PTR) - return 0; - return !(sym->ctype.modifiers & MOD_UNSIGNED); -} - static struct storage *x86_label_expr(struct expression *expr) { struct storage *new = stack_alloc(4); diff --git a/evaluate.c b/evaluate.c index 99dedb5c5bde..5c49c9c92a69 100644 --- a/evaluate.c +++ b/evaluate.c @@ -31,6 +31,15 @@ struct symbol *current_fn; static struct symbol *degenerate(struct expression *expr); static struct symbol *evaluate_symbol(struct symbol *sym); +int type_is_signed(struct symbol *sym) +{ + if (sym->type == SYM_NODE) + sym = sym->ctype.base_type; + if (sym->type == SYM_PTR) + return 0; + return !(sym->ctype.modifiers & MOD_UNSIGNED); +} + static struct symbol *evaluate_symbol_expression(struct expression *expr) { struct expression *addr; @@ -282,12 +291,18 @@ static struct expression * cast_to(struct expression *old, struct symbol *type) */ switch (old->type) { case EXPR_PREOP: - if (old->ctype->bit_size < type->bit_size) + if (old->op == '~' || old->op == '-') { + if (old->ctype->bit_size > type->bit_size) { + old->ctype = type; + old->unop = cast_to(old->unop, type); + return old; + } + if (old->ctype->bit_size == type->bit_size) + break; + if (type_is_signed(old->ctype)) + break; + warning(old->pos, "implicit unsigned widening cast of a '%c' expression", old->op); break; - if (old->op == '~') { - old->ctype = type; - old->unop = cast_to(old->unop, type); - return old; } break; @@ -310,6 +325,7 @@ static struct expression * cast_to(struct expression *old, struct symbol *type) /* nothing */; } + expr = alloc_expression(old->pos, EXPR_IMPLIED_CAST); expr->flags = old->flags; expr->ctype = type; @@ -1757,6 +1773,10 @@ Normal: } if (expr->op == '+') *expr = *expr->unop; + else if (expr->unop->type == EXPR_PREOP && expr->unop->op == expr->op) { + if (expr->unop->ctype == ctype) + *expr = *expr->unop->unop; + } expr->ctype = ctype; return ctype; Restr: diff --git a/show-parse.c b/show-parse.c index 1333e301c151..c8e864476fac 100644 --- a/show-parse.c +++ b/show-parse.c @@ -933,15 +933,6 @@ static int show_symbol_init(struct symbol *sym) return 0; } -static int type_is_signed(struct symbol *sym) -{ - if (sym->type == SYM_NODE) - sym = sym->ctype.base_type; - if (sym->type == SYM_PTR) - return 0; - return !(sym->ctype.modifiers & MOD_UNSIGNED); -} - static int show_cast_expr(struct expression *expr) { struct symbol *old_type, *new_type; diff --git a/symbol.h b/symbol.h index 1e745799a8d0..6928faf4fec6 100644 --- a/symbol.h +++ b/symbol.h @@ -389,5 +389,6 @@ extern int is_ptr_type(struct symbol *); void create_fouled(struct symbol *type); struct symbol *befoul(struct symbol *type); +int type_is_signed(struct symbol *sym); #endif /* SYMBOL_H */