@@ -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