22
22
23
23
#include " java_object_factory.h" // gen_nondet_init
24
24
25
+ // / Return whether `expr` is a nondet pointer that we should convert
26
+ static bool is_nondet_pointer (exprt expr)
27
+ {
28
+ // If the expression type doesn't have a subtype then I guess it's primitive
29
+ // and we do not want to convert it. If the type is a ptr-to-void or a
30
+ // function pointer then we also do not want to convert it.
31
+ const typet &type = expr.type ();
32
+ const bool non_void_non_function_pointer = type.id () == ID_pointer &&
33
+ type.subtype ().id () != ID_empty &&
34
+ type.subtype ().id () != ID_code;
35
+ return can_cast_expr<side_effect_expr_nondett>(expr) &&
36
+ non_void_non_function_pointer;
37
+ }
38
+
39
+ // / Populate `instructions` with goto instructions to nondet init
40
+ // / `aux_symbol_expr`
41
+ static void get_gen_nondet_init_instructions (
42
+ goto_programt &instructions,
43
+ const symbol_exprt &aux_symbol_expr,
44
+ const source_locationt &source_loc,
45
+ symbol_table_baset &symbol_table,
46
+ message_handlert &message_handler,
47
+ const object_factory_parameterst &object_factory_parameters,
48
+ const irep_idt &mode)
49
+ {
50
+ code_blockt gen_nondet_init_code;
51
+ const bool skip_classid = true ;
52
+ gen_nondet_init (
53
+ aux_symbol_expr,
54
+ gen_nondet_init_code,
55
+ symbol_table,
56
+ source_loc,
57
+ skip_classid,
58
+ allocation_typet::DYNAMIC,
59
+ object_factory_parameters,
60
+ update_in_placet::NO_UPDATE_IN_PLACE);
61
+
62
+ goto_convert (
63
+ gen_nondet_init_code, symbol_table, instructions, message_handler, mode);
64
+ }
65
+
25
66
// / Checks an instruction to see whether it contains an assignment from
26
67
// / side_effect_expr_nondet. If so, replaces the instruction with a range of
27
68
// / instructions to properly nondet-initialize the lhs.
@@ -44,94 +85,70 @@ static std::pair<goto_programt::targett, bool> insert_nondet_init_code(
44
85
{
45
86
const auto next_instr = std::next (target);
46
87
47
- // We only expect to find nondets in the rhs of an assignments or in return
48
- // statements
88
+ // We only expect to find nondets in the rhs of an assignments, and in return
89
+ // statements if remove_returns has not been run, but we do a more general
90
+ // check on all operands in case this changes
49
91
for (exprt &op : target->code .operands ())
50
92
{
51
- if (!can_cast_expr<side_effect_expr_nondett> (op))
93
+ if (!is_nondet_pointer (op))
52
94
{
53
95
continue ;
54
96
}
55
97
56
- const auto &nondet_expr = to_side_effect_expr_nondet (op);
57
-
58
- // If the lhs type doesn't have a subtype then I guess it's primitive and
59
- // we want to bail out now. If the type is a ptr-to-void or a function
60
- // pointer then we also want to bail.
61
- const typet &type = nondet_expr.type ();
62
- if (
63
- type.id () != ID_pointer || type.subtype ().id () == ID_empty ||
64
- type.subtype ().id () == ID_code)
65
- {
66
- continue ;
67
- }
98
+ const auto &nondet_expr = to_side_effect_expr_nondet (op);
68
99
69
100
if (!nondet_expr.get_nullable ())
70
101
object_factory_parameters.max_nonnull_tree_depth = 1 ;
71
102
72
- const auto source_loc = target->source_location ;
103
+ const source_locationt & source_loc = target->source_location ;
73
104
74
105
// Currently the code looks like this
75
- // target: original instruction
106
+ // target: instruction containing op
76
107
// When we are done it will look like this
77
108
// target : declare aux_symbol
78
109
// . <gen_nondet_init_instructions - many lines>
79
110
// . <gen_nondet_init_instructions - many lines>
80
111
// . <gen_nondet_init_instructions - many lines>
81
- // target2: orig instruction with op replaced by aux_symbol
112
+ // target2: instruction containing op, with op replaced by aux_symbol
82
113
// dead aux_symbol
83
114
84
115
symbolt &aux_symbol = get_fresh_aux_symbol (
85
- type,
116
+ op. type () ,
86
117
id2string (goto_programt::get_function_id (goto_program)),
87
118
" nondet_tmp" ,
88
119
source_loc,
89
120
ID_java,
90
121
symbol_table);
91
- aux_symbol.is_static_lifetime = false ;
92
122
93
123
const symbol_exprt aux_symbol_expr = aux_symbol.symbol_expr ();
94
124
op = aux_symbol_expr;
95
125
96
- // It is simplest to insert the final instruction first, before everything
97
- // gets moved around
98
- goto_programt::targett dead_aux_symbol = goto_program.insert_after (target);
99
- dead_aux_symbol->type = DEAD;
100
- dead_aux_symbol->code = code_deadt (aux_symbol_expr);
101
- dead_aux_symbol->source_location = source_loc;
102
-
103
126
// Insert an instruction declaring `aux_symbol` before `target`, being
104
127
// careful to preserve jumps to `target`
105
- goto_programt::instructiont decl_aux_symbol (DECL) ;
106
- decl_aux_symbol.code = code_declt (aux_symbol_expr);
128
+ goto_programt::instructiont decl_aux_symbol;
129
+ decl_aux_symbol.make_decl ( code_declt (aux_symbol_expr) );
107
130
decl_aux_symbol.source_location = source_loc;
108
131
goto_program.insert_before_swap (target, decl_aux_symbol);
109
132
110
- // Keep track of the new location of the original instruction.
133
+ // Keep track of the new location of the instruction containing op .
111
134
const goto_programt::targett target2 = std::next (target);
112
135
113
- code_blockt gen_nondet_init_code ;
114
- const bool skip_classid = true ;
115
- gen_nondet_init (
136
+ goto_programt gen_nondet_init_instructions ;
137
+ get_gen_nondet_init_instructions (
138
+ gen_nondet_init_instructions,
116
139
aux_symbol_expr,
117
- gen_nondet_init_code,
118
- symbol_table,
119
140
source_loc,
120
- skip_classid,
121
- allocation_typet::DYNAMIC,
122
- object_factory_parameters,
123
- update_in_placet::NO_UPDATE_IN_PLACE);
124
-
125
- goto_programt gen_nondet_init_instructions;
126
- goto_convert (
127
- gen_nondet_init_code,
128
141
symbol_table,
129
- gen_nondet_init_instructions,
130
142
message_handler,
143
+ object_factory_parameters,
131
144
mode);
132
-
133
145
goto_program.destructive_insert (target2, gen_nondet_init_instructions);
134
146
147
+ goto_programt::targett dead_aux_symbol = goto_program.insert_after (target2);
148
+ dead_aux_symbol->make_dead ();
149
+ dead_aux_symbol->code = code_deadt (aux_symbol_expr);
150
+ dead_aux_symbol->source_location = source_loc;
151
+
135
152
// In theory target could have more than one operand which should be
136
153
// replaced by convert_nondet, so we return target2 so that it
137
154
// will be checked again
@@ -159,9 +176,8 @@ void convert_nondet(
159
176
{
160
177
bool changed = false ;
161
178
auto instruction_iterator = goto_program.instructions .begin ();
162
- auto end = goto_program.instructions .end ();
163
179
164
- while (instruction_iterator != end)
180
+ while (instruction_iterator != goto_program. instructions . end () )
165
181
{
166
182
auto ret = insert_nondet_init_code (
167
183
goto_program,
0 commit comments