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