CBMC
std_types.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Pre-defined types
4 
5 Author: Daniel Kroening, kroening@kroening.com
6  Maria Svorenova, maria.svorenova@diffblue.com
7 
8 \*******************************************************************/
9 
12 
13 #include "std_types.h"
14 
15 #include "arith_tools.h"
16 #include "c_types.h"
17 #include "namespace.h"
18 #include "std_expr.h"
19 
20 void array_typet::check(const typet &type, const validation_modet vm)
21 {
22  PRECONDITION(type.id() == ID_array);
24  const array_typet &array_type = static_cast<const array_typet &>(type);
25  if(array_type.size().is_nil())
26  {
27  DATA_CHECK(
28  vm,
29  array_type.size() == nil_exprt{},
30  "nil array size must be exactly nil");
31  }
32 }
33 
35 {
36  // For backwards compatibility, allow the case that the array type is
37  // not annotated with an index type.
38  const auto &annotated_type =
39  static_cast<const typet &>(find(ID_C_index_type));
40  if(annotated_type.is_nil())
41  return c_index_type();
42  else
43  return annotated_type;
44 }
45 
48  const irep_idt &component_name) const
49 {
50  std::size_t number=0;
51 
52  for(const auto &c : components())
53  {
54  if(c.get_name() == component_name)
55  return number;
56 
57  number++;
58  }
59 
61 }
62 
65  const irep_idt &component_name) const
66 {
67  for(const auto &c : components())
68  {
69  if(c.get_name() == component_name)
70  return c;
71  }
72 
73  return static_cast<const componentt &>(get_nil_irep());
74 }
75 
76 const typet &
77 struct_union_typet::component_type(const irep_idt &component_name) const
78 {
79  const auto &c = get_component(component_name);
80  CHECK_RETURN(c.is_not_nil());
81  return c.type();
82 }
83 
85 {
87 }
88 
90 {
92 }
93 
95  : exprt(ID_base, std::move(base))
96 {
97 }
98 
100 {
101  bases().push_back(baset(base));
102 }
103 
104 std::optional<struct_typet::baset>
106 {
107  for(const auto &b : bases())
108  {
109  if(to_struct_tag_type(b.type()).get_identifier() == id)
110  return b;
111  }
112  return {};
113 }
114 
119 bool struct_typet::is_prefix_of(const struct_typet &other) const
120 {
121  const componentst &ot_components=other.components();
122  const componentst &tt_components=components();
123 
124  if(ot_components.size()<
125  tt_components.size())
126  return false;
127 
128  componentst::const_iterator
129  ot_it=ot_components.begin();
130 
131  for(const auto &tt_c : tt_components)
132  {
133  if(ot_it->type() != tt_c.type() || ot_it->get_name() != tt_c.get_name())
134  {
135  return false; // they just don't match
136  }
137 
138  ot_it++;
139  }
140 
141  return true; // ok, *this is a prefix of ot
142 }
143 
145 bool is_reference(const typet &type)
146 {
147  return type.id()==ID_pointer &&
148  type.get_bool(ID_C_reference);
149 }
150 
152 bool is_rvalue_reference(const typet &type)
153 {
154  return type.id()==ID_pointer &&
155  type.get_bool(ID_C_rvalue_reference);
156 }
157 
158 std::size_t bitvector_typet::width() const
159 {
160  return get_size_t(ID_width);
161 }
162 
164 {
165  set_width(numeric_cast_v<std::size_t>(width));
166 }
167 
169 {
170  set(ID_from, integer2string(from));
171 }
172 
174 {
175  set(ID_to, integer2string(to));
176 }
177 
179 {
180  return string2integer(get_string(ID_from));
181 }
182 
184 {
185  return string2integer(get_string(ID_to));
186 }
187 
198  const typet &type,
199  const namespacet &ns)
200 {
201  // Helper function to avoid the code duplication in the branches
202  // below.
203  const auto has_constant_components = [&ns](const typet &subtype) -> bool {
204  if(subtype.id() == ID_struct || subtype.id() == ID_union)
205  {
206  const auto &struct_union_type = to_struct_union_type(subtype);
207  for(const auto &component : struct_union_type.components())
208  {
210  return true;
211  }
212  }
213  return false;
214  };
215 
216  // There are 4 possibilities the code below is handling.
217  // The possibilities are enumerated as comments, to show
218  // what each code is supposed to be handling. For more
219  // comprehensive test case for this, take a look at
220  // regression/cbmc/no_nondet_static/main.c
221 
222  // const int a;
223  if(type.get_bool(ID_C_constant))
224  return true;
225 
226  // This is a termination condition to break the recursion
227  // for recursive types such as the following:
228  // struct list { const int datum; struct list * next; };
229  // NOTE: the difference between this condition and the previous
230  // one is that this one always returns.
231  if(type.id() == ID_pointer)
232  return type.get_bool(ID_C_constant);
233 
234  // When we have a case like the following, we don't immediately
235  // see the struct t. Instead, we only get to see symbol t1, which
236  // we have to use the namespace to resolve to its definition:
237  // struct t { const int a; };
238  // struct t t1;
239  if(type.id() == ID_struct_tag)
240  {
241  const auto &resolved_type = ns.follow_tag(to_struct_tag_type(type));
242  return has_constant_components(resolved_type);
243  }
244  else if(type.id() == ID_union_tag)
245  {
246  const auto &resolved_type = ns.follow_tag(to_union_tag_type(type));
247  return has_constant_components(resolved_type);
248  }
249 
250  // In a case like this, where we see an array (b[3] here), we know that
251  // the array contains subtypes. We get the first one, and
252  // then resolve it to its definition through the usage of the namespace.
253  // struct contains_constant_pointer { int x; int * const p; };
254  // struct contains_constant_pointer b[3] = { {23, &y}, {23, &y}, {23, &y} };
255  if(type.has_subtype())
256  {
257  const auto &subtype = to_type_with_subtype(type).subtype();
258  return is_constant_or_has_constant_components(subtype, ns);
259  }
260 
261  return false;
262 }
263 
265  typet _index_type,
266  typet _element_type,
267  constant_exprt _size)
268  : type_with_subtypet(ID_vector, std::move(_element_type))
269 {
270  index_type_nonconst() = std::move(_index_type);
271  size() = std::move(_size);
272 }
273 
275 {
276  // For backwards compatibility, allow the case that the array type is
277  // not annotated with an index type.
278  const auto &annotated_type =
279  static_cast<const typet &>(find(ID_C_index_type));
280  if(annotated_type.is_nil())
281  return c_index_type();
282  else
283  return annotated_type;
284 }
285 
287 {
288  return static_cast<const constant_exprt &>(find(ID_size));
289 }
290 
292 {
293  return static_cast<constant_exprt &>(add(ID_size));
294 }
bitvector_typet c_index_type()
Definition: c_types.cpp:16
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
Arrays with given size.
Definition: std_types.h:807
static void check(const typet &type, const validation_modet vm=validation_modet::INVARIANT)
Definition: std_types.cpp:20
typet index_type() const
The type of the index expressions into any instance of this type.
Definition: std_types.cpp:34
const exprt & size() const
Definition: std_types.h:840
std::size_t width() const
Definition: std_types.cpp:158
A constant literal expression.
Definition: std_expr.h:3000
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
typet & type()
Return the type of the expression.
Definition: expr.h:84
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
std::size_t get_size_t(const irep_idt &name) const
Definition: irep.cpp:67
const irept & find(const irep_idt &name) const
Definition: irep.cpp:93
tree_implementationt baset
Definition: irep.h:366
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:412
const irep_idt & id() const
Definition: irep.h:388
const std::string & get_string(const irep_idt &name) const
Definition: irep.h:401
irept & add(const irep_idt &name)
Definition: irep.cpp:103
bool is_nil() const
Definition: irep.h:368
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
The NIL expression.
Definition: std_expr.h:3091
void set_to(const mp_integer &to)
Definition: std_types.cpp:173
void set_from(const mp_integer &_from)
Definition: std_types.cpp:168
mp_integer get_to() const
Definition: std_types.cpp:183
mp_integer get_from() const
Definition: std_types.cpp:178
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:493
struct_tag_typet & type()
Definition: std_types.cpp:84
Structure type, corresponds to C style structs.
Definition: std_types.h:231
std::optional< baset > get_base(const irep_idt &id) const
Return the base with the given name, if exists.
Definition: std_types.cpp:105
bool is_prefix_of(const struct_typet &other) const
Returns true if the struct is a prefix of other, i.e., if this struct has n components then the compo...
Definition: std_types.cpp:119
void add_base(const struct_tag_typet &base)
Add a base class/struct.
Definition: std_types.cpp:99
const basest & bases() const
Get the collection of base classes/structs.
Definition: std_types.h:262
const typet & component_type(const irep_idt &component_name) const
Definition: std_types.cpp:77
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
Definition: std_types.cpp:64
const componentst & components() const
Definition: std_types.h:147
std::size_t component_number(const irep_idt &component_name) const
Return the sequence number of the component with given name.
Definition: std_types.cpp:47
std::vector< componentt > componentst
Definition: std_types.h:140
const irep_idt & get_identifier() const
Definition: std_types.h:410
Type with a single subtype.
Definition: type.h:180
const typet & subtype() const
Definition: type.h:187
static void check(const typet &type, const validation_modet vm=validation_modet::INVARIANT)
Definition: type.h:199
The type of an expression, extends irept.
Definition: type.h:29
bool has_subtype() const
Definition: type.h:64
vector_typet(typet index_type, typet element_type, constant_exprt size)
Definition: std_types.cpp:264
typet & index_type_nonconst()
The type of any index expression into an instance of this type.
Definition: std_types.h:1071
const constant_exprt & size() const
Definition: std_types.cpp:286
typet index_type() const
The type of any index expression into an instance of this type.
Definition: std_types.cpp:274
const irept & get_nil_irep()
Definition: irep.cpp:19
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:54
const std::string integer2string(const mp_integer &n, unsigned base)
Definition: mp_arith.cpp:103
BigInt mp_integer
Definition: smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:97
API to expression classes.
bool is_constant_or_has_constant_components(const typet &type, const namespacet &ns)
Identify whether a given type is constant itself or contains constant components.
Definition: std_types.cpp:197
bool is_reference(const typet &type)
Returns true if the type is a reference.
Definition: std_types.cpp:145
bool is_rvalue_reference(const typet &type)
Returns if the type is an R value reference.
Definition: std_types.cpp:152
Pre-defined types.
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:208
#define DATA_CHECK(vm, condition, message)
This macro takes a condition which denotes a well-formedness criterion on goto programs,...
Definition: validate.h:22
validation_modet