14
14
#include < analyses/variable-sensitivity/struct_abstract_object.h>
15
15
#include < analyses/variable-sensitivity/pointer_abstract_object.h>
16
16
#include < analyses/variable-sensitivity/array_abstract_object.h>
17
+ #include < analyses/variable-sensitivity/constant_pointer_abstract_object.h>
17
18
#include < analyses/ai.h>
18
19
#include < analyses/constant_propagator.h>
19
20
#include < util/simplify_expr.h>
@@ -60,7 +61,7 @@ abstract_object_pointert abstract_environmentt::eval(
60
61
ID_constant, [&](const exprt &expr)
61
62
{
62
63
return abstract_object_factory (
63
- expr.type (), to_constant_expr (expr));
64
+ expr.type (), to_constant_expr (expr), ns );
64
65
}
65
66
},
66
67
{
@@ -77,12 +78,12 @@ abstract_object_pointert abstract_environmentt::eval(
77
78
{
78
79
ID_address_of, [&](const exprt &expr)
79
80
{
80
- # if 0
81
- address_of_exprt address_expr(to_address_of_expr(expr));
82
- # endif
83
- // TODO(tkiley): This needs special handling
84
- // For now just return top
85
- return abstract_object_factory (expr. type (), true , false ) ;
81
+ sharing_ptrt<pointer_abstract_objectt> pointer_object=
82
+ std::dynamic_pointer_cast<pointer_abstract_objectt>(
83
+ abstract_object_factory (expr. type (), expr, ns));
84
+
85
+ // Store the abstract object in the pointer
86
+ return pointer_object ;
86
87
}
87
88
},
88
89
{
@@ -93,7 +94,7 @@ abstract_object_pointert abstract_environmentt::eval(
93
94
std::dynamic_pointer_cast<pointer_abstract_objectt>(
94
95
eval (dereference.pointer (), ns));
95
96
96
- return pointer_abstract_object->read_dereference (*this );
97
+ return pointer_abstract_object->read_dereference (*this , ns );
97
98
}
98
99
},
99
100
{
@@ -139,6 +140,7 @@ Function: abstract_environmentt::assign
139
140
Inputs:
140
141
expr - the expression to assign to
141
142
value - the value to assign to the expression
143
+ ns - the namespace
142
144
143
145
Outputs: A boolean, true if the assignment has changed the domain.
144
146
@@ -147,11 +149,14 @@ Function: abstract_environmentt::assign
147
149
\*******************************************************************/
148
150
149
151
bool abstract_environmentt::assign (
150
- const exprt &expr, const abstract_object_pointert value)
152
+ const exprt &expr, const abstract_object_pointert value, const namespacet &ns )
151
153
{
154
+ assert (value);
155
+
156
+ // Build a stack of index, member and dereference accesses which
157
+ // we will work through the relevant abstract objects
152
158
exprt s = expr;
153
159
std::stack<exprt> stactions; // I'm not a continuation, honest guv'
154
-
155
160
while (s.id () != ID_symbol)
156
161
{
157
162
if (s.id () == ID_index || s.id () == ID_member || s.id () == ID_dereference)
@@ -169,76 +174,12 @@ bool abstract_environmentt::assign(
169
174
170
175
symbol_exprt symbol_expr=to_symbol_expr (s);
171
176
177
+ // This is the root abstract object that is in the map of abstract objects
178
+ // It might not have the same type as value if the above stack isn't empty
172
179
abstract_object_pointert final_value;
173
180
174
181
if (!stactions.empty ())
175
182
{
176
- const exprt & next_expr=stactions.top ();
177
- stactions.pop ();
178
-
179
- typedef std::function<
180
- abstract_object_pointert (
181
- abstract_object_pointert, // The symbol we are modifying
182
- std::stack<exprt>, // The remaining stack
183
- abstract_object_pointert)> // The value we are writing.
184
- stacion_functiont;
185
-
186
- // Each handler takes the abstract object referenced, copies it,
187
- // writes according to the type of expression (e.g. for ID_member)
188
- // we would (should!) have an abstract_struct_objectt which has a
189
- // write_member which will attempt to update the abstract object for the
190
- // relevant member. This modified abstract object is returned and this
191
- // is inserted back into the map
192
- std::map<irep_idt,stacion_functiont> handlers=
193
- {
194
- {
195
- ID_index, [&](
196
- const abstract_object_pointert lhs_object,
197
- std::stack<exprt> stack,
198
- abstract_object_pointert rhs_object)
199
- {
200
- sharing_ptrt<array_abstract_objectt> array_abstract_object=
201
- std::dynamic_pointer_cast<array_abstract_objectt>(lhs_object);
202
- sharing_ptrt<array_abstract_objectt> modified_array=
203
- array_abstract_object->write_index (
204
- *this , stactions, to_index_expr (next_expr), rhs_object, false );
205
- return modified_array;
206
- }
207
- },
208
- {
209
- ID_member, [&](
210
- const abstract_object_pointert lhs_object,
211
- std::stack<exprt> stack,
212
- abstract_object_pointert rhs_object)
213
- {
214
- sharing_ptrt<struct_abstract_objectt> struct_abstract_object=
215
- std::dynamic_pointer_cast<struct_abstract_objectt>(lhs_object);
216
- sharing_ptrt<struct_abstract_objectt> modified_struct=
217
- struct_abstract_object->write_component (
218
- *this , stactions, to_member_expr (next_expr), rhs_object);
219
- return modified_struct;
220
- }
221
- },
222
- {
223
- ID_dereference, [&](
224
- const abstract_object_pointert lhs_object,
225
- std::stack<exprt> stack,
226
- abstract_object_pointert rhs_object)
227
- {
228
- sharing_ptrt<pointer_abstract_objectt> pointer_abstract_object=
229
- std::dynamic_pointer_cast<pointer_abstract_objectt>(lhs_object);
230
- sharing_ptrt<pointer_abstract_objectt> modified_pointer=
231
- pointer_abstract_object->write_dereference (
232
- *this , stactions, rhs_object, false );
233
- return modified_pointer;
234
- }
235
- }
236
- };
237
-
238
- // We added something to the stack that we couldn't deal with
239
- assert (handlers.find (next_expr.id ())!=handlers.end ());
240
- assert (value);
241
-
242
183
// The symbol is not in the map - it is therefore top
243
184
abstract_object_pointert symbol_object;
244
185
if (map.find (symbol_expr)==map.end ())
@@ -249,7 +190,7 @@ bool abstract_environmentt::assign(
249
190
{
250
191
symbol_object=map[symbol_expr];
251
192
}
252
- final_value=handlers[next_expr. id ()]( symbol_object, stactions, value );
193
+ final_value=write ( symbol_object, value, stactions, ns, false );
253
194
}
254
195
else
255
196
{
@@ -261,7 +202,6 @@ bool abstract_environmentt::assign(
261
202
if (final_value->is_top ())
262
203
{
263
204
map.erase (symbol_expr);
264
-
265
205
}
266
206
else
267
207
{
@@ -272,6 +212,120 @@ bool abstract_environmentt::assign(
272
212
273
213
/* ******************************************************************\
274
214
215
+ Function: abstract_object_pointert abstract_environmentt::write
216
+
217
+ Inputs:
218
+ lhs - the abstract object for the left hand side of the write (i.e. the one
219
+ to update).
220
+ rhs - the value we are trying to write to the left hand side
221
+ remaining_stack - what is left of the stack before the rhs can replace or be
222
+ merged with the rhs
223
+ ns - the namespace
224
+ merge_write - Are re replacing the left hand side with the right hand side
225
+ (e.g. we know for a fact that we are overwriting this object)
226
+ or could the write in fact not take place and therefore we
227
+ should merge to model the case where it did not.
228
+
229
+ Outputs: A modified version of the rhs after the write has taken place
230
+
231
+ Purpose: Write an abstract object onto another respecting a stack of
232
+ member, index and dereference access. This ping-pongs between
233
+ this method and the relevant write methods in abstract_struct,
234
+ abstract_pointer and abstract_array until the stack is empty
235
+
236
+ \*******************************************************************/
237
+
238
+ abstract_object_pointert abstract_environmentt::write (
239
+ abstract_object_pointert lhs,
240
+ abstract_object_pointert rhs,
241
+ std::stack<exprt> remaining_stack,
242
+ const namespacet &ns,
243
+ bool merge_write)
244
+ {
245
+ assert (!remaining_stack.empty ());
246
+ const exprt & next_expr=remaining_stack.top ();
247
+ remaining_stack.pop ();
248
+
249
+ typedef std::function<
250
+ abstract_object_pointert (
251
+ abstract_object_pointert, // The symbol we are modifying
252
+ std::stack<exprt>, // The remaining stack
253
+ abstract_object_pointert)> // The value we are writing.
254
+ stacion_functiont;
255
+
256
+ // Each handler takes the abstract object referenced, copies it,
257
+ // writes according to the type of expression (e.g. for ID_member)
258
+ // we would (should!) have an abstract_struct_objectt which has a
259
+ // write_member which will attempt to update the abstract object for the
260
+ // relevant member. This modified abstract object is returned and this
261
+ // is inserted back into the map
262
+ std::map<irep_idt, stacion_functiont> handlers=
263
+ {
264
+ {
265
+ ID_index, [&](
266
+ const abstract_object_pointert lhs_object,
267
+ std::stack<exprt> stack,
268
+ abstract_object_pointert rhs_object)
269
+ {
270
+ sharing_ptrt<array_abstract_objectt> array_abstract_object=
271
+ std::dynamic_pointer_cast<array_abstract_objectt>(lhs_object);
272
+
273
+ sharing_ptrt<array_abstract_objectt> modified_array=
274
+ array_abstract_object->write_index (
275
+ *this ,
276
+ stack,
277
+ to_index_expr (next_expr),
278
+ rhs_object,
279
+ merge_write);
280
+
281
+ return modified_array;
282
+ }
283
+ },
284
+ {
285
+ ID_member, [&](
286
+ const abstract_object_pointert lhs_object,
287
+ std::stack<exprt> stack,
288
+ abstract_object_pointert rhs_object)
289
+ {
290
+ sharing_ptrt<struct_abstract_objectt> struct_abstract_object=
291
+ std::dynamic_pointer_cast<struct_abstract_objectt>(lhs_object);
292
+
293
+ sharing_ptrt<struct_abstract_objectt> modified_struct=
294
+ struct_abstract_object->write_component (
295
+ *this ,
296
+ stack,
297
+ to_member_expr (next_expr),
298
+ rhs_object,
299
+ merge_write);
300
+
301
+ return modified_struct;
302
+ }
303
+ },
304
+ {
305
+ ID_dereference, [&](
306
+ const abstract_object_pointert lhs_object,
307
+ std::stack<exprt> stack,
308
+ abstract_object_pointert rhs_object)
309
+ {
310
+ sharing_ptrt<pointer_abstract_objectt> pointer_abstract_object=
311
+ std::dynamic_pointer_cast<pointer_abstract_objectt>(lhs_object);
312
+
313
+ sharing_ptrt<pointer_abstract_objectt> modified_pointer=
314
+ pointer_abstract_object->write_dereference (
315
+ *this , ns, stack, rhs_object, merge_write);
316
+
317
+ return modified_pointer;
318
+ }
319
+ }
320
+ };
321
+
322
+ // We added something to the stack that we couldn't deal with
323
+ assert (handlers.find (next_expr.id ())!=handlers.end ());
324
+ return handlers[next_expr.id ()](lhs, remaining_stack, rhs);
325
+ }
326
+
327
+ /* ******************************************************************\
328
+
275
329
Function: abstract_environmentt::assume
276
330
277
331
Inputs:
@@ -339,6 +393,11 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory(
339
393
return abstract_object_pointert (
340
394
new constant_abstract_valuet (type, top, bottom));
341
395
}
396
+ else if (type.id ()==ID_pointer)
397
+ {
398
+ return abstract_object_pointert (
399
+ new constant_pointer_abstract_objectt (type, top, bottom, *this ));
400
+ }
342
401
else
343
402
{
344
403
return abstract_object_pointert (new abstract_objectt (type, top, false ));
@@ -361,14 +420,19 @@ Function: abstract_environmentt::abstract_object_factory
361
420
\*******************************************************************/
362
421
363
422
abstract_object_pointert abstract_environmentt::abstract_object_factory (
364
- const typet type, const constant_exprt e ) const
423
+ const typet type, const exprt e, const namespacet &ns ) const
365
424
{
366
425
assert (type==e.type ());
367
426
if (type.id ()==ID_signedbv || type.id ()==ID_bool || type.id ()==ID_c_bool)
368
427
{
369
428
return abstract_object_pointert (
370
429
new constant_abstract_valuet (e));
371
430
}
431
+ else if (type.id ()==ID_pointer)
432
+ {
433
+ return abstract_object_pointert (
434
+ new constant_pointer_abstract_objectt (e, *this , ns));
435
+ }
372
436
else
373
437
{
374
438
return abstract_object_pointert (new abstract_objectt (e));
@@ -401,7 +465,6 @@ bool abstract_environmentt::merge(const abstract_environmentt &env)
401
465
402
466
std::stringstream merge_message;
403
467
404
-
405
468
ait<constant_propagator_domaint> ai;
406
469
symbol_tablet symbol_table;
407
470
namespacet ns (symbol_table);
0 commit comments