@@ -360,57 +360,42 @@ static void pop_frame(
360360{
361361 PRECONDITION (!state.call_stack ().empty ());
362362
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)
363385 {
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+ }
407388
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);
410392
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 ())))
412397 {
413- state.drop_existing_l1_name (key );
398+ state.drop_existing_l1_name (l1_o_id );
414399 }
415400 }
416401
0 commit comments