@@ -344,6 +344,30 @@ void value_sett::get_value_set(
344
344
get_value_set_rec (tmp, dest, " " , tmp.type (), ns);
345
345
}
346
346
347
+ // / Check if 'suffix' starts with 'field'.
348
+ // / Suffix is delimited by periods and '[]' (array access) tokens, so we're
349
+ // / looking for ".field($|[]|.)"
350
+ static bool suffix_starts_with_field (
351
+ const std::string &suffix, const std::string &field)
352
+ {
353
+ return
354
+ !suffix.empty () &&
355
+ suffix[0 ] == ' .' &&
356
+ suffix.compare (1 , field.length (), field) == 0 &&
357
+ (suffix.length () == field.length () + 1 ||
358
+ suffix[field.length () + 1 ] == ' .' ||
359
+ suffix[field.length () + 1 ] == ' [' );
360
+ }
361
+
362
+ static std::string strip_first_field_from_suffix (
363
+ const std::string &suffix, const std::string &field)
364
+ {
365
+ INVARIANT (
366
+ suffix_starts_with_field (suffix, field),
367
+ " suffix should start with " + field);
368
+ return suffix.substr (field.length () + 1 );
369
+ }
370
+
347
371
void value_sett::get_value_set_rec (
348
372
const exprt &expr,
349
373
object_mapt &dest,
@@ -711,72 +735,113 @@ void value_sett::get_value_set_rec(
711
735
}
712
736
else if (expr.id ()==ID_struct)
713
737
{
738
+ const auto &struct_components = to_struct_type (expr_type).components ();
739
+ INVARIANT (
740
+ struct_components.size () == expr.operands ().size (),
741
+ " struct expression should have an operand per component" );
742
+ auto component_iter = struct_components.begin ();
743
+ bool found_component = false ;
744
+
714
745
// a struct constructor, which may contain addresses
746
+
715
747
forall_operands (it, expr)
716
- get_value_set_rec (*it, dest, suffix, original_type, ns);
748
+ {
749
+ const std::string &component_name =
750
+ id2string (component_iter->get_name ());
751
+ if (suffix_starts_with_field (suffix, component_name))
752
+ {
753
+ std::string remaining_suffix =
754
+ strip_first_field_from_suffix (suffix, component_name);
755
+ get_value_set_rec (*it, dest, remaining_suffix, original_type, ns);
756
+ found_component = true ;
757
+ }
758
+ ++component_iter;
759
+ }
760
+
761
+ if (!found_component)
762
+ {
763
+ // Struct field doesn't appear as expected -- this has probably been
764
+ // cast from an incompatible type. Conservatively assume all fields may
765
+ // be of interest.
766
+ forall_operands (it, expr)
767
+ get_value_set_rec (*it, dest, suffix, original_type, ns);
768
+ }
717
769
}
718
770
else if (expr.id ()==ID_with)
719
771
{
720
- assert (expr.operands ().size ()==3 );
721
-
722
- // this is the array/struct
723
- object_mapt tmp_map0;
724
- get_value_set_rec (expr.op0 (), tmp_map0, suffix, original_type, ns);
772
+ const with_exprt &with_expr = to_with_expr (expr);
725
773
726
- // this is the update value -- note NO SUFFIX
727
- object_mapt tmp_map2;
728
- get_value_set_rec (expr.op2 (), tmp_map2, " " , original_type, ns);
729
-
730
- if (expr_type.id ()==ID_struct)
774
+ // If the suffix is empty we're looking for the whole struct:
775
+ // default to combining both options as below.
776
+ if (expr_type.id () == ID_struct && !suffix.empty ())
731
777
{
732
- #if 0
733
- const object_map_dt &object_map0=tmp_map0.read();
734
- irep_idt component_name=expr.op1().get(ID_component_name);
735
-
736
- bool insert=true;
737
-
738
- for(object_map_dt::const_iterator
739
- it=object_map0.begin();
740
- it!=object_map0.end();
741
- it++)
778
+ irep_idt component_name = with_expr.where ().get (ID_component_name);
779
+ if (suffix_starts_with_field (suffix, id2string (component_name)))
742
780
{
743
- const exprt &e=to_expr(it);
744
-
745
- if(e.id()==ID_member &&
746
- e.get(ID_component_name)==component_name)
747
- {
748
- if(insert)
749
- {
750
- dest.write().insert(tmp_map2.read().begin(), tmp_map2.read().end());
751
- insert=false;
752
- }
753
- }
754
- else
755
- dest.write().insert(*it);
781
+ // Looking for the member overwritten by this WITH expression
782
+ std::string remaining_suffix =
783
+ strip_first_field_from_suffix (suffix, id2string (component_name));
784
+ get_value_set_rec (
785
+ with_expr.new_value (), dest, remaining_suffix, original_type, ns);
786
+ }
787
+ else if (to_struct_type (expr_type).has_component (component_name))
788
+ {
789
+ // Looking for a non-overwritten member, look through this expression
790
+ get_value_set_rec (with_expr.old (), dest, suffix, original_type, ns);
791
+ }
792
+ else
793
+ {
794
+ // Member we're looking for is not defined in this struct -- this
795
+ // must be a reinterpret cast of some sort. Default to conservatively
796
+ // assuming either operand might be involved.
797
+ get_value_set_rec (expr.op0 (), dest, suffix, original_type, ns);
798
+ get_value_set_rec (expr.op2 (), dest, " " , original_type, ns);
756
799
}
757
- #else
758
- // Should be more precise! We only want "suffix"
759
- make_union (dest, tmp_map0);
760
- make_union (dest, tmp_map2);
761
- #endif
800
+ }
801
+ else if (expr_type.id () == ID_array && !suffix.empty ())
802
+ {
803
+ std::string new_value_suffix;
804
+ if (has_prefix (suffix, " []" ))
805
+ new_value_suffix = suffix.substr (2 );
806
+
807
+ // Otherwise use a blank suffix on the assumption anything involved with
808
+ // the new value might be interesting.
809
+
810
+ get_value_set_rec (with_expr.old (), dest, suffix, original_type, ns);
811
+ get_value_set_rec (
812
+ with_expr.new_value (), dest, new_value_suffix, original_type, ns);
762
813
}
763
814
else
764
815
{
765
- make_union (dest, tmp_map0);
766
- make_union (dest, tmp_map2);
816
+ // Something else-- the suffixes used here are a rough guess at best,
817
+ // so this is imprecise.
818
+ get_value_set_rec (expr.op0 (), dest, suffix, original_type, ns);
819
+ get_value_set_rec (expr.op2 (), dest, " " , original_type, ns);
767
820
}
768
821
}
769
822
else if (expr.id ()==ID_array)
770
823
{
771
824
// an array constructor, possibly containing addresses
825
+ std::string new_suffix = suffix;
826
+ if (has_prefix (suffix, " []" ))
827
+ new_suffix = suffix.substr (2 );
828
+ // Otherwise we're probably reinterpreting some other type -- try persisting
829
+ // with the current suffix for want of a better idea.
830
+
772
831
forall_operands (it, expr)
773
- get_value_set_rec (*it, dest, suffix , original_type, ns);
832
+ get_value_set_rec (*it, dest, new_suffix , original_type, ns);
774
833
}
775
834
else if (expr.id ()==ID_array_of)
776
835
{
777
836
// an array constructor, possibly containing an address
837
+ std::string new_suffix = suffix;
838
+ if (has_prefix (suffix, " []" ))
839
+ new_suffix = suffix.substr (2 );
840
+ // Otherwise we're probably reinterpreting some other type -- try persisting
841
+ // with the current suffix for want of a better idea.
842
+
778
843
assert (expr.operands ().size ()==1 );
779
- get_value_set_rec (expr.op0 (), dest, suffix , original_type, ns);
844
+ get_value_set_rec (expr.op0 (), dest, new_suffix , original_type, ns);
780
845
}
781
846
else if (expr.id ()==ID_dynamic_object)
782
847
{
0 commit comments