@@ -38,10 +38,21 @@ class namespacet;
38
38
// / pairs of an `exprt` and an optional offset if known (0 for both dynamic
39
39
// / objects in the example given above). RHS expressions are represented using
40
40
// / numbering to avoid storing redundant duplicate expressions.
41
+ // /
42
+ // / A value_sett may have a base (stored in field base_value_set), in which case
43
+ // / any lookup that fails in this value-set will check the base, and any write
44
+ // / to this value-set will copy any entry in the base into this value-set before
45
+ // / performing the write (i.e. we act as a copy-on-write layer on top of the
46
+ // / base). This makes copying or union'ing value-sets with a common base
47
+ // / cheaper -- the intended use case is for faster local analysis on top of a
48
+ // / large, expensive-to-copy global context. value_sett::make_union requires
49
+ // / that the value-sets being merged have the same base (or both have no base);
50
+ // / it is up to the user to make sure this is true.
51
+
41
52
class value_sett
42
53
{
43
54
public:
44
- value_sett ():location_number(0 )
55
+ value_sett ():location_number(0 ), base_value_set( nullptr )
45
56
{
46
57
}
47
58
@@ -340,6 +351,12 @@ class value_sett
340
351
const entryt &e, const typet &type,
341
352
const namespacet &ns);
342
353
354
+ // / Gets the number of entries in this value-set.
355
+ valuest::size_type size () const
356
+ {
357
+ return values.size ();
358
+ }
359
+
343
360
// / Pretty-print this value-set
344
361
// / \param ns: global namespace
345
362
// / \param [out] out: stream to write to
@@ -366,6 +383,9 @@ class value_sett
366
383
// / \return true if anything changed.
367
384
bool make_union (const value_sett &new_values)
368
385
{
386
+ INVARIANT (
387
+ new_values.base_value_set == base_value_set,
388
+ " Unioned value-sets must have the same base" );
369
389
return make_union (new_values.values );
370
390
}
371
391
@@ -459,6 +479,11 @@ class value_sett
459
479
exprt &expr,
460
480
const namespacet &ns) const ;
461
481
482
+ // / Set the base value-set, to which failing queries fall through. Note for
483
+ // / simplicity's sake, at the moment this value-set must be empty when this
484
+ // / is called, and the base value-set cannot be reset later.
485
+ void set_base_value_set (const value_sett *base);
486
+
462
487
protected:
463
488
// / Reads the set of objects pointed to by `expr`, including making
464
489
// / recursive lookups for dereference operations etc.
@@ -550,6 +575,8 @@ class value_sett
550
575
const namespacet &)
551
576
{
552
577
}
578
+
579
+ const value_sett *base_value_set;
553
580
};
554
581
555
582
#endif // CPROVER_POINTER_ANALYSIS_VALUE_SET_H
0 commit comments