aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@home.transmeta.com>2003-03-28 21:34:34 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 20:59:53 -0700
commit2ca23c6cb2f8cb7625e33702593c62fb91524797 (patch)
tree2dacc20ed1da18b1b9035fa4bb358cd704437d50
parent883e0c2829dce58799e29a1ff9a80a983ca61bcc (diff)
downloadsparse-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.c11
-rw-r--r--expression.h2
2 files changed, 9 insertions, 4 deletions
diff --git a/evaluate.c b/evaluate.c
index 910f48b8..48c7b76a 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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;