@@ -43,52 +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- // __CPROVER_w_ok(target, sizeof(target)) &&
60- // __CPROVER_same_object(lhs, target)
61- 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));
6292 }
6393
64- const auto lhs_offset = pointer_offset (lhs_address);
65- const auto own_offset = pointer_offset (address);
66-
67- // __CPROVER_offset(lhs) >= __CPROVER_offset(target)
68- condition.push_back (binary_relation_exprt (lhs_offset, ID_ge, own_offset));
69-
70- const auto lhs_region = plus_exprt (
71- typecast_exprt::conditional_cast (
72- size_of_expr (lhs_address.object ().type (), parent.ns ).value (),
73- lhs_offset.type ()),
74- lhs_offset);
75-
76- const exprt own_region = plus_exprt (
77- typecast_exprt::conditional_cast (
78- size_of_expr (address.object ().type (), parent.ns ).value (),
79- own_offset.type ()),
80- own_offset);
81-
82- // (sizeof(lhs) + __CPROVER_offset(lhs)) <=
83- // (sizeof(target) + __CPROVER_offset(target))
84- condition.push_back (binary_relation_exprt (lhs_region, ID_le, own_region));
85-
86- // __CPROVER_w_ok(target, sizeof(target)) &&
87- // __CPROVER_same_object(lhs, target) &&
88- // __CPROVER_offset(lhs) >= __CPROVER_offset(target) &&
89- // (sizeof(lhs) + __CPROVER_offset(lhs)) <=
90- // (sizeof(target) + __CPROVER_offset(target))
91- 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));
92102}
93103
94104assigns_clauset::assigns_clauset (
@@ -159,7 +169,6 @@ exprt assigns_clauset::generate_containment_check(const exprt &lhs) const
159169 {
160170 condition.push_back (target.generate_containment_check (lhs_address));
161171 }
162-
163172 for (const auto &target : global_write_set)
164173 {
165174 condition.push_back (target.generate_containment_check (lhs_address));
@@ -181,12 +190,6 @@ exprt assigns_clauset::generate_subset_check(
181190 exprt result = true_exprt ();
182191 for (const auto &subtarget : subassigns.global_write_set )
183192 {
184- // TODO: Optimize the implication generated due to the validity check.
185- // In some cases, e.g. when `subtarget` is known to be `NULL`,
186- // the implication can be skipped entirely. See #6105 for more details.
187- auto validity_check =
188- w_ok_exprt (subtarget.address , from_integer (0 , unsigned_int_type ()));
189-
190193 exprt::operandst current_subtarget_found_conditions;
191194 for (const auto &target : global_write_set)
192195 {
@@ -198,12 +201,7 @@ exprt assigns_clauset::generate_subset_check(
198201 current_subtarget_found_conditions.push_back (
199202 target.generate_containment_check (subtarget.address ));
200203 }
201-
202- auto current_subtarget_found = or_exprt (
203- not_exprt (validity_check),
204- disjunction (current_subtarget_found_conditions));
205-
206- result = and_exprt (result, current_subtarget_found);
204+ result = and_exprt (result, disjunction (current_subtarget_found_conditions));
207205 }
208206
209207 return result;
0 commit comments