@@ -354,7 +354,48 @@ class ai_baset
354
354
virtual std::unique_ptr<statet> make_temporary_state (const statet &s)=0;
355
355
};
356
356
357
- // domainT is expected to be derived from ai_domain_baseT
357
+ // / Base class for static analyses. Any actual static analysis
358
+ // / must (a) inherit from this class and (b) provide a domain class as a
359
+ // / type argument, which must, in turn, inherit from \ref ai_domain_baset.
360
+ // /
361
+ // / From a user's perspective, this class provides three main classes of
362
+ // / functions:
363
+ // /
364
+ // / 1. Running a static analysis, via
365
+ // / \ref ai_baset#operator()(const irep_idt&,const goto_programt&, <!--
366
+ // / --> const namespacet&),
367
+ // / \ref ai_baset#operator()(const goto_functionst&,const namespacet&)
368
+ // / and \ref ai_baset#operator()(const goto_modelt&)
369
+ // / 2. Accessing the results of a static analysis, by looking up the result
370
+ // / for a given location \p l using
371
+ // / \ref ait#operator[](goto_programt::const_targett).
372
+ // / 3. Outputting the results of the analysis; see
373
+ // / \ref ai_baset#output(const namespacet&, const irep_idt&,
374
+ // / const goto_programt&, std::ostream&)const et cetera.
375
+ // /
376
+ // / A typical usage pattern would be to call the static analysis first,
377
+ // / and use `operator[]` afterwards to retrieve the results. The fixed
378
+ // / point algorithm used is a standard worklist algorithm; the current
379
+ // / implementation is flow- and path-sensitive, but not context-sensitive.
380
+ // /
381
+ // / From an analysis developer's perspective, an analysis is implemented by
382
+ // / inheriting from this class (or, if a concurrency-sensitive analysis is
383
+ // / required, from \ref concurrency_aware_ait), providing a class implementing
384
+ // / the abstract domain as the type for the \p domainT parameter. Most of the
385
+ // / actual analysis functions (in particular, the minimal element, the lattice
386
+ // / join, and the state transformer) are supplied using \p domainT.
387
+ // /
388
+ // / To control the analysis in more detail, you can also override the following
389
+ // / methods:
390
+ // / - \ref ait#initialize(const irep_idt&, const goto_programt&),
391
+ // / \ref ait#initialize(const irep_idt&,
392
+ // / const goto_functionst::goto_functiont&) and
393
+ // / \ref ait#initialize(const goto_functionst&), for pre-analysis
394
+ // / initialization
395
+ // / - \ref ait#finalize(), for post-analysis cleanup.
396
+ // /
397
+ // For the <!-- --> trick above, see
398
+ // https://stackoverflow.com/questions/46744573/
358
399
template <typename domainT>
359
400
class ait :public ai_baset
360
401
{
@@ -366,6 +407,7 @@ class ait:public ai_baset
366
407
367
408
typedef goto_programt::const_targett locationt;
368
409
410
+ // / Find the analysis result for a given location.
369
411
domainT &operator [](locationt l)
370
412
{
371
413
typename state_mapt::iterator it=state_map.find (l);
@@ -375,6 +417,7 @@ class ait:public ai_baset
375
417
return it->second ;
376
418
}
377
419
420
+ // / Find the analysis result for a given location.
378
421
const domainT &operator [](locationt l) const
379
422
{
380
423
typename state_mapt::const_iterator it=state_map.find (l);
@@ -384,6 +427,7 @@ class ait:public ai_baset
384
427
return it->second ;
385
428
}
386
429
430
+ // / Used internally by the analysis.
387
431
std::unique_ptr<statet> abstract_state_before (locationt t) const override
388
432
{
389
433
typename state_mapt::const_iterator it = state_map.find (t);
@@ -397,25 +441,31 @@ class ait:public ai_baset
397
441
return util_make_unique<domainT>(it->second );
398
442
}
399
443
444
+ // / Remove all analysis results.
400
445
void clear () override
401
446
{
402
447
state_map.clear ();
403
448
ai_baset::clear ();
404
449
}
405
450
406
451
protected:
452
+ // / Map from locations to domain elements, for the results of a static
453
+ // / analysis.
407
454
typedef std::
408
455
unordered_map<locationt, domainT, const_target_hash, pointee_address_equalt>
409
456
state_mapt;
410
457
state_mapt state_map;
411
458
412
- // this one creates states, if need be
459
+ // / Look up the analysis state for a given location, instantiating a new state
460
+ // / if required. Used internally by the analysis.
413
461
virtual statet &get_state (locationt l) override
414
462
{
415
463
return state_map[l]; // calls default constructor
416
464
}
417
465
418
- // this one just finds states
466
+ // / Look up the analysis state for a given location, throwing an exception if
467
+ // / no state is known.
468
+ // / Used internally by the analysis.
419
469
const statet &find_state (locationt l) const override
420
470
{
421
471
typename state_mapt::const_iterator it=state_map.find (l);
@@ -425,18 +475,24 @@ class ait:public ai_baset
425
475
return it->second ;
426
476
}
427
477
478
+ // / Merge the state \p src, flowing from location \p from to
479
+ // / location \p to, into the state currently stored for location \p to.
428
480
bool merge (const statet &src, locationt from, locationt to) override
429
481
{
430
482
statet &dest=get_state (to);
431
483
return static_cast <domainT &>(dest).merge (
432
484
static_cast <const domainT &>(src), from, to);
433
485
}
434
486
487
+ // / Make a copy of \p s.
435
488
std::unique_ptr<statet> make_temporary_state (const statet &s) override
436
489
{
437
490
return util_make_unique<domainT>(static_cast <const domainT &>(s));
438
491
}
439
492
493
+ // / Internal: implementation of the fixed point function using
494
+ // / \ref ai_baset#sequential_fixedpoint(const goto_functionst&,
495
+ // / const namespacet&).
440
496
void fixedpoint (
441
497
const goto_functionst &goto_functions,
442
498
const namespacet &ns) override
@@ -457,6 +513,12 @@ class ait:public ai_baset
457
513
}
458
514
};
459
515
516
+ // / Base class for concurrency-aware static analyses. See
517
+ // / \ref ait for details.
518
+ // / The only difference is that after the sequential fixed point construction,
519
+ // / as done by \ref ait, another step is added to account for
520
+ // / concurrently-executed instructions.
521
+ // / TODO: Somebody who truly understands this algorithm should document it!
460
522
template <typename domainT>
461
523
class concurrency_aware_ait :public ait <domainT>
462
524
{
0 commit comments