CBMC
postcondition.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Symbolic Execution
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "postcondition.h"
13 
14 #include <util/find_symbols.h>
15 #include <util/pointer_expr.h>
16 #include <util/std_expr.h>
17 
19 
20 #include "renaming_level.h"
21 #include "symex_target_equation.h"
22 
24 {
25 public:
27  const namespacet &_ns,
28  const value_sett &_value_set,
29  const SSA_stept &_SSA_step,
30  const goto_symex_statet &_s)
31  : ns(_ns), value_set(_value_set), SSA_step(_SSA_step), s(_s)
32  {
33  }
34 
35 protected:
36  const namespacet &ns;
40 
41 public:
42  void compute(exprt &dest);
43 
44 protected:
45  void strengthen(exprt &dest);
46  void weaken(exprt &dest);
47  bool is_used_address_of(const exprt &expr, const irep_idt &identifier);
48  bool is_used(const exprt &expr, const irep_idt &identifier);
49 };
50 
52  const namespacet &ns,
53  const value_sett &value_set,
54  const symex_target_equationt &equation,
55  const goto_symex_statet &s,
56  exprt &dest)
57 {
58  for(symex_target_equationt::SSA_stepst::const_iterator
59  it=equation.SSA_steps.begin();
60  it!=equation.SSA_steps.end();
61  it++)
62  {
63  postconditiont postcondition(ns, value_set, *it, s);
64  postcondition.compute(dest);
65  if(dest.is_false())
66  return;
67  }
68 }
69 
71  const exprt &expr,
72  const irep_idt &identifier)
73 {
74  if(expr.id()==ID_symbol)
75  {
76  // leave alone
77  }
78  else if(expr.id()==ID_index)
79  {
80  return is_used_address_of(to_index_expr(expr).array(), identifier) ||
81  is_used(to_index_expr(expr).index(), identifier);
82  }
83  else if(expr.id()==ID_member)
84  {
85  return is_used_address_of(to_member_expr(expr).compound(), identifier);
86  }
87  else if(expr.id()==ID_dereference)
88  {
89  return is_used(to_dereference_expr(expr).pointer(), identifier);
90  }
91 
92  return false;
93 }
94 
96 {
97  // weaken due to assignment
98  weaken(dest);
99 
100  // strengthen due to assignment
101  strengthen(dest);
102 }
103 
105 {
106  if(dest.id()==ID_and &&
107  dest.type()==bool_typet()) // this distributes over "and"
108  {
109  Forall_operands(it, dest)
110  weaken(*it);
111 
112  return;
113  }
114 
115  // we are lazy:
116  // if lhs is mentioned in dest, we use "true".
117 
118  const irep_idt &lhs_identifier=SSA_step.ssa_lhs.get_object_name();
119 
120  if(is_used(dest, lhs_identifier))
121  dest=true_exprt();
122 
123  // otherwise, no weakening needed
124 }
125 
127 {
128  const irep_idt &lhs_identifier=SSA_step.ssa_lhs.get_object_name();
129 
130  if(!is_used(SSA_step.ssa_rhs, lhs_identifier))
131  {
132  // we don't do arrays or structs
133  if(SSA_step.ssa_lhs.type().id()==ID_array ||
134  SSA_step.ssa_lhs.type().id()==ID_struct)
135  return;
136 
137  exprt equality =
139 
140  if(dest.is_true())
141  dest.swap(equality);
142  else
143  dest=and_exprt(dest, equality);
144  }
145 }
146 
148  const exprt &expr,
149  const irep_idt &identifier)
150 {
151  if(expr.id()==ID_address_of)
152  {
153  return is_used_address_of(to_address_of_expr(expr).object(), identifier);
154  }
155  else if(is_ssa_expr(expr))
156  {
157  return to_ssa_expr(expr).get_object_name()==identifier;
158  }
159  else if(expr.id()==ID_symbol)
160  {
161  return to_symbol_expr(expr).get_identifier() == identifier;
162  }
163  else if(expr.id()==ID_dereference)
164  {
165  // aliasing may happen here
166  for(const exprt &e :
167  value_set.get_value_set(to_dereference_expr(expr).pointer(), ns))
168  {
169  if(has_symbol_expr(get_original_name(e), identifier, false))
170  return true;
171  }
172 
173  return false;
174  }
175  else
176  {
177  for(const auto &op : expr.operands())
178  {
179  if(is_used(op, identifier))
180  return true;
181  }
182  }
183 
184  return false;
185 }
Single SSA step in the equation.
Definition: ssa_step.h:47
exprt ssa_rhs
Definition: ssa_step.h:141
ssa_exprt ssa_lhs
Definition: ssa_step.h:139
Boolean AND.
Definition: std_expr.h:2120
The Boolean type.
Definition: std_types.h:36
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Equality.
Definition: std_expr.h:1361
Base class for all expressions.
Definition: expr.h:56
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:27
bool is_false() const
Return whether the expression is a constant representing false.
Definition: expr.cpp:34
typet & type()
Return the type of the expression.
Definition: expr.h:84
operandst & operands()
Definition: expr.h:94
Central data structure: state.
const irep_idt & id() const
Definition: irep.h:388
void swap(irept &irep)
Definition: irep.h:434
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
const SSA_stept & SSA_step
const namespacet & ns
bool is_used(const exprt &expr, const irep_idt &identifier)
void strengthen(exprt &dest)
const value_sett & value_set
const goto_symex_statet & s
void weaken(exprt &dest)
bool is_used_address_of(const exprt &expr, const irep_idt &identifier)
postconditiont(const namespacet &_ns, const value_sett &_value_set, const SSA_stept &_SSA_step, const goto_symex_statet &_s)
void compute(exprt &dest)
irep_idt get_object_name() const
const irep_idt & get_identifier() const
Definition: std_expr.h:160
Inheriting the interface of symex_targett this class represents the SSA form of the input program as ...
The Boolean constant true.
Definition: std_expr.h:3063
State type in value_set_domaint, used in value-set analysis and goto-symex.
Definition: value_set.h:44
std::vector< exprt > get_value_set(exprt expr, const namespacet &ns) const
Gets values pointed to by expr, including following dereference operators (i.e.
Definition: value_set.cpp:390
#define Forall_operands(it, expr)
Definition: expr.h:27
bool has_symbol_expr(const exprt &src, const irep_idt &identifier, bool include_bound_symbols)
Returns true if one of the symbol expressions in src has identifier identifier; if include_bound_symb...
API to expression classes for Pointers.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:890
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
void postcondition(const namespacet &ns, const value_sett &value_set, const symex_target_equationt &equation, const goto_symex_statet &s, exprt &dest)
Generate Equation using Symbolic Execution.
exprt get_original_name(exprt expr)
Undo all levels of renaming.
Renaming levels.
const ssa_exprt & to_ssa_expr(const exprt &expr)
Cast a generic exprt to an ssa_exprt.
Definition: ssa_expr.h:145
bool is_ssa_expr(const exprt &expr)
Definition: ssa_expr.h:125
API to expression classes.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2936
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1533
Generate Equation using Symbolic Execution.
Value Set.