CBMC
abstract_object.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3  Module: analyses variable-sensitivity
4 
5  Author: Thomas Kiley, thomas.kiley@diffblue.com
6 
7 \*******************************************************************/
8 
25 
26 #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H
27 #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H
28 
29 #include <memory>
30 #include <set>
31 #include <stack>
32 
34 #include <util/sharing_map.h>
35 
37 class namespacet;
39 enum class widen_modet;
40 
41 #define CLONE \
42  internal_abstract_object_pointert mutable_clone() const override \
43  { \
44  typedef std::remove_const< \
45  std::remove_reference<decltype(*this)>::type>::type current_typet; \
46  return internal_abstract_object_pointert(new current_typet(*this)); \
47  }
48 
65 
66 template <class T>
67 using sharing_ptrt = std::shared_ptr<const T>; // NOLINT(*)
68 
70 using abstract_object_visitedt = std::set<abstract_object_pointert>;
71 
72 class abstract_objectt : public std::enable_shared_from_this<abstract_objectt>
73 {
74 public:
81  abstract_objectt(const typet &type, bool top, bool bottom);
82 
91  const exprt &expr,
92  const abstract_environmentt &environment,
93  const namespacet &ns);
94 
96  {
97  }
98 
102  virtual const typet &type() const;
103 
108  virtual bool is_top() const;
109 
113  virtual bool is_bottom() const;
114 
118  virtual bool verify() const;
119 
120  virtual void get_statistics(
121  abstract_object_statisticst &statistics,
122  abstract_object_visitedt &visited,
123  const abstract_environmentt &env,
124  const namespacet &ns) const;
125 
142  const exprt &expr,
143  const std::vector<abstract_object_pointert> &operands,
144  const abstract_environmentt &environment,
145  const namespacet &ns) const;
146 
156  virtual exprt to_constant() const;
157 
167  exprt to_predicate(const exprt &name) const;
168 
186  abstract_environmentt &environment,
187  const namespacet &ns,
188  const std::stack<exprt> &stack,
189  const exprt &specifier,
190  const abstract_object_pointert &value,
191  bool merging_write) const;
192 
199  virtual void output(
200  std::ostream &out,
201  const class ai_baset &ai,
202  const namespacet &ns) const;
203 
207 
208  static void dump_map(std::ostream out, const shared_mapt &m);
216  static void
217  dump_map_diff(std::ostream out, const shared_mapt &m1, const shared_mapt &m2);
218 
227  virtual bool has_been_modified(const abstract_object_pointert &before) const
228  {
232  return this != before.get();
233  };
234 
247  {
249  bool modified;
250  };
251  static combine_result merge(
252  const abstract_object_pointert &op1,
253  const abstract_object_pointert &op2,
254  const locationt &merge_location,
255  const widen_modet &widen_mode);
256  static combine_result merge(
257  const abstract_object_pointert &op1,
258  const abstract_object_pointert &op2,
259  const widen_modet &widen_mode);
260 
268  static combine_result meet(
269  const abstract_object_pointert &op1,
270  const abstract_object_pointert &op2);
271 
278  meet(const abstract_object_pointert &other) const;
279 
289  write_location_context(const locationt &location) const;
290 
300  merge_location_context(const locationt &location) const;
301 
302  // Const versions must perform copy-on-write
304  {
305  if(is_top())
306  return shared_from_this();
307 
309  clone->set_top();
310  return clone;
311  }
312 
314  {
315  if(!is_top())
316  return shared_from_this();
317 
319  clone->set_not_top();
320  return clone;
321  }
322 
324 
330  {
332  visit(const abstract_object_pointert &element) const = 0;
333  };
334 
348  {
349  return shared_from_this();
350  }
351 
352  virtual size_t internal_hash() const
353  {
354  return std::hash<abstract_object_pointert>{}(shared_from_this());
355  }
356 
357  virtual bool internal_equality(const abstract_object_pointert &other) const
358  {
359  return shared_from_this() == other;
360  }
361 
365  virtual exprt to_predicate_internal(const exprt &name) const;
366 
367 private:
370  bool bottom;
371  bool top;
372 
373  // Hooks to allow a sub-class to perform its own operations on
374  // setting/clearing top
375  virtual void set_top_internal()
376  {
377  }
378  virtual void set_not_top_internal()
379  {
380  }
381 
396 
403 
404 protected:
405  template <class T>
406  using internal_sharing_ptrt = std::shared_ptr<T>;
407 
410 
411  // Macro is not used as this does not override
413  {
415  }
416 
425 
433  bool should_use_base_merge(const abstract_object_pointert &other) const;
434 
443  const abstract_object_pointert &other,
444  const widen_modet &widen_mode) const;
445 
452 
457  bool should_use_base_meet(const abstract_object_pointert &other) const;
458 
459  // The one exception is merge in descendant classes, which needs this
460  void set_top()
461  {
462  top = true;
463  this->set_top_internal();
464  }
465  void set_not_top()
466  {
467  top = false;
468  this->set_not_top_internal();
469  }
471  {
472  bottom = false;
473  }
474 };
475 
477 {
479  typedef std::size_t result_typet;
480  result_typet operator()(argument_typet const &s) const noexcept
481  {
482  return s->internal_hash();
483  }
484 };
485 
487 {
489  typedef std::size_t result_typet;
490  bool operator()(argument_typet const &left, argument_typet const &right) const
491  noexcept
492  {
493  return left->internal_equality(right);
494  }
495 };
496 
497 #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H
std::shared_ptr< const T > sharing_ptrt
Merge is designed to allow different abstractions to be merged gracefully.
std::set< abstract_object_pointert > abstract_object_visitedt
sharing_ptrt< class abstract_objectt > abstract_object_pointert
virtual bool internal_equality(const abstract_object_pointert &other) const
virtual exprt to_constant() const
Converts to a constant expression if possible.
virtual bool is_top() const
Find out if the abstract object is top.
static void dump_map(std::ostream out, const shared_mapt &m)
virtual bool verify() const
Verify the internal structure of an abstract_object is correct.
virtual abstract_object_pointert write(abstract_environmentt &environment, const namespacet &ns, const std::stack< exprt > &stack, const exprt &specifier, const abstract_object_pointert &value, bool merging_write) const
A helper function to evaluate writing to a component of an abstract object.
virtual bool is_bottom() const
Find out if the abstract object is bottom.
virtual internal_abstract_object_pointert mutable_clone() const
virtual abstract_object_pointert write_location_context(const locationt &location) const
Update the write location context for an abstract object.
virtual abstract_object_pointert expression_transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns) const
Interface for transforms.
virtual void set_not_top_internal()
virtual exprt to_predicate_internal(const exprt &name) const
to_predicate implementation - derived classes will override
goto_programt::const_targett locationt
bool should_use_base_meet(const abstract_object_pointert &other) const
Helper function to decide if base meet implementation should be used.
abstract_objectt(const typet &type, bool top, bool bottom)
Start the abstract object at either top or bottom or neither Asserts if both top and bottom are true.
virtual void set_top_internal()
virtual abstract_object_pointert abstract_object_meet_internal(const abstract_object_pointert &other) const
Helper function for base meet, in case additional work was needed.
exprt to_predicate(const exprt &name) const
Converts to an invariant expression.
static void dump_map_diff(std::ostream out, const shared_mapt &m1, const shared_mapt &m2)
Dump all elements in m1 that are different or missing in m2.
std::shared_ptr< T > internal_sharing_ptrt
abstract_object_pointert make_top() const
virtual size_t internal_hash() const
virtual abstract_object_pointert visit_sub_elements(const abstract_object_visitort &visitor) const
Apply a visitor operation to all sub elements of this abstract_object.
abstract_object_pointert abstract_object_meet(const abstract_object_pointert &other) const
Helper function for base meet.
abstract_object_pointert clear_top() const
static combine_result merge(const abstract_object_pointert &op1, const abstract_object_pointert &op2, const locationt &merge_location, const widen_modet &widen_mode)
bool should_use_base_merge(const abstract_object_pointert &other) const
To detect the cases where the base merge is sufficient to do a merge We can't do if this->is_bottom()...
virtual void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) const
Print the value of the abstract object.
static combine_result meet(const abstract_object_pointert &op1, const abstract_object_pointert &op2)
Interface method for the meet operation.
virtual abstract_object_pointert merge_location_context(const locationt &location) const
Update the merge location context for an abstract object.
abstract_object_pointert abstract_object_merge(const abstract_object_pointert &other) const
Create a new abstract object that is the result of the merge, unless the object would be unchanged,...
virtual abstract_object_pointert abstract_object_merge_internal(const abstract_object_pointert &other) const
Helper function for abstract_objectt::abstract_object_merge to perform any additional actions after t...
internal_sharing_ptrt< class abstract_objectt > internal_abstract_object_pointert
sharing_mapt< irep_idt, abstract_object_pointert, false, irep_id_hash > shared_mapt
virtual abstract_object_pointert unwrap_context() const
typet t
To enforce copy-on-write these are private and have read-only accessors.
virtual void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, const abstract_environmentt &env, const namespacet &ns) const
virtual ~abstract_objectt()
virtual bool has_been_modified(const abstract_object_pointert &before) const
Determine whether 'this' abstract_object has been modified in comparison to a previous 'before' state...
virtual const typet & type() const
Get the real type of the variable this abstract object is representing.
This is the basic interface of the abstract interpreter with default implementations of the core func...
Definition: ai.h:117
Base class for all expressions.
Definition: expr.h:56
instructionst::const_iterator const_targett
Definition: goto_program.h:615
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
The type of an expression, extends irept.
Definition: type.h:29
Concrete Goto Program.
Sharing map.
abstract_object_pointert argument_typet
std::size_t result_typet
bool operator()(argument_typet const &left, argument_typet const &right) const noexcept
abstract_object_pointert argument_typet
std::size_t result_typet
result_typet operator()(argument_typet const &s) const noexcept
Pure virtual interface required of a client that can apply a copy-on-write operation to a given abstr...
virtual abstract_object_pointert visit(const abstract_object_pointert &element) const =0
Clones the first parameter and merges it with the second.
abstract_object_pointert object