|
12 | 12 | #include "remove_skip.h"
|
13 | 13 | #include "goto_model.h"
|
14 | 14 |
|
15 |
| -bool is_skip(const goto_programt &body, goto_programt::const_targett it) |
| 15 | +/// Determine whether the instruction is semantically equivalent to a skip |
| 16 | +/// (no-op). This includes a skip, but also if(false) goto ..., goto next; |
| 17 | +/// next: ..., and (void)0. |
| 18 | +/// \param body goto program containing the instruction |
| 19 | +/// \param it instruction iterator that is tested for being a skip (or |
| 20 | +/// equivalent) |
| 21 | +/// \param ignore_labels If the caller takes care of moving labels, then even |
| 22 | +/// skip statements carrying labels can be treated as skips (even though they |
| 23 | +/// may carry key information such as error labels). |
| 24 | +/// \return True, iff it is equivalent to a skip. |
| 25 | +bool is_skip( |
| 26 | + const goto_programt &body, |
| 27 | + goto_programt::const_targett it, |
| 28 | + bool ignore_labels) |
16 | 29 | {
|
17 |
| - // we won't remove labelled statements |
18 |
| - // (think about error labels or the like) |
19 |
| - |
20 |
| - if(!it->labels.empty()) |
| 30 | + if(!ignore_labels && !it->labels.empty()) |
21 | 31 | return false;
|
22 | 32 |
|
23 | 33 | if(it->is_skip())
|
@@ -100,12 +110,17 @@ void remove_skip(
|
100 | 110 | // for collecting labels
|
101 | 111 | std::list<irep_idt> labels;
|
102 | 112 |
|
103 |
| - while(is_skip(goto_program, it)) |
| 113 | + while(is_skip(goto_program, it, true)) |
104 | 114 | {
|
105 | 115 | // don't remove the last skip statement,
|
106 | 116 | // it could be a target
|
107 |
| - if(it == std::prev(end)) |
| 117 | + if( |
| 118 | + it == std::prev(end) || |
| 119 | + (std::next(it)->is_end_function() && |
| 120 | + (!labels.empty() || !it->labels.empty()))) |
| 121 | + { |
108 | 122 | break;
|
| 123 | + } |
109 | 124 |
|
110 | 125 | // save labels
|
111 | 126 | labels.splice(labels.end(), it->labels);
|
|
0 commit comments