diff options
author | 2007-07-09 23:13:06 +0100 | |
---|---|---|
committer | 2007-07-10 08:37:20 -0700 | |
commit | 449a5e3b13e1ba529c63dc80615e79d2dafe539b (patch) | |
tree | 366d676a54e3234fe4b3a8da3ec0950feace3c39 /evaluate.c | |
parent | make size_t better approximate the reality (diff) | |
download | sparse-449a5e3b13e1ba529c63dc80615e79d2dafe539b.tar.gz sparse-449a5e3b13e1ba529c63dc80615e79d2dafe539b.tar.bz2 sparse-449a5e3b13e1ba529c63dc80615e79d2dafe539b.zip |
fix handling of address_space in casts and assignments
Turn FORCE_MOD into storage class specifier (that's how it's
actually used and that makes for much simpler logics).
Introduce explicit EXPR_FORCE_CAST for forced casts; handle it
properly.
Kill the idiocy in get_as() (we end up picking the oddest things
for address space - e.g. if we have int __attribute__((address_space(1))) *p,
we'll get warnings about removal of address space when we do things like
(unsigned short)*p. Fixed. BTW, that had caught a bunch of very odd
bogosities in the kernel and eliminated several false positives in there.
As the result, get_as() is gone now and evaluate_cast() got simpler.
Kill the similar idiocy in handling pointer assignments; while we are at it,
fix the qualifiers check for assignments to/from void * (you can't assign
const int * to void * - qualifiers on the left side should be no less than
on the right one; for normal codepath we get that checked, but the special
case of void * skips these checks).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'evaluate.c')
-rw-r--r-- | evaluate.c | 91 |
1 files changed, 37 insertions, 54 deletions
@@ -1276,6 +1276,22 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t bad_null(*rp); goto Cast; } + if (sclass & TYPE_PTR && t->ctype.as == s->ctype.as) { + /* we should be more lazy here */ + int mod1 = t->ctype.modifiers; + int mod2 = s->ctype.modifiers; + s = get_base_type(s); + t = get_base_type(t); + + /* + * assignments to/from void * are OK, provided that + * we do not remove qualifiers from pointed to [C] + * or mix address spaces [sparse]. + */ + if (!(mod2 & ~mod1 & (MOD_VOLATILE | MOD_CONST))) + if (s == &void_ctype || t == &void_ctype) + goto Cast; + } } /* It's OK if the target is more volatile or const than the source */ @@ -1283,22 +1299,6 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t if (!typediff) return 1; - /* Pointer destination? */ - if (tclass & TYPE_PTR) { - int source_as; - int target_as; - - /* "void *" matches anything as long as the address space is OK */ - target_as = t->ctype.as | target->ctype.as; - source_as = s->ctype.as | source->ctype.as; - if (source_as == target_as && (s->type == SYM_PTR || s->type == SYM_ARRAY)) { - s = get_base_type(s); - t = get_base_type(t); - if (s == &void_ctype || t == &void_ctype) - goto Cast; - } - } - warning(expr->pos, "incorrect type in %s (%s)", where, typediff); info(expr->pos, " expected %s", show_typename(target)); info(expr->pos, " got %s", show_typename(source)); @@ -1330,6 +1330,7 @@ static void mark_assigned(struct expression *expr) mark_assigned(expr->right); return; case EXPR_CAST: + case EXPR_FORCE_CAST: mark_assigned(expr->cast_expression); return; case EXPR_SLICE: @@ -2496,46 +2497,13 @@ static void evaluate_initializer(struct symbol *ctype, struct expression **ep) expression_error(*ep, "invalid initializer"); } -static int get_as(struct symbol *sym) -{ - int as; - unsigned long mod; - - if (!sym) - return 0; - as = sym->ctype.as; - mod = sym->ctype.modifiers; - if (sym->type == SYM_NODE) { - sym = sym->ctype.base_type; - as |= sym->ctype.as; - mod |= sym->ctype.modifiers; - } - - /* - * At least for now, allow casting to a "unsigned long". - * That's how we do things like pointer arithmetic and - * store pointers to registers. - */ - if (sym == &ulong_ctype) - return -1; - - if (sym && sym->type == SYM_PTR) { - sym = get_base_type(sym); - as |= sym->ctype.as; - mod |= sym->ctype.modifiers; - } - if (mod & MOD_FORCE) - return -1; - return as; -} - static struct symbol *evaluate_cast(struct expression *expr) { struct expression *target = expr->cast_expression; struct symbol *ctype; struct symbol *t1, *t2; int class1, class2; - int as1, as2; + int as1 = 0, as2 = 0; if (!target) return NULL; @@ -2596,6 +2564,9 @@ static struct symbol *evaluate_cast(struct expression *expr) if (class1 & TYPE_COMPOUND) warning(expr->pos, "cast to non-scalar"); + if (class1 == TYPE_PTR) + get_base_type(t1); + t2 = target->ctype; if (!t2) { expression_error(expr, "cast from unknown type"); @@ -2606,19 +2577,30 @@ static struct symbol *evaluate_cast(struct expression *expr) if (class2 & TYPE_COMPOUND) warning(expr->pos, "cast from non-scalar"); + if (expr->type == EXPR_FORCE_CAST) + goto out; + /* allowed cast unfouls */ if (class2 & TYPE_FOULED) t2 = t2->ctype.base_type; - if (!(ctype->ctype.modifiers & MOD_FORCE) && t1 != t2) { + if (t1 != t2) { if (class1 & TYPE_RESTRICT) warning(expr->pos, "cast to restricted type"); if (class2 & TYPE_RESTRICT) warning(expr->pos, "cast from restricted type"); } - as1 = get_as(ctype); - as2 = get_as(target->ctype); + if (t1 == &ulong_ctype) + as1 = -1; + else if (class1 == TYPE_PTR) + as1 = t1->ctype.as; + + if (t2 == &ulong_ctype) + as2 = -1; + else if (class2 == TYPE_PTR) + as2 = t2->ctype.as; + if (!as1 && as2 > 0) warning(expr->pos, "cast removes address space of expression"); if (as1 > 0 && as2 > 0 && as1 != as2) @@ -2628,7 +2610,7 @@ static struct symbol *evaluate_cast(struct expression *expr) warning(expr->pos, "cast adds address space to expression (<asn:%d>)", as1); - if (!(ctype->ctype.modifiers & MOD_PTRINHERIT) && class1 == TYPE_PTR && + if (!(t1->ctype.modifiers & MOD_PTRINHERIT) && class1 == TYPE_PTR && !as1 && (target->flags & Int_const_expr)) { if (t1->ctype.base_type == &void_ctype) { if (is_zero_constant(target)) { @@ -2860,6 +2842,7 @@ struct symbol *evaluate_expression(struct expression *expr) return NULL; return evaluate_postop(expr); case EXPR_CAST: + case EXPR_FORCE_CAST: case EXPR_IMPLIED_CAST: return evaluate_cast(expr); case EXPR_SIZEOF: |