@@ -27,32 +27,25 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
27
27
if (operands.size ()==1 &&
28
28
operands[0 ].type ().id ()==ID_pointer)
29
29
{
30
- const bvt &bv=convert_bv (operands[0 ]);
31
-
32
- if (!bv.empty ())
33
- {
34
- bvt invalid_bv;
35
- encode (pointer_logic.get_invalid_object (), invalid_bv);
36
-
37
- bvt equal_invalid_bv;
38
- equal_invalid_bv.resize (object_bits);
30
+ // condition can only be evaluated once all (address-taken)
31
+ // objects are known, thus postpone
32
+ literalt l=prop.new_variable ();
39
33
40
- for (std::size_t i=0 ; i<object_bits; i++)
41
- {
42
- equal_invalid_bv[i]=prop.lequal (bv[offset_bits+i],
43
- invalid_bv[offset_bits+i]);
44
- }
34
+ postponed_list.push_back (postponedt ());
35
+ postponed_list.back ().op =convert_bv (operands[0 ]);
36
+ postponed_list.back ().bv .push_back (l);
37
+ postponed_list.back ().expr =expr;
45
38
46
- return prop.land (equal_invalid_bv);
47
- }
39
+ return l;
48
40
}
49
41
}
50
42
else if (expr.id () == ID_is_dynamic_object)
51
43
{
52
44
if (operands.size ()==1 &&
53
45
operands[0 ].type ().id ()==ID_pointer)
54
46
{
55
- // we postpone
47
+ // condition can only be evaluated once all (address-taken)
48
+ // objects are known, thus postpone
56
49
literalt l=prop.new_variable ();
57
50
58
51
postponed_list.push_back (postponedt ());
@@ -813,6 +806,82 @@ void bv_pointerst::do_postponed(
813
806
prop.l_set_to_true (prop.limplies (l1, l2));
814
807
}
815
808
}
809
+ else if (postponed.expr .id ()==ID_invalid_pointer)
810
+ {
811
+ const pointer_logict::objectst &objects=pointer_logic.objects ;
812
+
813
+ bvt disj;
814
+ disj.reserve (objects.size ());
815
+
816
+ bvt saved_bv=postponed.op ;
817
+ saved_bv.erase (saved_bv.begin (), saved_bv.begin ()+offset_bits);
818
+
819
+ bvt invalid_bv, null_bv;
820
+ encode (pointer_logic.get_invalid_object (), invalid_bv);
821
+ invalid_bv.erase (invalid_bv.begin (), invalid_bv.begin ()+offset_bits);
822
+ encode (pointer_logic.get_null_object (), null_bv);
823
+ null_bv.erase (null_bv.begin (), null_bv.begin ()+offset_bits);
824
+
825
+ disj.push_back (bv_utils.equal (saved_bv, invalid_bv));
826
+ disj.push_back (bv_utils.equal (saved_bv, null_bv));
827
+
828
+ // the pointer is invalid if its object part compares equal to
829
+ // any of the object parts of dynamic objects that have *not*
830
+ // been allocated (as their path condition, stored in
831
+ // ID_C_dynamic_guard, evaluates to false)
832
+ std::size_t number=0 ;
833
+
834
+ for (pointer_logict::objectst::const_iterator
835
+ it=objects.begin ();
836
+ it!=objects.end ();
837
+ ++it, ++number)
838
+ {
839
+ const exprt &expr=*it;
840
+
841
+ if (!pointer_logic.is_dynamic_object (expr) ||
842
+ !is_ssa_expr (expr))
843
+ continue ;
844
+
845
+ // only compare object part
846
+ bvt bv;
847
+ encode (number, bv);
848
+
849
+ bv.erase (bv.begin (), bv.begin ()+offset_bits);
850
+ POSTCONDITION (bv.size ()==saved_bv.size ());
851
+
852
+ literalt l1=bv_utils.equal (bv, saved_bv);
853
+
854
+ const ssa_exprt &ssa=to_ssa_expr (expr);
855
+
856
+ const exprt &guard=
857
+ static_cast <const exprt&>(
858
+ ssa.get_original_expr ().find (ID_C_dynamic_guard));
859
+
860
+ if (guard.is_nil ())
861
+ continue ;
862
+
863
+ const bvt &guard_bv=convert_bv (guard);
864
+ DATA_INVARIANT (guard_bv.size ()==1 , " guard expected to be Boolean" );
865
+ literalt l_guard=guard_bv[0 ];
866
+
867
+ disj.push_back (prop.land (!l_guard, l1));
868
+ }
869
+
870
+ // compare object part to max object number
871
+ bvt bv;
872
+ encode (number, bv);
873
+
874
+ bv.erase (bv.begin (), bv.begin ()+offset_bits);
875
+ POSTCONDITION (bv.size ()==saved_bv.size ());
876
+
877
+ disj.push_back (
878
+ bv_utils.rel (
879
+ saved_bv, ID_ge, bv, bv_utilst::representationt::UNSIGNED));
880
+
881
+ PRECONDITION (postponed.bv .size ()==1 );
882
+ literalt l=postponed.bv .front ();
883
+ prop.l_set_to (prop.lequal (prop.lor (disj), l), true );
884
+ }
816
885
else
817
886
UNREACHABLE;
818
887
}
0 commit comments