@@ -33,6 +33,7 @@ Author: Daniel Kroening, kroening@kroening.com
33
33
#include < util/std_expr.h>
34
34
#include < util/string2int.h>
35
35
#include < util/string_constant.h>
36
+ #include < util/threeval.h>
36
37
37
38
#include < goto-programs/cfg.h>
38
39
#include < goto-programs/class_hierarchy.h>
@@ -3173,44 +3174,87 @@ irep_idt java_bytecode_convert_methodt::get_static_field(
3173
3174
return inherited_method.get_full_component_identifier ();
3174
3175
}
3175
3176
3176
- // / create temporary variables if a write instruction can have undesired side-
3177
- // / effects
3177
+ // / Create temporary variables if a write instruction can have undesired side-
3178
+ // / effects.
3179
+ // / \param tmp_var_prefix: The prefix string to use for new temporary variables
3180
+ // / \param tmp_var_type: The type of the temporary variable.
3181
+ // / \param[out] block: The code block the assignment is added to if required.
3182
+ // / \param write_type: The enumeration type of the write instruction.
3183
+ // / \param identifier: The identifier of the symbol in the write instruction.
3178
3184
void java_bytecode_convert_methodt::save_stack_entries (
3179
3185
const std::string &tmp_var_prefix,
3180
3186
const typet &tmp_var_type,
3181
3187
code_blockt &block,
3182
3188
const bytecode_write_typet write_type,
3183
3189
const irep_idt &identifier)
3184
3190
{
3191
+ const std::function<bool (
3192
+ const std::function<tvt (const exprt &expr)>, const exprt &expr)>
3193
+ entry_matches = [&entry_matches, &identifier](
3194
+ const std::function<tvt (const exprt &expr)> predicate,
3195
+ const exprt &expr) {
3196
+ const tvt &tvres = predicate (expr);
3197
+ if (tvres.is_unknown ())
3198
+ {
3199
+ return std::any_of (
3200
+ expr.operands ().begin (),
3201
+ expr.operands ().end (),
3202
+ [&predicate, &entry_matches](const exprt &expr) {
3203
+ return entry_matches (predicate, expr);
3204
+ });
3205
+ }
3206
+ else
3207
+ {
3208
+ return tvres.is_true ();
3209
+ }
3210
+ };
3211
+
3212
+ const std::function<tvt (const exprt &expr)> has_member_entry = [&identifier](
3213
+ const exprt &expr) {
3214
+ const auto member_expr = expr_try_dynamic_cast<member_exprt>(expr);
3215
+ return !member_expr ? tvt::unknown ()
3216
+ : tvt (member_expr->get_component_name () == identifier);
3217
+ };
3218
+
3219
+ const std::function<tvt (const exprt &expr)> is_symbol_entry =
3220
+ [&identifier](const exprt &expr) {
3221
+ const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(expr);
3222
+ return !symbol_expr ? tvt::unknown ()
3223
+ : tvt (symbol_expr->get_identifier () == identifier);
3224
+ };
3225
+
3226
+ const std::function<tvt (const exprt &expr)> is_dereference_entry =
3227
+ [&identifier](const exprt &expr) {
3228
+ const auto dereference_expr =
3229
+ expr_try_dynamic_cast<dereference_exprt>(expr);
3230
+ return !dereference_expr ? tvt::unknown () : tvt (true );
3231
+ };
3232
+
3185
3233
for (auto &stack_entry : stack)
3186
3234
{
3187
- // remove typecasts if existing
3188
- while (stack_entry.id ()==ID_typecast)
3189
- stack_entry=to_typecast_expr (stack_entry).op ();
3190
-
3191
3235
// variables or static fields and symbol -> save symbols with same id
3192
- if ((write_type==bytecode_write_typet::VARIABLE ||
3193
- write_type==bytecode_write_typet::STATIC_FIELD) &&
3194
- stack_entry.id ()==ID_symbol)
3236
+ if (
3237
+ (write_type == bytecode_write_typet::VARIABLE ||
3238
+ write_type == bytecode_write_typet::STATIC_FIELD) &&
3239
+ entry_matches (is_symbol_entry, stack_entry))
3195
3240
{
3196
- const symbol_exprt &var=to_symbol_expr (stack_entry);
3197
- if (var.get_identifier ()==identifier)
3198
- create_stack_tmp_var (tmp_var_prefix, tmp_var_type, block, stack_entry);
3241
+ create_stack_tmp_var (tmp_var_prefix, tmp_var_type, block, stack_entry);
3199
3242
}
3200
3243
3201
3244
// array reference and dereference -> save all references on the stack
3202
- else if (write_type==bytecode_write_typet::ARRAY_REF &&
3203
- stack_entry.id ()==ID_dereference)
3245
+ else if (
3246
+ write_type == bytecode_write_typet::ARRAY_REF &&
3247
+ entry_matches (is_dereference_entry, stack_entry))
3248
+ {
3204
3249
create_stack_tmp_var (tmp_var_prefix, tmp_var_type, block, stack_entry);
3250
+ }
3205
3251
3206
3252
// field and member access -> compare component name
3207
- else if (write_type==bytecode_write_typet::FIELD &&
3208
- stack_entry.id ()==ID_member)
3253
+ else if (
3254
+ write_type == bytecode_write_typet::FIELD &&
3255
+ entry_matches (has_member_entry, stack_entry))
3209
3256
{
3210
- const irep_idt &entry_id=
3211
- to_member_expr (stack_entry).get_component_name ();
3212
- if (entry_id==identifier)
3213
- create_stack_tmp_var (tmp_var_prefix, tmp_var_type, block, stack_entry);
3257
+ create_stack_tmp_var (tmp_var_prefix, tmp_var_type, block, stack_entry);
3214
3258
}
3215
3259
}
3216
3260
}
0 commit comments