aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-08-05 23:11:33 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-08-06 18:30:44 +0200
commitf01f79df0512ef16dc1ae681edf75e6924a8cf2e (patch)
tree8c72dd203e9ff624eeb2b9a69f7ac31676563b79
parenta9e0d28f76699e6fc2c1795801cad75ece790841 (diff)
downloadsparse-f01f79df0512ef16dc1ae681edf75e6924a8cf2e.tar.gz
shift-assign: fix linearization of shift-assign
The result of a shift-assigns has the same type as the left operand but the shift itself must be done on the promoted type. The usual conversions are not done for shifts. The problem is that this promoted type is not stored explicitly in the data structure. This is specific to shift-assigns because for other operations, for example add-assign, the usual conversions must be done and the resulting type can be found on the RHS. Since at linearization, the LHS and the RHS must have the same type, the solution is to cast the RHS to LHS's promoted type during evaluation. This solve a bunch of problems with shift-assigns, like doing logical shift when an arithmetic shift was needed. Fixes: efdefb100d086aaabf20d475c3d1a65cbceeb534 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--evaluate.c6
-rw-r--r--validation/linear/bug-assign-op0.c1
-rw-r--r--validation/linear/shift-assign1.c1
-rw-r--r--validation/shift-undef.c16
4 files changed, 13 insertions, 11 deletions
diff --git a/evaluate.c b/evaluate.c
index dddea761..6d8ecd7f 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1342,8 +1342,12 @@ static int evaluate_assign_op(struct expression *expr)
return 1;
} else if (op == SPECIAL_SHR_ASSIGN || op == SPECIAL_SHL_ASSIGN) {
// shifts do integer promotions, but that's it.
+ unrestrict(expr->left, tclass, &t);
+ target = integer_promotion(t);
+
unrestrict(expr->right, sclass, &s);
- target = integer_promotion(s);
+ source = integer_promotion(s);
+ expr->right = cast_to(expr->right, source);
goto Cast;
} else if (!(sclass & TYPE_RESTRICT))
goto usual;
diff --git a/validation/linear/bug-assign-op0.c b/validation/linear/bug-assign-op0.c
index 0cabc622..b351bb51 100644
--- a/validation/linear/bug-assign-op0.c
+++ b/validation/linear/bug-assign-op0.c
@@ -46,7 +46,6 @@ unsigned int sldivu(unsigned int u, long s)
/*
* check-name: bug-assign-op0
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-start
asr:
diff --git a/validation/linear/shift-assign1.c b/validation/linear/shift-assign1.c
index 9b3137bb..4c96fc28 100644
--- a/validation/linear/shift-assign1.c
+++ b/validation/linear/shift-assign1.c
@@ -45,7 +45,6 @@ u64 u64u64(u64 a, u64 b) { a >>= b; return a; }
/*
* check-name: shift-assign1
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-start
s16s16:
diff --git a/validation/shift-undef.c b/validation/shift-undef.c
index 4e94fa23..613c6b95 100644
--- a/validation/shift-undef.c
+++ b/validation/shift-undef.c
@@ -140,23 +140,23 @@ shift-undef.c:32:11: warning: shift too big (100) for type int
shift-undef.c:33:11: warning: shift too big (101) for type unsigned int
shift-undef.c:34:11: warning: shift too big (102) for type unsigned int
shift-undef.c:35:11: warning: shift count is negative (-1)
-shift-undef.c:36:11: warning: shift count is negative (-2)
-shift-undef.c:37:11: warning: shift count is negative (-3)
+shift-undef.c:36:11: warning: shift too big (4294967294) for type unsigned int
+shift-undef.c:37:11: warning: shift too big (4294967293) for type unsigned int
shift-undef.c:38:25: warning: shift too big (103) for type int
shift-undef.c:39:25: warning: shift too big (104) for type unsigned int
shift-undef.c:40:25: warning: shift too big (105) for type unsigned int
shift-undef.c:41:25: warning: shift count is negative (-4)
-shift-undef.c:42:25: warning: shift count is negative (-5)
-shift-undef.c:43:25: warning: shift count is negative (-6)
+shift-undef.c:42:25: warning: shift too big (4294967291) for type unsigned int
+shift-undef.c:43:25: warning: shift too big (4294967290) for type unsigned int
shift-undef.c:44:30: warning: shift too big (106) for type int
shift-undef.c:45:30: warning: shift too big (107) for type unsigned int
shift-undef.c:46:30: warning: shift too big (108) for type unsigned int
shift-undef.c:47:30: warning: shift count is negative (-7)
-shift-undef.c:48:30: warning: shift count is negative (-8)
-shift-undef.c:49:30: warning: shift count is negative (-9)
+shift-undef.c:48:30: warning: shift too big (4294967288) for type unsigned int
+shift-undef.c:49:30: warning: shift too big (4294967287) for type unsigned int
shift-undef.c:50:26: warning: shift too big (109) for type int
-shift-undef.c:51:26: warning: shift too big (110) for type int
-shift-undef.c:52:26: warning: shift too big (111) for type int
+shift-undef.c:51:26: warning: shift too big (110) for type unsigned int
+shift-undef.c:52:26: warning: shift too big (111) for type unsigned int
shift-undef.c:53:26: warning: shift count is negative (-10)
shift-undef.c:54:26: warning: shift count is negative (-11)
shift-undef.c:55:26: warning: shift count is negative (-12)