CBMC
fatal_assertions.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Fatal Assertions
4 
5 Author: Daniel Kroening, dkr@amazon.com
6 
7 \*******************************************************************/
8 
11 
12 #include "fatal_assertions.h"
13 
14 #include <util/irep_hash.h>
15 
17 
18 #include <stack>
19 #include <unordered_set>
20 
22 {
23  using function_itt = goto_functionst::function_mapt::const_iterator;
25  function_itt __function_it,
27  : function_it(__function_it), target(__target)
28  {
29  }
32  bool operator==(const function_loc_pairt &other) const
33  {
34  return function_it->first == other.function_it->first &&
35  target == other.target;
36  }
37 };
38 
40 {
41  using function_itt = goto_functionst::function_mapt::const_iterator;
42  std::size_t operator()(const function_itt &function_it) const
43  {
44  return function_it->first.hash();
45  }
46 };
47 
49 {
50  std::size_t operator()(const function_loc_pairt &p) const
51  {
52  auto h1 = p.function_it->first.hash();
53  auto h2 = const_target_hash{}(p.target);
54  return hash_combine(h1, h2);
55  }
56 };
57 
58 using loc_sett =
59  std::unordered_set<function_loc_pairt, function_loc_pair_hasht>;
60 
61 static loc_sett
62 reachable_fixpoint(const loc_sett &locs, const goto_functionst &goto_functions)
63 {
64  // frontier set
65  std::stack<function_loc_pairt> working;
66 
67  for(auto loc : locs)
68  working.push(loc);
69 
70  loc_sett fixpoint;
71 
72  while(!working.empty())
73  {
74  auto loc = working.top();
75  working.pop();
76 
77  auto insertion_result = fixpoint.insert(loc);
78  if(!insertion_result.second)
79  continue; // seen already
80 
81  if(loc.target->is_function_call())
82  {
83  // get the callee
84  auto &function = loc.target->call_function();
85  if(function.id() == ID_symbol)
86  {
87  // add the callee to the working set
88  auto &function_identifier = to_symbol_expr(function).get_identifier();
89  auto function_iterator =
90  goto_functions.function_map.find(function_identifier);
91  CHECK_RETURN(function_iterator != goto_functions.function_map.end());
92  working.emplace(
93  function_iterator,
94  function_iterator->second.body.instructions.begin());
95  }
96 
97  // add the next location to the working set
98  working.emplace(loc.function_it, std::next(loc.target));
99  }
100  else
101  {
102  auto &body = loc.function_it->second.body;
103 
104  for(auto successor : body.get_successors(loc.target))
105  working.emplace(loc.function_it, successor);
106  }
107  }
108 
109  return fixpoint;
110 }
111 
115  propertiest &properties,
116  const goto_functionst &goto_functions)
117 {
118  // Iterate to find refuted fatal assertions. Anything reachalble
119  // from there is a 'fatal loc'.
120  loc_sett fatal_locs;
121 
122  for(auto function_it = goto_functions.function_map.begin();
123  function_it != goto_functions.function_map.end();
124  function_it++)
125  {
126  auto &body = function_it->second.body;
127  for(auto target = body.instructions.begin();
128  target != body.instructions.end();
129  target++)
130  {
131  if(target->is_assert() && target->source_location().property_fatal())
132  {
133  auto id = target->source_location().get_property_id();
134  auto property = properties.find(id);
135  CHECK_RETURN(property != properties.end());
136 
137  // Status?
138  if(property->second.status == property_statust::FAIL)
139  {
140  fatal_locs.emplace(function_it, target);
141  }
142  }
143  }
144  }
145 
146  // Saturate fixpoint.
147  auto fixpoint = reachable_fixpoint(fatal_locs, goto_functions);
148 
149  // Now mark PASS assertions as UNKNOWN.
150  for(auto &loc : fixpoint)
151  {
152  if(loc.target->is_assert())
153  {
154  auto id = loc.target->source_location().get_property_id();
155  auto property = properties.find(id);
156  CHECK_RETURN(property != properties.end());
157 
158  // Status?
159  if(property->second.status == property_statust::PASS)
160  {
161  property->second.status = property_statust::UNKNOWN;
162  }
163  }
164  }
165 }
166 
168  propertiest &properties,
169  const goto_functionst &goto_functions)
170 {
171  propagate_fatal_to_proven(properties, goto_functions);
172 }
A collection of goto functions.
function_mapt function_map
instructionst::const_iterator const_targett
Definition: goto_program.h:615
const irep_idt & get_identifier() const
Definition: std_expr.h:160
static loc_sett reachable_fixpoint(const loc_sett &locs, const goto_functionst &goto_functions)
std::unordered_set< function_loc_pairt, function_loc_pair_hasht > loc_sett
void propagate_fatal_assertions(propertiest &properties, const goto_functionst &goto_functions)
Proven assertions after refuted fatal assertions are marked as UNKNOWN.
void propagate_fatal_to_proven(propertiest &properties, const goto_functionst &goto_functions)
Proven assertions after refuted fatal assertions are marked as UNKNOWN.
Fatal Assertions.
Goto Programs with Functions.
irep hash functions
#define hash_combine(h1, h2)
Definition: irep_hash.h:121
@ UNKNOWN
The checker was unable to determine the status of the property.
@ PASS
The property was not violated.
@ FAIL
The property was violated.
std::map< irep_idt, property_infot > propertiest
A map of property IDs to property infos.
Definition: properties.h:76
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
std::size_t operator()(const function_itt &function_it) const
goto_functionst::function_mapt::const_iterator function_itt
std::size_t operator()(const function_loc_pairt &p) const
goto_programt::const_targett target
function_itt function_it
function_loc_pairt(function_itt __function_it, goto_programt::const_targett __target)
bool operator==(const function_loc_pairt &other) const
goto_functionst::function_mapt::const_iterator function_itt