aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-27 14:42:31 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-09-01 08:43:40 +0200
commita5a8f8b9a1febfbae59751d1ce25a86ada8818ae (patch)
tree76ba1e448a2858fc8939e3b9400ecc5497812185
parent86556e1537cb094ddd33e30d1ee451d8930246c6 (diff)
downloadsparse-dev-a5a8f8b9a1febfbae59751d1ce25a86ada8818ae.tar.gz
fix linearization of unreachable switch (with reachable label).
An unreachable/inactive switch statement is currently not linearized. That's nice because it avoids to create useless instructions. However, the body of the statement can contain a label which can be reachable. If so, the resulting IR will contain a branch to an unexisting BB. Bad. For example, code like: int foo(int a) { goto label; switch(a) { default: label: break; } return 0; } (which is just a complicated way to write: int foo(int a) { return 0; }) is linearized as: foo: br .L1 Fix this by linearizing the statement even if not active. Note: it seems that none of the other statements are discarded if inactive. Good. OTOH, statement expressions can also contains (reachable) labels and thus would need the same fix (which will need much more work). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--linearize.c11
-rw-r--r--validation/linear/unreachable-label0.c1
2 files changed, 6 insertions, 6 deletions
diff --git a/linearize.c b/linearize.c
index a56c272f..3e7d4d9e 100644
--- a/linearize.c
+++ b/linearize.c
@@ -2177,13 +2177,14 @@ static pseudo_t linearize_switch(struct entrypoint *ep, struct statement *stmt)
struct multijmp *jmp;
pseudo_t pseudo;
+ if (!expr || !expr->ctype)
+ return VOID;
pseudo = linearize_expression(ep, expr);
- if (pseudo == VOID)
- return pseudo;
-
active = ep->active;
- if (!bb_reachable(active))
- return VOID;
+ if (!active) {
+ active = alloc_basic_block(ep, stmt->pos);
+ set_activeblock(ep, active);
+ }
switch_ins = alloc_typed_instruction(OP_SWITCH, expr->ctype);
use_pseudo(switch_ins, pseudo, &switch_ins->cond);
diff --git a/validation/linear/unreachable-label0.c b/validation/linear/unreachable-label0.c
index 568ae588..695e5cb0 100644
--- a/validation/linear/unreachable-label0.c
+++ b/validation/linear/unreachable-label0.c
@@ -12,7 +12,6 @@ label:
/*
* check-name: unreachable-label0
* check-command: test-linearize $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-contains: ret\\.