@@ -110,70 +110,34 @@ bool remove_instanceoft::lower_instanceof(
110
110
return a.compare(b) < 0;
111
111
});
112
112
113
- // Make temporaries to store the class identifier (avoids repeated derefs) and
114
- // the instanceof result:
115
-
116
113
auto jlo = to_struct_tag_type(java_lang_object_type().subtype());
117
114
exprt object_clsid = get_class_identifier_field(check_ptr, jlo, ns);
118
115
119
- symbolt &clsid_tmp_sym = fresh_java_symbol(
120
- object_clsid.type(),
121
- "class_identifier_tmp",
122
- this_inst->source_location,
123
- function_identifier,
124
- symbol_table);
125
-
126
- symbolt &instanceof_result_sym = fresh_java_symbol(
127
- bool_typet(),
128
- "instanceof_result_tmp",
129
- this_inst->source_location,
130
- function_identifier,
131
- symbol_table);
132
-
133
- // Create
134
- // if(expr == null)
135
- // instanceof_result = false;
136
- // else
137
- // string clsid = expr->@class_identifier
138
- // instanceof_result = clsid == "A" || clsid == "B" || ...
139
-
140
- // According to the Java specification, null instanceof T is false for all
141
- // possible values of T.
142
- // (http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2)
143
-
144
- code_blockt else_block;
145
- else_block.add(code_declt(clsid_tmp_sym.symbol_expr()));
146
- else_block.add(code_assignt(clsid_tmp_sym.symbol_expr(), object_clsid));
116
+ // Replace the instanceof operation with (check_ptr != null &&
117
+ // (check_ptr->@class_identifier == "A" ||
118
+ // check_ptr->@class_identifier == "B" || ...
119
+
120
+ // By operating directly on a pointer rather than using a temporary
121
+ // (x->@clsid == "A" rather than id = x->@clsid; id == "A") we enable symex's
122
+ // value-set filtering to discard no-longer-viable candidates for "x" (in the
123
+ // case where 'x' is a symbol, not a general expression like x->y->@clsid).
124
+ // This means there are more clean dereference operations (ones where there
125
+ // is no possibility of reading a null, invalid or incorrectly-typed object),
126
+ // and less pessimistic aliasing assumptions possibly causing goto-symex to
127
+ // explore in-fact-unreachable paths.
147
128
148
129
exprt::operandst or_ops;
149
130
for(const auto &clsname : children)
150
131
{
151
132
constant_exprt clsexpr(clsname, string_typet());
152
- equal_exprt test(clsid_tmp_sym.symbol_expr() , clsexpr);
133
+ equal_exprt test(object_clsid , clsexpr);
153
134
or_ops.push_back(test);
154
135
}
155
- else_block.add(
156
- code_assignt(instanceof_result_sym.symbol_expr(), disjunction(or_ops)));
157
-
158
- const code_ifthenelset is_null_branch(
159
- equal_exprt(
160
- check_ptr, null_pointer_exprt(to_pointer_type(check_ptr.type()))),
161
- code_assignt(instanceof_result_sym.symbol_expr(), false_exprt()),
162
- std::move(else_block));
163
-
164
- // Replace the instanceof construct with instanceof_result:
165
- expr = instanceof_result_sym.symbol_expr();
166
-
167
- // Insert the new test block before it:
168
- goto_programt new_check_program;
169
- goto_convert(
170
- is_null_branch,
171
- symbol_table,
172
- new_check_program,
173
- message_handler,
174
- ID_java);
175
-
176
- goto_program.destructive_insert(this_inst, new_check_program);
136
+
137
+ notequal_exprt not_null(
138
+ check_ptr, null_pointer_exprt(to_pointer_type(check_ptr.type())));
139
+
140
+ expr = and_exprt(not_null, disjunction(or_ops));
177
141
178
142
return true;
179
143
}
0 commit comments