diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-03-28 21:34:34 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 20:59:53 -0700 |
| commit | 2ca23c6cb2f8cb7625e33702593c62fb91524797 (patch) | |
| tree | 2dacc20ed1da18b1b9035fa4bb358cd704437d50 | |
| parent | 883e0c2829dce58799e29a1ff9a80a983ca61bcc (diff) | |
| download | sparse-dev-2ca23c6cb2f8cb7625e33702593c62fb91524797.tar.gz | |
Zero out the high bits when casting constants to a smaller type,
so that a EXPR_VALUE expression never contains extra bits that
won't be used. It's just less confusing that way (but realize that
we always keep the value unsigned, even if the _type_ is signed).
| -rw-r--r-- | evaluate.c | 11 | ||||
| -rw-r--r-- | expression.h | 2 |
2 files changed, 9 insertions, 4 deletions
@@ -186,13 +186,13 @@ static int cast_value(struct expression *expr, struct symbol *newtype, // For pointers and integers, we can just move the value around expr->type = EXPR_VALUE; - if (old_size >= new_size) { + if (old_size == new_size) { expr->value = old->value; return 1; } + // expand it to the full "long long" value is_signed = !(oldtype->ctype.modifiers & MOD_UNSIGNED); - mask = 1ULL << (old_size-1); value = old->value; if (!(value & mask)) @@ -201,7 +201,12 @@ static int cast_value(struct expression *expr, struct symbol *newtype, ormask = ~andmask; if (!is_signed) ormask = 0; - expr->value = (value & andmask) | ormask; + value = (value & andmask) | ormask; + + // Truncate it to the new size + mask = 1ULL << (new_size-1); + mask = mask | (mask-1); + expr->value = value & mask; return 1; } diff --git a/expression.h b/expression.h index ddc1af42..bf201baf 100644 --- a/expression.h +++ b/expression.h @@ -36,7 +36,7 @@ struct expression { struct symbol *ctype; union { // EXPR_VALUE - long long value; + unsigned long long value; // EXPR_UNOP, EXPR_PREOP and EXPR_POSTOP struct expression *unop; |
