@@ -457,74 +457,65 @@ static void replace_history_parameter_rec(
457
457
const source_locationt &location,
458
458
const irep_idt &mode,
459
459
goto_programt &history,
460
- const irep_idt &id )
460
+ const irep_idt &history_id )
461
461
{
462
462
for (auto &op : expr.operands ())
463
463
{
464
464
replace_history_parameter_rec (
465
- symbol_table, op, parameter2history, location, mode, history, id );
465
+ symbol_table, op, parameter2history, location, mode, history, history_id );
466
466
}
467
467
468
- if (expr.id () == ID_old || expr.id () == ID_loop_entry)
469
- {
470
- const auto ¶meter = to_history_expr (expr, id).expression ();
468
+ if (expr.id () != ID_old && expr.id () != ID_loop_entry)
469
+ return ;
471
470
472
- const auto &id = parameter.id ();
473
- if (
474
- id == ID_dereference || id == ID_member || id == ID_symbol ||
475
- id == ID_ptrmember || id == ID_constant || id == ID_typecast ||
476
- id == ID_index)
477
- {
478
- auto it = parameter2history.find (parameter);
471
+ const auto ¶meter = to_history_expr (expr, history_id).expression ();
472
+ const auto &id = parameter.id ();
473
+ if (
474
+ id != ID_dereference && id != ID_member && id != ID_symbol &&
475
+ id != ID_ptrmember && id != ID_constant && id != ID_typecast &&
476
+ id != ID_index)
477
+ {
478
+ throw invalid_source_file_exceptiont (
479
+ " Tracking history of " + id2string (parameter.id ()) +
480
+ " expressions is not supported yet." ,
481
+ expr.source_location ());
482
+ }
479
483
480
- if (it == parameter2history.end ())
481
- {
482
- // 0. Create a skip target to jump to, if the parameter is invalid
483
- goto_programt skip_program;
484
- const auto skip_target =
485
- skip_program.add (goto_programt::make_skip (location));
486
-
487
- // 1. Create a temporary symbol expression that represents the
488
- // history variable
489
- symbol_exprt tmp_symbol =
490
- new_tmp_symbol (parameter.type (), location, mode, symbol_table)
491
- .symbol_expr ();
492
-
493
- // 2. Associate the above temporary variable to it's corresponding
494
- // expression
495
- it = parameter2history.emplace (parameter, tmp_symbol).first ;
496
-
497
- // 3. Add the required instructions to the instructions list
498
- // 3.1. Declare the newly created temporary variable
499
- history.add (goto_programt::make_decl (tmp_symbol, location));
500
-
501
- // 3.2. Skip storing the history if the expression is invalid
502
- history.add (goto_programt::make_goto (
503
- skip_target,
504
- not_exprt{
505
- all_dereferences_are_valid (parameter, namespacet (symbol_table))},
506
- location));
507
-
508
- // 3.3. Add an assignment such that the value pointed to by the new
509
- // temporary variable is equal to the value of the corresponding
510
- // parameter
511
- history.add (
512
- goto_programt::make_assignment (tmp_symbol, parameter, location));
513
-
514
- // 3.4. Add a skip target
515
- history.destructive_append (skip_program);
516
- }
484
+ // speculatively insert a dummy, which will be replaced below if the insert
485
+ // actually happened
486
+ auto entry =
487
+ parameter2history.insert ({parameter, symbol_exprt::typeless (ID_nil)});
517
488
518
- expr = it->second ;
519
- }
520
- else
521
- {
522
- throw invalid_source_file_exceptiont (
523
- " Tracking history of " + id2string (parameter.id ()) +
524
- " expressions is not supported yet." ,
525
- expr.source_location ());
526
- }
489
+ if (entry.second )
490
+ {
491
+ // 1. Create a temporary symbol expression that represents the
492
+ // history variable
493
+ entry.first ->second =
494
+ new_tmp_symbol (parameter.type (), location, mode, symbol_table)
495
+ .symbol_expr ();
496
+
497
+ // 2. Add the required instructions to the instructions list
498
+ // 2.1. Declare the newly created temporary variable
499
+ history.add (goto_programt::make_decl (entry.first ->second , location));
500
+
501
+ // 2.2. Skip storing the history if the expression is invalid
502
+ auto goto_instruction = history.add (goto_programt::make_incomplete_goto (
503
+ not_exprt{
504
+ all_dereferences_are_valid (parameter, namespacet (symbol_table))},
505
+ location));
506
+
507
+ // 2.3. Add an assignment such that the value pointed to by the new
508
+ // temporary variable is equal to the value of the corresponding
509
+ // parameter
510
+ history.add (
511
+ goto_programt::make_assignment (entry.first ->second , parameter, location));
512
+
513
+ // 2.4. Complete conditional jump for invalid-parameter case
514
+ auto label_instruction = history.add (goto_programt::make_skip (location));
515
+ goto_instruction->complete_goto (label_instruction);
527
516
}
517
+
518
+ expr = entry.first ->second ;
528
519
}
529
520
530
521
replace_history_parametert replace_history_old (
0 commit comments