CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
rewrite_union.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Symbolic Execution of ANSI-C
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "rewrite_union.h"
13
14#include <util/arith_tools.h>
15#include <util/byte_operators.h>
16#include <util/c_types.h>
17#include <util/pointer_expr.h>
19#include <util/std_code.h>
20
22
23static bool have_to_rewrite_union(const exprt &expr)
24{
25 if(expr.id()==ID_member)
26 {
27 const exprt &op=to_member_expr(expr).struct_op();
28
29 if(op.type().id() == ID_union_tag || op.type().id() == ID_union)
30 return true;
31 }
32 else if(expr.id()==ID_union)
33 return true;
34
35 for(const auto &op : expr.operands())
36 {
38 return true;
39 }
40
41 return false;
42}
43
44// inside an address of (&x), unions can simply
45// be type casts and don't have to be re-written!
47{
48 if(!have_to_rewrite_union(expr))
49 return;
50
51 if(expr.id()==ID_index)
52 {
54 rewrite_union(to_index_expr(expr).index());
55 }
56 else if(expr.id()==ID_member)
58 else if(expr.id()==ID_symbol)
59 {
60 // done!
61 }
62 else if(expr.id()==ID_dereference)
63 rewrite_union(to_dereference_expr(expr).pointer());
64}
65
69{
70 if(expr.id()==ID_address_of)
71 {
73 return;
74 }
75
76 if(!have_to_rewrite_union(expr))
77 return;
78
79 Forall_operands(it, expr)
80 rewrite_union(*it);
81
82 if(expr.id()==ID_member)
83 {
84 const exprt &op=to_member_expr(expr).struct_op();
85
86 if(op.type().id() == ID_union_tag || op.type().id() == ID_union)
87 {
88 exprt offset = from_integer(0, c_index_type());
89 expr = make_byte_extract(op, offset, expr.type());
90 }
91 }
92 else if(expr.id()==ID_union)
93 {
95 exprt offset = from_integer(0, c_index_type());
97 expr = make_byte_update(nondet, offset, union_expr.op());
98 }
99}
100
102{
103 for(auto &instruction : goto_function.body.instructions)
104 {
105 rewrite_union(instruction.code_nonconst());
106
107 if(instruction.has_condition())
108 rewrite_union(instruction.condition_nonconst());
109 }
110}
111
112void rewrite_union(goto_functionst &goto_functions)
113{
114 for(auto &gf_entry : goto_functions.function_map)
115 rewrite_union(gf_entry.second);
116}
117
118void rewrite_union(goto_modelt &goto_model)
119{
120 rewrite_union(goto_model.goto_functions);
121}
122
128static bool restore_union_rec(exprt &expr, const namespacet &ns)
129{
130 bool unmodified = true;
131
132 Forall_operands(it, expr)
133 unmodified &= restore_union_rec(*it, ns);
134
135 if(
138 {
140 if(be.op().type().id() == ID_union || be.op().type().id() == ID_union_tag)
141 {
142 const union_typet &union_type =
143 be.op().type().id() == ID_union_tag
144 ? ns.follow_tag(to_union_tag_type(be.op().type()))
145 : to_union_type(be.op().type());
146
147 for(const auto &comp : union_type.components())
148 {
149 if(be.offset().is_zero() && be.type() == comp.type())
150 {
151 expr = member_exprt{be.op(), comp.get_name(), be.type()};
152 return false;
153 }
154 else if(
155 comp.type().id() == ID_array || comp.type().id() == ID_struct ||
156 comp.type().id() == ID_struct_tag)
157 {
158 std::optional<exprt> result = get_subexpression_at_offset(
159 member_exprt{be.op(), comp.get_name(), comp.type()},
160 be.offset(),
161 be.type(),
162 ns);
163 if(result.has_value())
164 {
165 expr = *result;
166 return false;
167 }
168 }
169 }
170 }
171 }
172
173 return unmodified;
174}
175
180void restore_union(exprt &expr, const namespacet &ns)
181{
182 exprt tmp = expr;
183
184 if(!restore_union_rec(tmp, ns))
185 expr.swap(tmp);
186}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
byte_update_exprt make_byte_update(const exprt &_op, const exprt &_offset, const exprt &_value)
Construct a byte_update_exprt with endianness and byte width matching the current configuration.
byte_extract_exprt make_byte_extract(const exprt &_op, const exprt &_offset, const typet &_type)
Construct a byte_extract_exprt with endianness and byte width matching the current configuration.
Expression classes for byte-level operators.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
bitvector_typet c_index_type()
Definition c_types.cpp:16
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Expression of type type extracted from some object op starting at position offset (given in number of...
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
const source_locationt & source_location() const
Definition expr.h:231
A collection of goto functions.
function_mapt function_map
::goto_functiont goto_functiont
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
Extract member of struct or union.
Definition std_expr.h:2971
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
A side_effect_exprt that returns a non-deterministically chosen value.
Definition std_code.h:1520
Union constructor from single element.
Definition std_expr.h:1770
The union type.
Definition c_types.h:147
#define Forall_operands(it, expr)
Definition expr.h:27
Symbol Table + CFG.
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
std::optional< exprt > get_subexpression_at_offset(const exprt &expr, const mp_integer &offset_bytes, const typet &target_type_raw, const namespacet &ns)
Pointer Logic.
void restore_union(exprt &expr, const namespacet &ns)
Undo the union access -> byte_extract replacement that rewrite_union did for the purpose of displayin...
static bool have_to_rewrite_union(const exprt &expr)
void rewrite_union_address_of(exprt &expr)
void rewrite_union(exprt &expr)
We rewrite u.c for unions u into byte_extract(u, 0), and { .c = v } into byte_update(NIL,...
static bool restore_union_rec(exprt &expr, const namespacet &ns)
Undo the union access -> byte_extract replacement that rewrite_union did for the purpose of displayin...
Symbolic Execution.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1816