@@ -43,52 +43,62 @@ exprt assigns_clauset::targett::normalize(const exprt &expr)
43
43
exprt assigns_clauset::targett::generate_containment_check (
44
44
const address_of_exprt &lhs_address) const
45
45
{
46
- exprt::operandst condition;
46
+ exprt::operandst address_validity;
47
+ exprt::operandst containment_check;
47
48
48
49
// __CPROVER_w_ok(target, sizeof(target))
49
- condition .push_back (w_ok_exprt (
50
+ address_validity .push_back (w_ok_exprt (
50
51
address,
51
52
size_of_expr (dereference_exprt (address).type (), parent.ns ).value ()));
52
53
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
+
53
59
// __CPROVER_same_object(lhs, target)
54
- condition .push_back (same_object (lhs_address, address));
60
+ containment_check .push_back (same_object (lhs_address, address));
55
61
56
62
// 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)
58
68
{
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));
62
92
}
63
93
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));
92
102
}
93
103
94
104
assigns_clauset::assigns_clauset (
@@ -159,7 +169,6 @@ exprt assigns_clauset::generate_containment_check(const exprt &lhs) const
159
169
{
160
170
condition.push_back (target.generate_containment_check (lhs_address));
161
171
}
162
-
163
172
for (const auto &target : global_write_set)
164
173
{
165
174
condition.push_back (target.generate_containment_check (lhs_address));
@@ -181,12 +190,6 @@ exprt assigns_clauset::generate_subset_check(
181
190
exprt result = true_exprt ();
182
191
for (const auto &subtarget : subassigns.global_write_set )
183
192
{
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
-
190
193
exprt::operandst current_subtarget_found_conditions;
191
194
for (const auto &target : global_write_set)
192
195
{
@@ -198,12 +201,7 @@ exprt assigns_clauset::generate_subset_check(
198
201
current_subtarget_found_conditions.push_back (
199
202
target.generate_containment_check (subtarget.address ));
200
203
}
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));
207
205
}
208
206
209
207
return result;
0 commit comments