CBMC
ai_history.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Abstract Interpretation
4 
5 Author: Martin Brain, martin.brain@cs.ox.ac.uk
6 
7 \*******************************************************************/
8 
11 
12 #ifndef CPROVER_ANALYSES_AI_HISTORY_H
13 #define CPROVER_ANALYSES_AI_HISTORY_H
14 
15 #include <memory>
16 
17 #include <util/json.h>
18 #include <util/xml.h>
19 
21 
34 
37 {
38 public:
40 
43  typedef std::shared_ptr<const ai_history_baset> trace_ptrt;
44 
45 protected:
50  {
51  }
52 
54  {
55  }
56 
57 public:
59  {
60  }
61 
73  {
74  bool operator()(const trace_ptrt &l, const trace_ptrt &r) const
75  {
76  return *l < *r;
77  }
78  };
79  typedef std::set<trace_ptrt, compare_historyt> trace_sett; // Order matters!
80 
81  enum class step_statust
82  {
83  NEW,
84  MERGED,
85  BLOCKED
86  };
87 
88  typedef std::pair<step_statust, trace_ptrt> step_returnt;
117  locationt to,
118  const trace_sett &others,
119  trace_ptrt caller_hist) const = 0;
120 
122 
124  virtual bool operator<(const ai_history_baset &op) const = 0;
125 
127  virtual bool operator==(const ai_history_baset &op) const = 0;
128 
131  virtual const locationt &current_location(void) const = 0;
132 
139  virtual bool should_widen(const ai_history_baset &other) const
140  {
141  return false;
142  }
143 
144  virtual void output(std::ostream &out) const
145  {
146  }
147  virtual jsont output_json(void) const;
148  virtual xmlt output_xml(void) const;
149 };
150 
155 {
156 protected:
157  // DATA_INVARIANT(current.is_dereferenceable(), "Must not be _::end()")
159 
160 public:
162  {
163  }
164 
166  : ai_history_baset(old), current(old.current)
167  {
168  }
169 
171  locationt to,
172  const trace_sett &others,
173  trace_ptrt caller_hist) const override
174  {
175  trace_ptrt next(new ahistoricalt(to));
176 
177  if(others.empty())
178  {
179  return std::make_pair(step_statust::NEW, next);
180  }
181  else
182  {
183  // Aggressively merge histories because they are indistinguishable
184  INVARIANT(others.size() == 1, "Only needs one history per location");
185 
186  const auto it = others.begin();
187  INVARIANT(
188  *(*(it)) == *next,
189  "The next location in history map must contain next history");
190 
191  return std::make_pair(step_statust::MERGED, *it);
192  }
193  }
194 
195  bool operator<(const ai_history_baset &op) const override
196  {
197  PRECONDITION(dynamic_cast<const ahistoricalt *>(&op) != nullptr);
198 
199  return this->current_location()->location_number <
200  op.current_location()->location_number;
201  }
202 
203  bool operator==(const ai_history_baset &op) const override
204  {
205  PRECONDITION(dynamic_cast<const ahistoricalt *>(&op) != nullptr);
206 
207  // It would be nice to:
208  // return this->current == op.current
209  // But they may point to different goto_programs,
210  // giving undefined behaviour in C++
211  // So (safe due to data invariant & uniqueness of location numbers) ...
212  return this->current_location()->location_number ==
213  op.current_location()->location_number;
214  }
215 
216  const locationt &current_location(void) const override
217  {
218  return current;
219  }
220 
221  // Use default widening
222  // without history there is no reason to say any location is better than
223  // another to widen.
224  bool should_widen(const ai_history_baset &other) const override
225  {
226  return ai_history_baset::should_widen(other);
227  }
228 
229  void output(std::ostream &out) const override
230  {
231  out << "ahistorical : location " << current_location()->location_number;
232  }
233 };
234 
235 
242 {
243 public:
246 
248  {
249  }
250 };
251 
253 template <typename traceT>
255 {
256 public:
258  {
259  ai_history_baset::trace_ptrt p(new traceT(l));
260  return p;
261  }
262 };
263 
264 #endif // CPROVER_ANALYSES_AI_HISTORY_H
The common case of history is to only care about where you are now, not how you got there!...
Definition: ai_history.h:155
ahistoricalt(locationt l)
Definition: ai_history.h:161
locationt current
Definition: ai_history.h:158
bool operator==(const ai_history_baset &op) const override
History objects should be comparable.
Definition: ai_history.h:203
bool operator<(const ai_history_baset &op) const override
The order for history_sett.
Definition: ai_history.h:195
ahistoricalt(const ahistoricalt &old)
Definition: ai_history.h:165
const locationt & current_location(void) const override
The current location in the history, used to compute the transformer POSTCONDITION(return value is de...
Definition: ai_history.h:216
step_returnt step(locationt to, const trace_sett &others, trace_ptrt caller_hist) const override
Step creates a new history by advancing the current one to location "to" It is given the set of all o...
Definition: ai_history.h:170
bool should_widen(const ai_history_baset &other) const override
Domains with a substantial height may need to widen when merging this method allows the history to pr...
Definition: ai_history.h:224
void output(std::ostream &out) const override
Definition: ai_history.h:229
A history object is an abstraction / representation of the control-flow part of a set of traces.
Definition: ai_history.h:37
std::shared_ptr< const ai_history_baset > trace_ptrt
History objects are intended to be immutable so they can be shared to reduce memory overhead.
Definition: ai_history.h:43
ai_history_baset(const ai_history_baset &)
Definition: ai_history.h:53
std::pair< step_statust, trace_ptrt > step_returnt
Definition: ai_history.h:88
virtual bool operator<(const ai_history_baset &op) const =0
The order for history_sett.
virtual void output(std::ostream &out) const
Definition: ai_history.h:144
static const trace_ptrt no_caller_history
Definition: ai_history.h:121
virtual step_returnt step(locationt to, const trace_sett &others, trace_ptrt caller_hist) const =0
Step creates a new history by advancing the current one to location "to" It is given the set of all o...
virtual bool should_widen(const ai_history_baset &other) const
Domains with a substantial height may need to widen when merging this method allows the history to pr...
Definition: ai_history.h:139
ai_history_baset(locationt)
Create a new history starting from a given location This is used to start the analysis from scratch P...
Definition: ai_history.h:49
virtual jsont output_json(void) const
Definition: ai_history.cpp:14
goto_programt::const_targett locationt
Definition: ai_history.h:39
virtual bool operator==(const ai_history_baset &op) const =0
History objects should be comparable.
virtual xmlt output_xml(void) const
Definition: ai_history.cpp:22
virtual const locationt & current_location(void) const =0
The current location in the history, used to compute the transformer POSTCONDITION(return value is de...
virtual ~ai_history_baset()
Definition: ai_history.h:58
std::set< trace_ptrt, compare_historyt > trace_sett
Definition: ai_history.h:79
As more detailed histories can get complex (for example, nested loops or deep, mutually recursive cal...
Definition: ai_history.h:242
virtual ai_history_baset::trace_ptrt epoch(ai_history_baset::locationt)=0
Creates a new history from the given starting point.
virtual ~ai_history_factory_baset()
Definition: ai_history.h:247
An easy factory implementation for histories that don't need parameters.
Definition: ai_history.h:255
ai_history_baset::trace_ptrt epoch(ai_history_baset::locationt l) override
Creates a new history from the given starting point.
Definition: ai_history.h:257
instructionst::const_iterator const_targett
Definition: goto_program.h:615
Definition: json.h:27
Definition: xml.h:21
Concrete Goto Program.
static int8_t r
Definition: irep_hash.h:60
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
In a number of places we need to work with sets of histories so that these (a) make use of the immuta...
Definition: ai_history.h:73
bool operator()(const trace_ptrt &l, const trace_ptrt &r) const
Definition: ai_history.h:74