@@ -31,7 +31,6 @@ assigns_clause_targett::assigns_clause_targett(
3131 INVARIANT (
3232 pointer_object.type ().id () == ID_pointer,
3333 " Assigns clause targets should be stored as pointer expressions." );
34-
3534 const symbolt &function_symbol = contract.ns .lookup (function_id);
3635
3736 // Declare a new symbol to stand in for the reference
@@ -60,15 +59,49 @@ std::vector<symbol_exprt> assigns_clause_targett::temporary_declarations() const
6059 return result;
6160}
6261
63- exprt assigns_clause_targett::alias_expression (const exprt &ptr )
62+ exprt assigns_clause_targett::alias_expression (const exprt &lhs )
6463{
65- return same_object (ptr, local_target);
64+ exprt::operandst condition;
65+ exprt lhs_ptr = (lhs.id () == ID_address_of) ? to_address_of_expr (lhs).object ()
66+ : pointer_for (lhs);
67+
68+ // __CPROVER_same_object(lhs, target)
69+ condition.push_back (same_object (lhs_ptr, target));
70+
71+ // If assigns target was a dereference, comparing objects is enough
72+ if (target_id == ID_dereference)
73+ {
74+ return conjunction (condition);
75+ }
76+
77+ const exprt lhs_offset = pointer_offset (lhs_ptr);
78+ const exprt target_offset = pointer_offset (target);
79+
80+ // __CPROVER_offset(lhs) >= __CPROVER_offset(target)
81+ condition.push_back (binary_relation_exprt (lhs_offset, ID_ge, target_offset));
82+
83+ const exprt region_lhs = plus_exprt (
84+ typecast_exprt::conditional_cast (
85+ size_of_expr (lhs.type (), contract.ns ).value (), lhs_offset.type ()),
86+ lhs_offset);
87+
88+ const exprt region_target = plus_exprt (
89+ typecast_exprt::conditional_cast (
90+ size_of_expr (dereference_exprt (local_target).type (), contract.ns ).value (),
91+ target_offset.type ()),
92+ target_offset);
93+
94+ // (sizeof(lhs) + __CPROVER_offset(lhs)) <=
95+ // (sizeof(target) + __CPROVER_offset(target))
96+ condition.push_back (binary_relation_exprt (region_lhs, ID_le, region_target));
97+
98+ return conjunction (condition);
6699}
67100
68101exprt assigns_clause_targett::compatible_expression (
69102 const assigns_clause_targett &called_target)
70103{
71- return alias_expression (called_target.get_direct_pointer ());
104+ return same_object (called_target.get_direct_pointer (), local_target );
72105}
73106
74107goto_programt
@@ -107,9 +140,9 @@ assigns_clauset::assigns_clauset(
107140 function_id(function_id),
108141 log(log_parameter)
109142{
110- for (exprt current_operation : assigns_expr.operands ())
143+ for (exprt target : assigns_expr.operands ())
111144 {
112- add_target (current_operation );
145+ add_target (target );
113146 }
114147}
115148
@@ -121,17 +154,17 @@ assigns_clauset::~assigns_clauset()
121154 }
122155}
123156
124- assigns_clause_targett *assigns_clauset::add_target (exprt current_operation )
157+ assigns_clause_targett *assigns_clauset::add_target (exprt target )
125158{
126- assigns_clause_targett *target = new assigns_clause_targett (
127- (current_operation .id () == ID_address_of)
128- ? to_index_expr (to_address_of_expr (current_operation ).object ()).array ()
129- : current_operation ,
159+ assigns_clause_targett *new_target = new assigns_clause_targett (
160+ (target .id () == ID_address_of)
161+ ? to_index_expr (to_address_of_expr (target ).object ()).array ()
162+ : target ,
130163 parent,
131164 log,
132165 function_id);
133- targets.push_back (target );
134- return target ;
166+ targets.push_back (new_target );
167+ return new_target ;
135168}
136169
137170assigns_clause_targett *
@@ -239,28 +272,18 @@ goto_programt assigns_clauset::havoc_code(
239272
240273exprt assigns_clauset::alias_expression (const exprt &lhs)
241274{
275+ // If write set is empty, no assignment is allowed.
242276 if (targets.empty ())
243277 {
244278 return false_exprt ();
245279 }
246280
247- exprt left_ptr = assigns_clause_targett::pointer_for (lhs);
248-
249- bool first_iter = true ;
250- exprt result = false_exprt ();
281+ exprt::operandst condition;
251282 for (assigns_clause_targett *target : targets)
252283 {
253- if (first_iter)
254- {
255- result = target->alias_expression (left_ptr);
256- first_iter = false ;
257- }
258- else
259- {
260- result = or_exprt (result, target->alias_expression (left_ptr));
261- }
284+ condition.push_back (target->alias_expression (lhs));
262285 }
263- return result ;
286+ return disjunction (condition) ;
264287}
265288
266289exprt assigns_clauset::compatible_expression (
0 commit comments