|
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