@@ -427,25 +427,6 @@ void local_value_set_analysist::transform_function_stub(
427427 }
428428 else if (has_prefix (lhs_fieldname.base_name , precise_evs_prefix))
429429 {
430- std::vector<std::string> suffix_vec;
431- // / Split the field name into individual field dereferences, so ".x.y"
432- // / turns into ['.x', '.y']
433- const char delim=' .' ;
434- std::string::const_iterator start=lhs_fieldname.field_name .begin ();
435- for (
436- std::string::const_iterator it
437- =std::next (lhs_fieldname.field_name .begin ());
438- it!=lhs_fieldname.field_name .end ();
439- ++it)
440- {
441- if (*it==delim)
442- {
443- suffix_vec.emplace_back (start, it);
444- start=it;
445- }
446- }
447- suffix_vec.emplace_back (start, lhs_fieldname.field_name .end ());
448-
449430 const external_value_set_exprt::access_path_entriest
450431 &access_path_entries =
451432 to_external_value_set (lhs_fieldname.structured_lhs )
@@ -552,6 +533,88 @@ bool local_value_set_analysist::is_singular(const std::set<exprt> &values)
552533 return baset::is_singular (values);
553534}
554535
536+ void local_value_set_analysist::operator ()(const goto_programt &goto_program)
537+ {
538+ initialize (goto_program);
539+ // / This is a dummy variable that will always be empty because we handle
540+ // / function calls specially
541+ goto_functionst goto_functions;
542+
543+ while (true )
544+ {
545+ bool fixedpoint_changed_valuesets =
546+ static_analysis_baset::fixedpoint (goto_program, goto_functions);
547+
548+ if (!fixedpoint_changed_valuesets)
549+ break ;
550+
551+ bool initializer_precise_evs_added =
552+ add_precise_evs_initializers (goto_program);
553+
554+ if (!initializer_precise_evs_added)
555+ break ;
556+ }
557+ }
558+
559+ bool local_value_set_analysist::add_precise_evs_initializers (
560+ const goto_programt &goto_program)
561+ {
562+ const std::string precise_evs_prefix = PRECISE_EVS_PREFIX;
563+ bool any_changes = false ;
564+
565+ for (locationt loc = goto_program.instructions .begin ();
566+ loc != goto_program.instructions .end ();
567+ ++loc)
568+ {
569+ if (loc->incoming_edges .size () <= 1 )
570+ continue ;
571+
572+ // / At each place in the control flow graph where two or more paths join
573+ // / together, we look through all the predecessors and see which precise
574+ // / EVSs occur in the left hand sides of their domains.
575+ std::map<irep_idt, unsigned long > precise_evs_counts;
576+
577+ for (goto_programt::instructionst::const_iterator predecessor :
578+ loc->incoming_edges )
579+ {
580+ for (const auto &value : (*this )[predecessor].value_set .values )
581+ {
582+ const exprt &lhs = value.second .structured_lhs ;
583+
584+ if (
585+ can_cast_expr<external_value_set_exprt>(lhs) &&
586+ to_external_value_set (lhs).get_external_value_set_type () ==
587+ external_value_set_typet::PRECISE)
588+ {
589+ ++precise_evs_counts[value.first ];
590+ }
591+ }
592+ }
593+
594+ // / For each precise EVSs which occurs in some predecessor but not
595+ // / all, we add a copy of the EVS with is_initializer set to true to the
596+ // / value-set at the join instruction, to account for the fact that there
597+ // / is a path to this point where it still has its initial value.
598+ for (const auto identifier_count : precise_evs_counts)
599+ {
600+ if (identifier_count.second < loc->incoming_edges .size ())
601+ {
602+ local_value_sett &value_set = (*this )[loc].value_set ;
603+ value_sett::entryt &entry = value_set.values [identifier_count.first ];
604+
605+ external_value_set_exprt init_evs =
606+ to_external_value_set (entry.structured_lhs ).as_initializer ();
607+
608+ bool object_map_changed = value_set.insert (entry.object_map , init_evs);
609+
610+ if (object_map_changed)
611+ any_changes = true ;
612+ }
613+ }
614+ }
615+ return any_changes;
616+ }
617+
555618// / Finds expressions that are reachable from parameters or global variables
556619// / according to a given value-set-analysis state. For example:
557620// /
@@ -631,7 +694,7 @@ void lvsaa_single_external_set_summaryt::from_final_state(
631694 // field ones. If this is not possible then we export per field ones
632695 // and not precise ones.
633696 const bool should_export_precise_evs=
634- final_state.should_apply_precise_external_value_sets ();
697+ final_state.should_export_precise_external_value_sets ();
635698
636699 // Picks which value-set LHS expressions may be external to this function:
637700 for (auto it=final_state.values .begin ();
0 commit comments