@@ -43,46 +43,44 @@ static std::pair<goto_programt::targett, bool> insert_nondet_init_code(
4343 const irep_idt &mode)
4444{
4545 const auto next_instr = std::next (target);
46- bool changed = false ;
4746
4847 // We only expect to find nondets in the rhs of an assignments or in return
4948 // statements
5049 for (exprt &op : target->code .operands ())
5150 {
52- if (op. id () != ID_side_effect )
51+ if (!can_cast_expr<side_effect_expr_nondett>(op) )
5352 {
5453 continue ;
5554 }
5655
57- const auto &side_effect = to_side_effect_expr (op);
58- if (side_effect.get_statement () != ID_nondet)
59- {
60- continue ;
61- }
56+ const auto &nondet_expr = to_side_effect_expr_nondet (op);
6257
63- const typet &type = side_effect.type ();
6458 // If the lhs type doesn't have a subtype then I guess it's primitive and
65- // we want to bail out now
66- if (type.id () != ID_pointer)
67- {
68- continue ;
69- }
70-
71- // Although, if the type is a ptr-to-void or a function pointer then we also
72- // want to bail
73- if (type.subtype ().id () == ID_empty || type.subtype ().id () == ID_code)
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)
7465 {
7566 continue ;
7667 }
7768
78- if (!to_side_effect_expr_nondet (side_effect) .get_nullable ())
69+ if (!nondet_expr .get_nullable ())
7970 object_factory_parameters.max_nonnull_tree_depth = 1 ;
8071
81- // Get the symbol to nondet-init
8272 const auto source_loc = target->source_location ;
8373
84- // Create symbol for storing nondet object. We will replace `op` with this
85- // symbol.
74+ // Currently the code looks like this
75+ // target: original instruction
76+ // When we are done it will look like this
77+ // target : declare aux_symbol
78+ // . <gen_nondet_init_instructions - many lines>
79+ // . <gen_nondet_init_instructions - many lines>
80+ // . <gen_nondet_init_instructions - many lines>
81+ // target2: orig instruction with op replaced by aux_symbol
82+ // dead aux_symbol
83+
8684 symbolt &aux_symbol = get_fresh_aux_symbol (
8785 type,
8886 id2string (goto_programt::get_function_id (goto_program)),
@@ -93,54 +91,54 @@ static std::pair<goto_programt::targett, bool> insert_nondet_init_code(
9391 aux_symbol.is_static_lifetime = false ;
9492
9593 const symbol_exprt aux_symbol_expr = aux_symbol.symbol_expr ();
96- code_declt decl (aux_symbol_expr);
97- decl.add_source_location () = source_loc;
94+ op = aux_symbol_expr;
9895
99- // Create goto instructions for declaring and deading aux_symbol
100- goto_programt aux_instructions;
101- code_blockt aux_block;
102- aux_block.move (decl);
103- goto_convert (
104- aux_block, symbol_table, aux_instructions, message_handler, mode);
105- CHECK_RETURN (aux_instructions.instructions .size () == 2 );
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+ // Insert an instruction declaring `aux_symbol` before `target`, being
104+ // careful to preserve jumps to `target`
105+ goto_programt::instructiont decl_aux_symbol (DECL);
106+ decl_aux_symbol.code = code_declt (aux_symbol_expr);
107+ decl_aux_symbol.source_location = source_loc;
108+ goto_program.insert_before_swap (target, decl_aux_symbol);
106109
107- code_blockt init_code;
110+ // Keep track of the new location of the original instruction.
111+ const goto_programt::targett target2 = std::next (target);
108112
113+ code_blockt gen_nondet_init_code;
109114 const bool skip_classid = true ;
110115 gen_nondet_init (
111116 aux_symbol_expr,
112- init_code ,
117+ gen_nondet_init_code ,
113118 symbol_table,
114119 source_loc,
115120 skip_classid,
116121 allocation_typet::DYNAMIC,
117122 object_factory_parameters,
118123 update_in_placet::NO_UPDATE_IN_PLACE);
119124
120- goto_programt nondet_init_instructions ;
125+ goto_programt gen_nondet_init_instructions ;
121126 goto_convert (
122- init_code, symbol_table, nondet_init_instructions, message_handler, mode);
123-
124- // First insert the declaration of aux_symbol at the front of
125- // nondet_init_instructions
126- nondet_init_instructions.insert_before_swap (
127- nondet_init_instructions.instructions .begin (),
128- aux_instructions.instructions .front ());
129-
130- // Insert nondet_init_instructions into the instruction list before target
131- goto_program.destructive_insert (target, nondet_init_instructions);
132-
133- // Replace op with aux symbol in target
134- op = aux_symbol_expr;
127+ gen_nondet_init_code,
128+ symbol_table,
129+ gen_nondet_init_instructions,
130+ message_handler,
131+ mode);
135132
136- // Finally insert the dead instruction for aux_symbol after target
137- goto_program.insert_after (target)->swap (
138- aux_instructions.instructions .back ());
133+ goto_program.destructive_insert (target2, gen_nondet_init_instructions);
139134
140- changed = true ;
135+ // In theory target could have more than one operand which should be
136+ // replaced by convert_nondet, so we return target2 so that it
137+ // will be checked again
138+ return std::make_pair (target2, true );
141139 }
142140
143- return std::make_pair (next_instr, changed );
141+ return std::make_pair (next_instr, false );
144142}
145143
146144// / For each instruction in the goto program, checks if it is an assignment from
0 commit comments