27
27
# include < iostream>
28
28
#endif
29
29
30
- // / Function: abstract_environmentt::eval
31
- // / Evaluate the value of an expression relative to the current domain
32
- // /
33
- // / \param expr: the expression to evaluate
34
- // / \param ns: the current namespace
35
- // /
36
- // / \return The abstract_object representing the value of the expression
37
30
abstract_object_pointert
38
31
abstract_environmentt::eval (const exprt &expr, const namespacet &ns) const
39
32
{
@@ -121,35 +114,6 @@ abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const
121
114
}
122
115
}
123
116
124
- // / Function: abstract_environmentt::assign
125
- // /
126
- // / \param expr: the expression to assign to
127
- // / \param value: the value to assign to the expression
128
- // / \param ns: the namespace
129
- // /
130
- // / \return A boolean, true if the assignment has changed the domain.
131
- // /
132
- // / Assign a value to an expression
133
- // /
134
- // / Assign is in principe simple, it updates the map with the new
135
- // / abstract object. The challenge is how to handle write to compound
136
- // / objects, for example:
137
- // / a[i].x.y = 23;
138
- // / In this case we clearly want to update a, but we need to delegate to
139
- // / the object in a so that it updates the right part of it (depending on
140
- // / what kind of array abstraction it is). So, as we find the variable
141
- // / ('a' in this case) we build a stack of which part of it is accessed.
142
- // /
143
- // / As abstractions may split the assignment into multiple writes (for
144
- // / example pointers that could point to several locations, arrays with
145
- // / non-constant indexes), each of which has to handle the rest of the
146
- // / compound write, thus the stack is passed (to write, which does the
147
- // / actual updating) as an explicit argument rather than just via
148
- // / recursion.
149
- // /
150
- // / The same use case (but for the opposite reason; because you will only
151
- // / update one of the multiple objects) is also why a merge_write flag is
152
- // / needed.
153
117
bool abstract_environmentt::assign (
154
118
const exprt &expr,
155
119
const abstract_object_pointert value,
@@ -257,26 +221,6 @@ bool abstract_environmentt::assign(
257
221
return true ;
258
222
}
259
223
260
- // / Function: abstract_object_pointert abstract_environmentt::write
261
- // /
262
- // / \param lhs: the abstract object for the left hand side of the write
263
- // / (i.e. the one to update).
264
- // / \param rhs: the value we are trying to write to the left hand side
265
- // / \param remaining_stack: what is left of the stack before the rhs can replace
266
- // / or be merged with the rhs
267
- // / \param ns: the namespace
268
- // / \param merge_write: Are we replacing the left hand side with the
269
- // / right hand side (e.g. we know for a fact that
270
- // / we are overwriting this object) or could the
271
- // / write in fact not take place and therefore we
272
- // / should merge to model the case where it did not.
273
- // /
274
- // / \return A modified version of the rhs after the write has taken place
275
- // /
276
- // / Write an abstract object onto another respecting a stack of
277
- // / member, index and dereference access. This ping-pongs between
278
- // / this method and the relevant write methods in abstract_struct,
279
- // / abstract_pointer and abstract_array until the stack is empty
280
224
abstract_object_pointert abstract_environmentt::write (
281
225
abstract_object_pointert lhs,
282
226
abstract_object_pointert rhs,
@@ -318,20 +262,6 @@ abstract_object_pointert abstract_environmentt::write(
318
262
}
319
263
}
320
264
321
- // / Function: abstract_environmentt::assume
322
- // /
323
- // / \param expr: the expression that is to be assumed
324
- // / \param ns: the current namespace
325
- // /
326
- // / \return True if the assume changed the domain.
327
- // /
328
- // / Reduces the domain to (an over-approximation) of the cases
329
- // / when the the expression holds. Used to implement assume
330
- // / statements and conditional branches.
331
- // / It would be valid to simply return false here because it
332
- // / is an over-approximation. We try to do better than that.
333
- // / The better the implementation the more precise the results
334
- // / will be.
335
265
bool abstract_environmentt::assume (const exprt &expr, const namespacet &ns)
336
266
{
337
267
// We should only attempt to assume Boolean things
@@ -380,17 +310,6 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns)
380
310
return false ;
381
311
}
382
312
383
- // / Function: abstract_environmentt::abstract_object_factory
384
- // /
385
- // / \param type: the type of the object whose state should be tracked
386
- // / \param top: does the type of the object start as top
387
- // / \param bottom: does the type of the object start as bottom in
388
- // / the two-value domain
389
- // /
390
- // / \return The abstract object that has been created
391
- // /
392
- // / Look at the configuration for the sensitivity and create an
393
- // / appropriate abstract_object
394
313
abstract_object_pointert abstract_environmentt::abstract_object_factory (
395
314
const typet &type,
396
315
const namespacet &ns,
@@ -402,15 +321,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory(
402
321
type, top, bottom, empty_constant_expr, *this , ns);
403
322
}
404
323
405
- // / Function: abstract_environmentt::abstract_object_factory
406
- // /
407
- // / \param type: the type of the object whose state should be tracked
408
- // / \param expr: the starting value of the symbol
409
- // /
410
- // / \return The abstract object that has been created
411
- // /
412
- // / Look at the configuration for the sensitivity and create an
413
- // / appropriate abstract_object, assigning an appropriate value
414
324
abstract_object_pointert abstract_environmentt::abstract_object_factory (
415
325
const typet &type,
416
326
const exprt &e,
@@ -419,19 +329,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory(
419
329
return abstract_object_factory (type, false , false , e, *this , ns);
420
330
}
421
331
422
- // / Function: abstract_environmentt::abstract_object_factory
423
- // /
424
- // / \param type: the type of the object whose state should be tracked
425
- // / \param top: does the type of the object start as top in the two-value domain
426
- // / \param bottom: does the type of the object start as bottom in
427
- // / the two-value domain
428
- // / \param expr: the starting value of the symbol if top and bottom
429
- // / are both false
430
- // /
431
- // / \return The abstract object that has been created
432
- // /
433
- // / Look at the configuration for the sensitivity and create an
434
- // / appropriate abstract_object
435
332
abstract_object_pointert abstract_environmentt::abstract_object_factory (
436
333
const typet &type,
437
334
bool top,
@@ -444,13 +341,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory(
444
341
type, top, bottom, e, environment, ns);
445
342
}
446
343
447
- // / Function: abstract_environmentt::merge
448
- // /
449
- // / \param env: the other environment
450
- // /
451
- // / \return A Boolean, true when the merge has changed something
452
- // /
453
- // / Computes the join between "this" and "b"
454
344
bool abstract_environmentt::merge (const abstract_environmentt &env)
455
345
{
456
346
// Use the sharing_map's "iterative over all differences" functionality
@@ -489,61 +379,35 @@ bool abstract_environmentt::merge(const abstract_environmentt &env)
489
379
}
490
380
}
491
381
492
- // / Function: abstract_environmentt::havoc
493
- // /
494
- // / \param havoc_string: diagnostic string to track down havoc causing.
495
- // /
496
- // / \return None
497
- // /
498
- // / Set the domain to top
499
382
void abstract_environmentt::havoc (const std::string &havoc_string)
500
383
{
501
384
// TODO(tkiley): error reporting
502
385
make_top ();
503
386
}
504
387
505
- // / Function: abstract_environmentt::make_top
506
- // /
507
- // / Set the domain to top
508
388
void abstract_environmentt::make_top ()
509
389
{
510
390
// since we assume anything is not in the map is top this is sufficient
511
391
map.clear ();
512
392
bottom = false ;
513
393
}
514
394
515
- // / Function: abstract_environmentt::make_bottom
516
- // /
517
- // / Set the domain to top
518
395
void abstract_environmentt::make_bottom ()
519
396
{
520
397
map.clear ();
521
398
bottom = true ;
522
399
}
523
400
524
- // / abstract_environmentt::is_bottom
525
- // /
526
- // / Gets whether the domain is bottom
527
401
bool abstract_environmentt::is_bottom () const
528
402
{
529
403
return map.empty () && bottom;
530
404
}
531
405
532
- // / Function: abstract_environmentt::is_top
533
- // /
534
- // / Gets whether the domain is top
535
406
bool abstract_environmentt::is_top () const
536
407
{
537
408
return map.empty () && !bottom;
538
409
}
539
410
540
- // / Function: abstract_environmentt::output
541
- // /
542
- // / \param out: the stream to write to
543
- // / \param ai: the abstract interpreter that contains this domain
544
- // / \param ns: the current namespace
545
- // /
546
- // / Print out all the values in the abstract object map
547
411
void abstract_environmentt::output (
548
412
std::ostream &out,
549
413
const ai_baset &ai,
@@ -562,9 +426,6 @@ void abstract_environmentt::output(
562
426
out << " }\n " ;
563
427
}
564
428
565
- // / Function: abstract_environmentt::verify
566
- // /
567
- // / Check there aren't any null pointer mapped values
568
429
bool abstract_environmentt::verify () const
569
430
{
570
431
decltype (map)::viewt view;
@@ -601,33 +462,11 @@ abstract_object_pointert abstract_environmentt::eval_expression(
601
462
return eval_obj->expression_transform (e, operands, *this , ns);
602
463
}
603
464
604
- // / Function: abstract_environmentt::erase
605
- // /
606
- // / \param expr: A symbol to delete from the map
607
- // /
608
- // /
609
- // / Delete a symbol from the map. This is necessary if the
610
- // / symbol falls out of scope and should no longer be tracked.
611
465
void abstract_environmentt::erase (const symbol_exprt &expr)
612
466
{
613
467
map.erase_if_exists (expr.get_identifier ());
614
468
}
615
469
616
- // / Function: abstract_environmentt::environment_diff
617
- // /
618
- // / Inputs: Two abstract_environmentt's that need to be intersected for,
619
- // / so that we can find symbols that have changed between
620
- // / different domains.
621
- // /
622
- // / Outputs: An std::vector containing the symbols that are present in
623
- // / both environments.
624
- // /
625
- // / Purpose: For our implementation of variable sensitivity domains, we
626
- // / need to be able to efficiently find symbols that have changed
627
- // / between different domains. To do this, we need to be able
628
- // / to quickly find which symbols have new written locations,
629
- // / which we do by finding the intersection between two different
630
- // / domains (environments).
631
470
std::vector<abstract_environmentt::map_keyt>
632
471
abstract_environmentt::modified_symbols (
633
472
const abstract_environmentt &first,
0 commit comments