@@ -360,57 +360,42 @@ static void pop_frame(
360
360
{
361
361
PRECONDITION (!state.call_stack ().empty ());
362
362
363
+ const framet &frame = state.call_stack ().top ();
364
+
365
+ // restore program counter
366
+ symex_transition (state, frame.calling_location .pc , false );
367
+ state.source .function_id = frame.calling_location .function_id ;
368
+
369
+ // restore L1 renaming
370
+ state.level1 .restore_from (frame.old_level1 );
371
+
372
+ // If the program is multi-threaded then the state guard is used to
373
+ // accumulate assumptions (in symex_assume_l2) and must be left alone.
374
+ // If however it is single-threaded then we should restore the guard, as the
375
+ // guard coming out of the function may be more complex (e.g. if the callee
376
+ // was { if(x) while(true) { } } then the guard may still be `!x`),
377
+ // but at this point all control-flow paths have either converged or been
378
+ // proven unviable, so we can stop specifying the callee's constraints when
379
+ // we generate an assumption or VCC.
380
+
381
+ // If we're doing path exploration then we do tail-duplication, and we
382
+ // actually *are* in a more-restricted context than we were when the
383
+ // function began.
384
+ if (state.threads .size () == 1 && !doing_path_exploration)
363
385
{
364
- const framet &frame = state.call_stack ().top ();
365
-
366
- // restore program counter
367
- symex_transition (state, frame.calling_location .pc , false );
368
- state.source .function_id = frame.calling_location .function_id ;
369
-
370
- // restore L1 renaming
371
- state.level1 .restore_from (frame.old_level1 );
372
-
373
- // If the program is multi-threaded then the state guard is used to
374
- // accumulate assumptions (in symex_assume_l2) and must be left alone.
375
- // If however it is single-threaded then we should restore the guard, as the
376
- // guard coming out of the function may be more complex (e.g. if the callee
377
- // was { if(x) while(true) { } } then the guard may still be `!x`),
378
- // but at this point all control-flow paths have either converged or been
379
- // proven unviable, so we can stop specifying the callee's constraints when
380
- // we generate an assumption or VCC.
381
-
382
- // If we're doing path exploration then we do tail-duplication, and we
383
- // actually *are* in a more-restricted context than we were when the
384
- // function began.
385
- if (state.threads .size () == 1 && !doing_path_exploration)
386
- {
387
- state.guard = frame.guard_at_function_start ;
388
- }
389
-
390
- symex_renaming_levelt::viewt view;
391
- state.get_level2 ().current_names .get_view (view);
392
-
393
- std::vector<irep_idt> keys_to_erase;
394
-
395
- for (const auto &pair : view)
396
- {
397
- const irep_idt l1_o_id = pair.second .first .get_l1_object_identifier ();
398
-
399
- // could use iteration over local_objects as l1_o_id is prefix
400
- if (
401
- frame.local_objects .find (l1_o_id) == frame.local_objects .end () ||
402
- (state.threads .size () > 1 &&
403
- path_storage.dirty (pair.second .first .get_object_name ())))
404
- {
405
- continue ;
406
- }
386
+ state.guard = frame.guard_at_function_start ;
387
+ }
407
388
408
- keys_to_erase.push_back (pair.first );
409
- }
389
+ for (const irep_idt &l1_o_id : frame.local_objects )
390
+ {
391
+ const auto l2_entry_opt = state.get_level2 ().current_names .find (l1_o_id);
410
392
411
- for (const irep_idt &key : keys_to_erase)
393
+ if (
394
+ l2_entry_opt.has_value () &&
395
+ (state.threads .size () == 1 ||
396
+ !path_storage.dirty (l2_entry_opt->get ().first .get_object_name ())))
412
397
{
413
- state.drop_existing_l1_name (key );
398
+ state.drop_existing_l1_name (l1_o_id );
414
399
}
415
400
}
416
401
0 commit comments