@@ -43,45 +43,62 @@ exprt assigns_clauset::targett::normalize(const exprt &expr)
4343exprt assigns_clauset::targett::generate_containment_check (
4444 const address_of_exprt &lhs_address) const
4545{
46- exprt::operandst condition;
46+ exprt::operandst address_validity;
47+ exprt::operandst containment_check;
4748
4849 // __CPROVER_w_ok(target, sizeof(target))
49- condition .push_back (w_ok_exprt (
50+ address_validity .push_back (w_ok_exprt (
5051 address,
5152 size_of_expr (dereference_exprt (address).type (), parent.ns ).value ()));
5253
54+ // __CPROVER_w_ok(lhs, sizeof(lhs))
55+ address_validity.push_back (w_ok_exprt (
56+ lhs_address,
57+ size_of_expr (dereference_exprt (lhs_address).type (), parent.ns ).value ()));
58+
5359 // __CPROVER_same_object(lhs, target)
54- condition .push_back (same_object (lhs_address, address));
60+ containment_check .push_back (same_object (lhs_address, address));
5561
5662 // If assigns target was a dereference, comparing objects is enough
57- if (id == ID_dereference)
63+ // and the resulting condition will be
64+ // __CPROVER_w_ok(target, sizeof(target))
65+ // && __CPROVER_w_ok(lhs, sizeof(lhs))
66+ // ==> __CPROVER_same_object(lhs, target)
67+ if (id != ID_dereference)
5868 {
59- return conjunction (condition);
69+ const auto lhs_offset = pointer_offset (lhs_address);
70+ const auto own_offset = pointer_offset (address);
71+
72+ // __CPROVER_offset(lhs) >= __CPROVER_offset(target)
73+ containment_check.push_back (
74+ binary_relation_exprt (lhs_offset, ID_ge, own_offset));
75+
76+ const auto lhs_region = plus_exprt (
77+ typecast_exprt::conditional_cast (
78+ size_of_expr (lhs_address.object ().type (), parent.ns ).value (),
79+ lhs_offset.type ()),
80+ lhs_offset);
81+
82+ const exprt own_region = plus_exprt (
83+ typecast_exprt::conditional_cast (
84+ size_of_expr (address.object ().type (), parent.ns ).value (),
85+ own_offset.type ()),
86+ own_offset);
87+
88+ // (sizeof(lhs) + __CPROVER_offset(lhs)) <=
89+ // (sizeof(target) + __CPROVER_offset(target))
90+ containment_check.push_back (
91+ binary_relation_exprt (lhs_region, ID_le, own_region));
6092 }
6193
62- const auto lhs_offset = pointer_offset (lhs_address);
63- const auto own_offset = pointer_offset (address);
64-
65- // __CPROVER_offset(lhs) >= __CPROVER_offset(target)
66- condition.push_back (binary_relation_exprt (lhs_offset, ID_ge, own_offset));
67-
68- const auto lhs_region = plus_exprt (
69- typecast_exprt::conditional_cast (
70- size_of_expr (lhs_address.object ().type (), parent.ns ).value (),
71- lhs_offset.type ()),
72- lhs_offset);
73-
74- const exprt own_region = plus_exprt (
75- typecast_exprt::conditional_cast (
76- size_of_expr (address.object ().type (), parent.ns ).value (),
77- own_offset.type ()),
78- own_offset);
79-
80- // (sizeof(lhs) + __CPROVER_offset(lhs)) <=
81- // (sizeof(target) + __CPROVER_offset(target))
82- condition.push_back (binary_relation_exprt (lhs_region, ID_le, own_region));
83-
84- return conjunction (condition);
94+ // __CPROVER_w_ok(target, sizeof(target))
95+ // && __CPROVER_w_ok(lhs, sizeof(lhs))
96+ // ==> __CPROVER_same_object(lhs, target)
97+ // && __CPROVER_offset(lhs) >= __CPROVER_offset(target)
98+ // && (sizeof(lhs) + __CPROVER_offset(lhs)) <=
99+ // (sizeof(target) + __CPROVER_offset(target))
100+ return binary_relation_exprt (
101+ conjunction (address_validity), ID_implies, conjunction (containment_check));
85102}
86103
87104assigns_clauset::assigns_clauset (
@@ -152,7 +169,6 @@ exprt assigns_clauset::generate_containment_check(const exprt &lhs) const
152169 {
153170 condition.push_back (target.generate_containment_check (lhs_address));
154171 }
155-
156172 for (const auto &target : global_write_set)
157173 {
158174 condition.push_back (target.generate_containment_check (lhs_address));
@@ -174,12 +190,6 @@ exprt assigns_clauset::generate_subset_check(
174190 exprt result = true_exprt ();
175191 for (const auto &subtarget : subassigns.global_write_set )
176192 {
177- // TODO: Optimize the implication generated due to the validity check.
178- // In some cases, e.g. when `subtarget` is known to be `NULL`,
179- // the implication can be skipped entirely. See #6105 for more details.
180- auto validity_check =
181- w_ok_exprt (subtarget.address , from_integer (0 , unsigned_int_type ()));
182-
183193 exprt::operandst current_subtarget_found_conditions;
184194 for (const auto &target : global_write_set)
185195 {
@@ -191,12 +201,7 @@ exprt assigns_clauset::generate_subset_check(
191201 current_subtarget_found_conditions.push_back (
192202 target.generate_containment_check (subtarget.address ));
193203 }
194-
195- auto current_subtarget_found = or_exprt (
196- not_exprt (validity_check),
197- disjunction (current_subtarget_found_conditions));
198-
199- result = and_exprt (result, current_subtarget_found);
204+ result = and_exprt (result, disjunction (current_subtarget_found_conditions));
200205 }
201206
202207 return result;
0 commit comments