1
1
/* ******************************************************************\
2
2
3
- Module: Specify write set in function contracts.
3
+ Module: Specify write set in code contracts.
4
4
5
5
Author: Felipe R. Monteiro
6
6
@@ -19,129 +19,107 @@ Date: July 2021
19
19
#include < util/c_types.h>
20
20
#include < util/pointer_predicates.h>
21
21
22
- assigns_clause_targett::assigns_clause_targett (
23
- const exprt &object,
24
- code_contractst &contract,
25
- messaget &log_parameter,
26
- const irep_idt &function_id)
27
- : contract(contract),
28
- init_block(),
29
- log(log_parameter),
30
- target(pointer_for(object)),
31
- target_id(object.id())
22
+ assigns_clauset::targett::targett (
23
+ const assigns_clauset &parent,
24
+ const exprt &expr)
25
+ : expr(address_of_exprt(expr)), id(expr.id()), parent(parent)
32
26
{
33
- INVARIANT (
34
- target.type ().id () == ID_pointer,
35
- " Assigns clause targets should be stored as pointer expressions." );
36
27
}
37
28
38
- assigns_clause_targett::~assigns_clause_targett ()
39
- {
40
- }
41
-
42
- exprt assigns_clause_targett::alias_expression (const exprt &lhs)
29
+ exprt assigns_clauset::targett::alias_expression (const exprt &lhs) const
43
30
{
44
31
exprt::operandst condition;
45
- exprt lhs_ptr = (lhs.id () == ID_address_of) ? to_address_of_expr (lhs).object ()
46
- : pointer_for (lhs);
32
+ const auto lhs_ptr = (lhs.id () == ID_address_of)
33
+ ? to_address_of_expr (lhs).object ()
34
+ : address_of_exprt (lhs);
47
35
48
36
// __CPROVER_w_ok(target, sizeof(target))
49
37
condition.push_back (w_ok_exprt (
50
- target,
51
- size_of_expr (dereference_exprt (target).type (), contract.ns ).value ()));
38
+ expr, size_of_expr (dereference_exprt (expr).type (), parent.ns ).value ()));
52
39
53
40
// __CPROVER_same_object(lhs, target)
54
- condition.push_back (same_object (lhs_ptr, target ));
41
+ condition.push_back (same_object (lhs_ptr, expr ));
55
42
56
43
// If assigns target was a dereference, comparing objects is enough
57
- if (target_id == ID_dereference)
44
+ if (id == ID_dereference)
58
45
{
59
46
return conjunction (condition);
60
47
}
61
48
62
- const exprt lhs_offset = pointer_offset (lhs_ptr);
63
- const exprt target_offset = pointer_offset (target );
49
+ const auto lhs_offset = pointer_offset (lhs_ptr);
50
+ const auto own_offset = pointer_offset (expr );
64
51
65
52
// __CPROVER_offset(lhs) >= __CPROVER_offset(target)
66
- condition.push_back (binary_relation_exprt (lhs_offset, ID_ge, target_offset ));
53
+ condition.push_back (binary_relation_exprt (lhs_offset, ID_ge, own_offset ));
67
54
68
- const exprt region_lhs = plus_exprt (
55
+ const auto lhs_region = plus_exprt (
69
56
typecast_exprt::conditional_cast (
70
- size_of_expr (lhs.type (), contract .ns ).value (), lhs_offset.type ()),
57
+ size_of_expr (lhs.type (), parent .ns ).value (), lhs_offset.type ()),
71
58
lhs_offset);
72
59
73
- const exprt region_target = plus_exprt (
60
+ const exprt own_region = plus_exprt (
74
61
typecast_exprt::conditional_cast (
75
- size_of_expr (dereference_exprt (target ).type (), contract .ns ).value (),
76
- target_offset .type ()),
77
- target_offset );
62
+ size_of_expr (dereference_exprt (expr ).type (), parent .ns ).value (),
63
+ own_offset .type ()),
64
+ own_offset );
78
65
79
66
// (sizeof(lhs) + __CPROVER_offset(lhs)) <=
80
67
// (sizeof(target) + __CPROVER_offset(target))
81
- condition.push_back (binary_relation_exprt (region_lhs , ID_le, region_target ));
68
+ condition.push_back (binary_relation_exprt (lhs_region , ID_le, own_region ));
82
69
83
70
return conjunction (condition);
84
71
}
85
72
86
- exprt assigns_clause_targett ::compatible_expression (
87
- const assigns_clause_targett &called_target)
73
+ exprt assigns_clauset::targett ::compatible_expression (
74
+ const assigns_clauset::targett &other_target) const
88
75
{
89
- return same_object (called_target.get_target (), target);
90
- }
91
-
92
- const exprt &assigns_clause_targett::get_target () const
93
- {
94
- return target;
76
+ return same_object (other_target.expr , expr);
95
77
}
96
78
97
79
assigns_clauset::assigns_clauset (
98
- const exprt &assigns,
99
- code_contractst &contract,
100
- const irep_idt function_id,
101
- messaget log_parameter)
102
- : assigns(assigns),
103
- parent(contract),
104
- function_id(function_id),
105
- log(log_parameter)
80
+ const exprt &expr,
81
+ const messaget &log,
82
+ const namespacet &ns)
83
+ : expr(expr), log(log), ns(ns)
106
84
{
107
- for (exprt target : assigns .operands ())
85
+ for (const auto &target_expr : expr .operands ())
108
86
{
109
- add_target (target );
87
+ add_target (target_expr );
110
88
}
111
89
}
112
90
113
- assigns_clauset::~assigns_clauset ( )
91
+ void assigns_clauset::add_target ( const exprt &target_expr )
114
92
{
115
- for (assigns_clause_targett *target : targets)
93
+ auto insertion_succeeded =
94
+ targets
95
+ .emplace (
96
+ *this ,
97
+ (target_expr.id () == ID_address_of)
98
+ ? to_index_expr (to_address_of_expr (target_expr).object ()).array ()
99
+ : target_expr)
100
+ .second ;
101
+
102
+ if (!insertion_succeeded)
116
103
{
117
- delete target;
104
+ log .warning () << " Ignored duplicate expression '"
105
+ << from_expr (ns, target_expr.id (), target_expr)
106
+ << " ' in assigns clause at "
107
+ << target_expr.source_location ().as_string () << messaget::eom;
118
108
}
119
109
}
120
110
121
- void assigns_clauset::add_target (exprt target)
122
- {
123
- assigns_clause_targett *new_target = new assigns_clause_targett (
124
- (target.id () == ID_address_of)
125
- ? to_index_expr (to_address_of_expr (target).object ()).array ()
126
- : target,
127
- parent,
128
- log ,
129
- function_id);
130
- targets.push_back (new_target);
131
- }
132
-
133
- goto_programt assigns_clauset::havoc_code ()
111
+ goto_programt assigns_clauset::havoc_code () const
134
112
{
135
113
modifiest modifies;
136
- for (const auto &t : targets)
137
- modifies.insert (to_address_of_expr (t-> get_target () ).object ());
114
+ for (const auto &target : targets)
115
+ modifies.insert (to_address_of_expr (target. expr ).object ());
138
116
139
117
goto_programt havoc_statements;
140
- append_havoc_code (assigns .source_location (), modifies, havoc_statements);
118
+ append_havoc_code (expr .source_location (), modifies, havoc_statements);
141
119
return havoc_statements;
142
120
}
143
121
144
- exprt assigns_clauset::alias_expression (const exprt &lhs)
122
+ exprt assigns_clauset::alias_expression (const exprt &lhs) const
145
123
{
146
124
// If write set is empty, no assignment is allowed.
147
125
if (targets.empty ())
@@ -150,15 +128,15 @@ exprt assigns_clauset::alias_expression(const exprt &lhs)
150
128
}
151
129
152
130
exprt::operandst condition;
153
- for (assigns_clause_targett * target : targets)
131
+ for (const auto & target : targets)
154
132
{
155
- condition.push_back (target-> alias_expression (lhs));
133
+ condition.push_back (target. alias_expression (lhs));
156
134
}
157
135
return disjunction (condition);
158
136
}
159
137
160
138
exprt assigns_clauset::compatible_expression (
161
- const assigns_clauset &called_assigns)
139
+ const assigns_clauset &called_assigns) const
162
140
{
163
141
if (called_assigns.targets .empty ())
164
142
{
@@ -167,11 +145,11 @@ exprt assigns_clauset::compatible_expression(
167
145
168
146
bool first_clause = true ;
169
147
exprt result = true_exprt ();
170
- for (assigns_clause_targett * called_target : called_assigns.targets )
148
+ for (const auto & called_target : called_assigns.targets )
171
149
{
172
150
bool first_iter = true ;
173
151
exprt current_target_compatible = false_exprt ();
174
- for (assigns_clause_targett * target : targets)
152
+ for (const auto & target : targets)
175
153
{
176
154
if (first_iter)
177
155
{
@@ -180,30 +158,30 @@ exprt assigns_clauset::compatible_expression(
180
158
181
159
// Validating the called target through __CPROVER_w_ok() is
182
160
// only useful when the called target is a dereference
183
- const auto &called_target_ptr = called_target-> get_target () ;
161
+ const auto &called_target_ptr = called_target. expr ;
184
162
if (
185
163
to_address_of_expr (called_target_ptr).object ().id () == ID_dereference)
186
164
{
187
165
// or_exprt is short-circuited, therefore
188
- // target-> compatible_expression(*called_target) would not be
166
+ // target. compatible_expression(*called_target) would not be
189
167
// checked on invalid called_targets.
190
168
current_target_compatible = or_exprt (
191
169
not_exprt (w_ok_exprt (
192
170
called_target_ptr, from_integer (0 , unsigned_int_type ()))),
193
- target-> compatible_expression (* called_target));
171
+ target. compatible_expression (called_target));
194
172
}
195
173
else
196
174
{
197
175
current_target_compatible =
198
- target-> compatible_expression (* called_target);
176
+ target. compatible_expression (called_target);
199
177
}
200
178
first_iter = false ;
201
179
}
202
180
else
203
181
{
204
182
current_target_compatible = or_exprt (
205
183
current_target_compatible,
206
- target-> compatible_expression (* called_target));
184
+ target. compatible_expression (called_target));
207
185
}
208
186
}
209
187
if (first_clause)
0 commit comments