CBMC
report_traces.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Report Traces
4 
5 Author: Daniel Kroening, dkr@amazon.com
6 
7 \*******************************************************************/
8 
11 
12 #include "report_traces.h"
13 
14 #include <util/console.h>
15 #include <util/format_expr.h>
16 #include <util/pointer_expr.h>
17 
18 #include <iomanip>
19 
20 std::optional<exprt> address_to_lvalue(exprt src)
21 {
22  if(src.id() == ID_object_address)
23  return to_object_address_expr(src).object_expr();
24  else if(src.id() == ID_field_address)
25  {
26  const auto &field_address_expr = to_field_address_expr(src);
27  auto compound_opt = address_to_lvalue(field_address_expr.base());
28  if(compound_opt.has_value())
29  return member_exprt(
30  *compound_opt,
31  field_address_expr.component_name(),
32  field_address_expr.field_type());
33  else
34  return {};
35  }
36  else if(src.id() == ID_element_address)
37  {
38  const auto &element_address_expr = to_element_address_expr(src);
39  auto array_opt = address_to_lvalue(element_address_expr.base());
40  if(array_opt.has_value())
41  return index_exprt(
42  *array_opt,
43  element_address_expr.index(),
44  element_address_expr.element_type());
45  else
46  return {};
47  }
48  else if(src.id() == ID_annotated_pointer_constant)
49  {
50  const auto &pointer =
52  if(
53  pointer.id() == ID_address_of &&
54  to_address_of_expr(pointer).object().id() == ID_symbol)
55  return to_address_of_expr(pointer).object();
56  else
57  return {};
58  }
59  else
60  return {};
61 }
62 
64 {
65  auto src_lvalue_opt = address_to_lvalue(src);
66  if(src_lvalue_opt.has_value())
67  return address_of_exprt(*src_lvalue_opt);
68  else
69  return src;
70 }
71 
73  const std::vector<framet> &frames,
74  const propertyt &property,
75  bool verbose,
76  const namespacet &ns)
77 {
78  irep_idt function_id, file;
79 
80  for(auto &step : property.trace)
81  {
82  const auto &frame = frames[step.frame.index];
83 
84  if(
85  frame.source_location.get_function() != function_id ||
86  frame.source_location.get_file() != file)
87  {
88  consolet::out() << consolet::faint << frame.source_location.get_file();
89  if(frame.source_location.get_function() != "")
90  consolet::out() << " function " << frame.source_location.get_function();
91  consolet::out() << consolet::reset << '\n';
92  file = frame.source_location.get_file();
93  function_id = frame.source_location.get_function();
94  }
95 
96  consolet::out() << consolet::faint << std::setw(4)
97  << frame.source_location.get_line() << consolet::reset
98  << ' ';
99 
100  if(step.updates.empty())
101  {
102  if(!verbose)
103  {
104  consolet::out() << "(no assignment)\n";
105  }
106  else
107  {
108  bool first = true;
109  for(auto &implication : frame.implications)
110  {
111  if(first)
112  first = false;
113  else
114  {
115  consolet::out() << std::setw(4) << ' ';
116  }
117  consolet::out() << "constraint: " << format(implication.as_expr())
118  << '\n';
119  }
120  }
121  }
122  else
123  {
124  bool first = true;
125  for(auto &update : step.updates)
126  {
127  if(first)
128  first = false;
129  else
130  {
131  consolet::out() << std::setw(4) << ' ';
132  }
133 
134  // use an l-value expression for better readability, if possible
135  auto lhs_lvalue_opt = address_to_lvalue(update.address);
136  if(lhs_lvalue_opt.has_value())
137  consolet::out() << format(*lhs_lvalue_opt);
138  else
139  consolet::out() << '[' << format(update.address) << ']';
140 
141  // use address_of for better readability
142  auto value_with_address_of = use_address_of(update.value);
143 
144  consolet::out() << " := " << format(value_with_address_of);
145  consolet::out() << '\n';
146  }
147  }
148  }
149 }
150 
152  const std::vector<framet> &frames,
153  const std::vector<propertyt> &properties,
154  bool verbose,
155  const namespacet &ns)
156 {
157  for(auto &property : properties)
158  {
159  if(property.status == propertyt::REFUTED)
160  {
161  consolet::out() << '\n'
162  << "Trace for " << consolet::bold
163  << property.property_id() << consolet::reset << ':'
164  << '\n';
165 
166  show_trace(frames, property, verbose, ns);
167  }
168  }
169 }
Operator to return the address of an object.
Definition: pointer_expr.h:540
exprt & object()
Definition: pointer_expr.h:549
static std::ostream & reset(std::ostream &)
Definition: console.cpp:176
static std::ostream & faint(std::ostream &)
Definition: console.cpp:160
static std::ostream & bold(std::ostream &)
Definition: console.cpp:152
static std::ostream & out()
Definition: console.h:55
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:56
Array index operator.
Definition: std_expr.h:1465
const irep_idt & id() const
Definition: irep.h:384
Extract member of struct or union.
Definition: std_expr.h:2841
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
symbol_exprt object_expr() const
tracet trace
Definition: solver_types.h:158
Console.
static format_containert< T > format(const T &o)
Definition: format.h:37
static exprt implication(exprt lhs, exprt rhs)
API to expression classes for Pointers.
const annotated_pointer_constant_exprt & to_annotated_pointer_constant_expr(const exprt &expr)
Cast an exprt to an annotated_pointer_constant_exprt.
const field_address_exprt & to_field_address_expr(const exprt &expr)
Cast an exprt to an field_address_exprt.
Definition: pointer_expr.h:727
const object_address_exprt & to_object_address_expr(const exprt &expr)
Cast an exprt to an object_address_exprt.
Definition: pointer_expr.h:643
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
const element_address_exprt & to_element_address_expr(const exprt &expr)
Cast an exprt to an element_address_exprt.
Definition: pointer_expr.h:814
void report_traces(const std::vector< framet > &frames, const std::vector< propertyt > &properties, bool verbose, const namespacet &ns)
void show_trace(const std::vector< framet > &frames, const propertyt &property, bool verbose, const namespacet &ns)
static exprt use_address_of(exprt src)
std::optional< exprt > address_to_lvalue(exprt src)
Report Traces.