@@ -32,8 +32,66 @@ static void build_NONDET_retvals_replacements(
32
32
next_instr_it!=instructions.end ();
33
33
instr_it = next_instr_it, ++next_instr_it)
34
34
{
35
- if (instr_it->type !=FUNCTION_CALL || next_instr_it->type !=ASSIGN)
35
+ if (instr_it->type != FUNCTION_CALL || next_instr_it->type != ASSIGN)
36
+ {
37
+ if (instr_it->type == ASSIGN)
38
+ {
39
+ const code_assignt &assign = to_code_assign (instr_it->code );
40
+ if (assign.rhs ().id () == ID_side_effect)
41
+ {
42
+ const side_effect_exprt side_effect =
43
+ to_side_effect_expr (assign.rhs ());
44
+ if (side_effect.get_statement () == ID_nondet)
45
+ {
46
+ // See if we can see that this instruction is definitely
47
+ // dead. Iterate backwards through the program from the current
48
+ // instruction, looking for an unconditional GOTO or a target.
49
+ // If we find an unconditional GOTO first then the instruction
50
+ // is dead. If we find a target first then we must assume that
51
+ // it can be reached. If we reach the beginning before finding
52
+ // either then the instruction is reachable.
53
+ bool is_dead = true ;
54
+ for (auto sit = instr_it;
55
+ sit != instructions.begin ();
56
+ sit=std::prev (sit))
57
+ {
58
+ if (sit->is_target ())
59
+ {
60
+ is_dead = false ;
61
+ break ;
62
+ }
63
+ if (sit->type == GOTO && sit->guard .is_true ())
64
+ break ;
65
+ }
66
+ if (is_dead || side_effect.type ().id () == ID_pointer)
67
+ {
68
+ // Create a new static variable to put on the rhs of this
69
+ // assignment. When the instruction is dead then this is
70
+ // sound. Otherwise this is not sound, but it is
71
+ // preferable to having a pointer that could point to
72
+ // anything. A better solution would be to use the
73
+ // replace_java_nondet pass or similar.
74
+ static unsigned long counter = 0UL ;
75
+ std::stringstream sstr;
76
+ sstr << " @__CPROVER_NONDET_dead_replace_" << ++counter;
77
+ symbolt symbol;
78
+ symbol.type =
79
+ side_effect.type ().id () == ID_pointer ?
80
+ to_pointer_type (side_effect.type ()).subtype () :
81
+ side_effect.type ();
82
+ symbol.name = sstr.str ();
83
+ symbol.base_name = symbol.name ;
84
+ symbol.mode = ID_java;
85
+ symbol.pretty_name = symbol.name ;
86
+ symbol.is_static_lifetime = true ;
87
+ const_cast <symbol_tablet&>(model.symbol_table ).insert (symbol);
88
+ replacements.insert ({instr_it, symbol.symbol_expr ()});
89
+ }
90
+ }
91
+ }
92
+ }
36
93
continue ;
94
+ }
37
95
const code_function_callt &fn_call=to_code_function_call (instr_it->code );
38
96
if (fn_call.function ().id ()!=ID_symbol)
39
97
continue ;
0 commit comments