@@ -74,40 +74,53 @@ bool remove_instanceoft::contains_instanceof(
74
74
return false ;
75
75
}
76
76
77
- // / Replaces an expression like e instanceof A with e.@class_identifier == "A"
78
- // / Or a big-or of similar expressions if we know of subtypes that also satisfy
77
+ // / Replaces an expression like e instanceof A with e.\ @class_identifier == "A"
78
+ // / or a big-or of similar expressions if we know of subtypes that also satisfy
79
79
// / the given test.
80
- // / \par parameters: Expression to lower `expr` and the `goto_program` and
81
- // / instruction `this_inst` it belongs to.
82
- // / \return Side-effect on `expr` replacing it with an explicit clsid test
80
+ // / \param expr: Expression to lower (the code or the guard of an instruction)
81
+ // / \param goto_program: program the expression belongs to
82
+ // / \param this_inst: instruction the expression is found at
83
+ // / \param inst_switch: set of instructions to switch around once we're done
83
84
void remove_instanceoft::lower_instanceof (
84
85
exprt &expr,
85
86
goto_programt &goto_program,
86
87
goto_programt::targett this_inst,
87
88
instanceof_instt &inst_switch)
88
89
{
89
- if (expr.id ()= =ID_java_instanceof)
90
+ if (expr.id ()! =ID_java_instanceof)
90
91
{
92
+ Forall_operands (it, expr)
93
+ lower_instanceof (*it, goto_program, this_inst, inst_switch);
94
+ return ;
95
+ }
96
+
91
97
const exprt &check_ptr=expr.op0 ();
92
- assert (check_ptr.type ().id ()==ID_pointer);
98
+ INVARIANT (
99
+ check_ptr.type ().id ()==ID_pointer,
100
+ " instanceof first operand should be a pointer" );
93
101
const exprt &target_arg=expr.op1 ();
94
- assert (target_arg.id ()==ID_type);
102
+ INVARIANT (
103
+ target_arg.id ()==ID_type,
104
+ " instanceof second operand should be a type" );
95
105
const typet &target_type=target_arg.type ();
96
106
97
107
// Find all types we know about that satisfy the given requirement:
98
- assert (target_type.id ()==ID_symbol);
108
+ INVARIANT (
109
+ target_type.id ()==ID_symbol,
110
+ " instanceof second operand should have a simple type" );
99
111
const irep_idt &target_name=
100
112
to_symbol_type (target_type).get_identifier ();
101
113
std::vector<irep_idt> children=
102
114
class_hierarchy.get_children_trans (target_name);
103
115
children.push_back (target_name);
104
116
105
- assert (!children.empty () && " Unable to execute instanceof" );
106
-
107
- // Insert an instruction before this one that assigns the clsid we're
108
- // checking against to a temporary, as GOTO program if-expressions should
117
+ // Insert an instruction before the new check that assigns the clsid we're
118
+ // checking for to a temporary, as GOTO program if-expressions should
109
119
// not contain derefs.
110
-
120
+ // We actually insert the assignment instruction after the existing one.
121
+ // This will briefly be ill-formed (use before def of instanceof_tmp) but the
122
+ // two will subsequently switch places. This makes sure that the inserted
123
+ // assignement doesn't end up before any labels pointing at this instruction.
111
124
symbol_typet jlo (" java::java.lang.Object" );
112
125
exprt object_clsid=get_class_identifier_field (check_ptr, jlo, ns);
113
126
@@ -126,10 +139,7 @@ void remove_instanceoft::lower_instanceof(
126
139
newinst->source_location =this_inst->source_location ;
127
140
newinst->function =this_inst->function ;
128
141
129
- // Insert the check instruction after the existing one.
130
- // This will briefly be ill-formed (use before def of
131
- // instanceof_tmp) but the two will subsequently switch
132
- // places in lower_instanceof(goto_programt &) below.
142
+ // Remember to switch the instructions
133
143
inst_switch.push_back (make_pair (this_inst, newinst));
134
144
// Replace the instanceof construct with a big-or.
135
145
exprt::operandst or_ops;
@@ -140,20 +150,14 @@ void remove_instanceoft::lower_instanceof(
140
150
or_ops.push_back (test);
141
151
}
142
152
expr=disjunction (or_ops);
143
- }
144
- else
145
- {
146
- Forall_operands (it, expr)
147
- lower_instanceof (*it, goto_program, this_inst, inst_switch);
148
- }
149
153
}
150
154
151
- // / See function above
152
- // / \par parameters: GOTO program instruction `target` whose instanceof
153
- // / expressions,
154
- // / if any, should be replaced with explicit tests, and the
155
- // / `goto_program` it is part of.
156
- // / \return Side-effect on `target` as above.
155
+ // / Replaces expressions like e instanceof A with e.\@class_identifier == "A"
156
+ // / or a big-or of similar expressions if we know of subtypes that also satisfy
157
+ // / the given test. Does this for the code or guard at a specific instruction.
158
+ // / \param goto_program: program to process
159
+ // / \param target: instruction to check for instanceof expressions
160
+ // / \param inst_switch: set of instructions to switch around once we're done
157
161
void remove_instanceoft::lower_instanceof (
158
162
goto_programt &goto_program,
159
163
goto_programt::targett target,
@@ -167,35 +171,39 @@ void remove_instanceoft::lower_instanceof(
167
171
// code (e.g. a guarded-goto), but this assertion checks that this
168
172
// assumption is correct and remains true on future evolution of the
169
173
// allowable goto instruction types.
170
- assert (!(code_iof && guard_iof));
174
+ INVARIANT (
175
+ !(code_iof && guard_iof), " instanceof code should not have a guard" );
171
176
if (code_iof)
172
177
lower_instanceof (target->code , goto_program, target, inst_switch);
173
178
if (guard_iof)
174
179
lower_instanceof (target->guard , goto_program, target, inst_switch);
175
180
}
176
181
177
- // / See function above
178
- // / \par parameters: `goto_program`, all of whose instanceof expressions will
179
- // / be replaced by explicit class-identifier tests.
180
- // / \return Side-effect on `goto_program` as above.
182
+ // / Replace every instanceof in the passed function body with an explicit
183
+ // / class-identifier test.
184
+ // / Extra auxiliary variables may be introduced into symbol_table.
185
+ // / \param goto_program: The function body to work on.
186
+ // / \return true if one or more instanceof expressions have been replaced
181
187
bool remove_instanceoft::lower_instanceof (goto_programt &goto_program)
182
188
{
183
189
instanceof_instt inst_switch;
184
- Forall_goto_program_instructions (target, goto_program)
185
- lower_instanceof (goto_program, target, inst_switch);
186
- if (!inst_switch.empty ())
190
+ for (goto_programt::instructionst::iterator target=
191
+ goto_program.instructions .begin ();
192
+ target!=goto_program.instructions .end ();
193
+ ++target)
187
194
{
188
- for (auto &p : inst_switch)
189
- {
190
- const goto_programt::targett &this_inst=p.first ;
191
- const goto_programt::targett &newinst=p.second ;
192
- this_inst->swap (*newinst);
193
- }
194
- goto_program.update ();
195
- return true ;
195
+ lower_instanceof (goto_program, target, inst_switch);
196
196
}
197
- else
197
+ if (inst_switch. empty ())
198
198
return false ;
199
+ for (auto &p : inst_switch)
200
+ {
201
+ const goto_programt::targett &this_inst=p.first ;
202
+ const goto_programt::targett &newinst=p.second ;
203
+ this_inst->swap (*newinst);
204
+ }
205
+ goto_program.update ();
206
+ return true ;
199
207
}
200
208
201
209
// / See function above
@@ -226,6 +234,5 @@ void remove_instanceof(
226
234
227
235
void remove_instanceof (goto_modelt &goto_model)
228
236
{
229
- remove_instanceof (
230
- goto_model.symbol_table , goto_model.goto_functions );
237
+ remove_instanceof (goto_model.symbol_table , goto_model.goto_functions );
231
238
}
0 commit comments