CBMC
pointer_offset_size.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Pointer Logic
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "pointer_offset_size.h"
13 
14 #include "arith_tools.h"
15 #include "byte_operators.h"
16 #include "c_types.h"
17 #include "config.h"
18 #include "invariant.h"
19 #include "namespace.h"
20 #include "pointer_expr.h"
21 #include "simplify_expr.h"
22 #include "ssa_expr.h"
23 #include "std_expr.h"
24 
25 std::optional<mp_integer> member_offset(
26  const struct_typet &type,
27  const irep_idt &member,
28  const namespacet &ns)
29 {
30  mp_integer result = 0;
31  std::size_t bit_field_bits = 0;
32 
33  for(const auto &comp : type.components())
34  {
35  if(comp.get_name() == member)
36  return result;
37 
38  if(comp.type().id() == ID_c_bit_field)
39  {
40  const std::size_t w = to_c_bit_field_type(comp.type()).get_width();
41  bit_field_bits += w;
42  result += bit_field_bits / config.ansi_c.char_width;
43  bit_field_bits %= config.ansi_c.char_width;
44  }
45  else if(comp.is_boolean())
46  {
47  ++bit_field_bits;
48  result += bit_field_bits / config.ansi_c.char_width;
49  bit_field_bits %= config.ansi_c.char_width;
50  }
51  else
52  {
54  bit_field_bits == 0, "padding ensures offset at byte boundaries");
55  const auto sub_size = pointer_offset_size(comp.type(), ns);
56  if(!sub_size.has_value())
57  return {};
58  else
59  result += *sub_size;
60  }
61  }
62 
63  return result;
64 }
65 
66 std::optional<mp_integer> member_offset_bits(
67  const struct_typet &type,
68  const irep_idt &member,
69  const namespacet &ns)
70 {
71  mp_integer offset=0;
72  const struct_typet::componentst &components=type.components();
73 
74  for(const auto &comp : components)
75  {
76  if(comp.get_name()==member)
77  return offset;
78 
79  auto member_bits = pointer_offset_bits(comp.type(), ns);
80  if(!member_bits.has_value())
81  return {};
82 
83  offset += *member_bits;
84  }
85 
86  return {};
87 }
88 
90 std::optional<mp_integer>
91 pointer_offset_size(const typet &type, const namespacet &ns)
92 {
93  auto bits = pointer_offset_bits(type, ns);
94 
95  if(bits.has_value())
96  return (*bits + config.ansi_c.char_width - 1) / config.ansi_c.char_width;
97  else
98  return {};
99 }
100 
101 std::optional<mp_integer>
102 pointer_offset_bits(const typet &type, const namespacet &ns)
103 {
104  if(type.id()==ID_array)
105  {
106  auto sub = pointer_offset_bits(to_array_type(type).element_type(), ns);
107  if(!sub.has_value())
108  return {};
109 
110  // get size - we can only distinguish the elements if the size is constant
111  const auto size = numeric_cast<mp_integer>(to_array_type(type).size());
112  if(!size.has_value())
113  return {};
114 
115  return (*sub) * (*size);
116  }
117  else if(type.id()==ID_vector)
118  {
119  auto sub = pointer_offset_bits(to_vector_type(type).element_type(), ns);
120  if(!sub.has_value())
121  return {};
122 
123  // get size
124  const mp_integer size =
125  numeric_cast_v<mp_integer>(to_vector_type(type).size());
126 
127  return (*sub) * size;
128  }
129  else if(type.id()==ID_complex)
130  {
131  auto sub = pointer_offset_bits(to_complex_type(type).subtype(), ns);
132 
133  if(sub.has_value())
134  return (*sub) * 2;
135  else
136  return {};
137  }
138  else if(type.id()==ID_struct)
139  {
140  const struct_typet &struct_type=to_struct_type(type);
141  mp_integer result=0;
142 
143  for(const auto &c : struct_type.components())
144  {
145  const typet &subtype = c.type();
146  auto sub_size = pointer_offset_bits(subtype, ns);
147 
148  if(!sub_size.has_value())
149  return {};
150 
151  result += *sub_size;
152  }
153 
154  return result;
155  }
156  else if(type.id()==ID_union)
157  {
158  const union_typet &union_type=to_union_type(type);
159 
160  if(union_type.components().empty())
161  return mp_integer{0};
162 
163  const auto widest_member = union_type.find_widest_union_component(ns);
164 
165  if(widest_member.has_value())
166  return widest_member->second;
167  else
168  return {};
169  }
170  else if(type.id()==ID_signedbv ||
171  type.id()==ID_unsignedbv ||
172  type.id()==ID_fixedbv ||
173  type.id()==ID_floatbv ||
174  type.id()==ID_bv ||
175  type.id()==ID_c_bool ||
176  type.id()==ID_c_bit_field)
177  {
178  return mp_integer(to_bitvector_type(type).get_width());
179  }
180  else if(type.id()==ID_c_enum)
181  {
182  return mp_integer(
183  to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width());
184  }
185  else if(type.id()==ID_c_enum_tag)
186  {
187  return pointer_offset_bits(ns.follow_tag(to_c_enum_tag_type(type)), ns);
188  }
189  else if(type.id()==ID_bool)
190  {
191  return mp_integer(1);
192  }
193  else if(type.id()==ID_pointer)
194  {
195  // the following is an MS extension
196  if(type.get_bool(ID_C_ptr32))
197  return mp_integer(32);
198 
199  return mp_integer(to_bitvector_type(type).get_width());
200  }
201  else if(type.id() == ID_union_tag)
202  {
203  return pointer_offset_bits(ns.follow_tag(to_union_tag_type(type)), ns);
204  }
205  else if(type.id() == ID_struct_tag)
206  {
207  return pointer_offset_bits(ns.follow_tag(to_struct_tag_type(type)), ns);
208  }
209  else if(type.id()==ID_code)
210  {
211  return mp_integer(0);
212  }
213  else if(type.id()==ID_string)
214  {
215  return mp_integer(32);
216  }
217  else
218  return {};
219 }
220 
221 std::optional<exprt>
222 member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
223 {
224  // need to distinguish structs and unions
225  const typet &compound_type = member_expr.struct_op().type();
226  if(compound_type.id() == ID_struct || compound_type.id() == ID_struct_tag)
227  {
228  const struct_typet &struct_type =
229  compound_type.id() == ID_struct_tag
230  ? ns.follow_tag(to_struct_tag_type(compound_type))
231  : to_struct_type(compound_type);
232  return member_offset_expr(
233  struct_type, member_expr.get_component_name(), ns);
234  }
235  else if(compound_type.id() == ID_union || compound_type.id() == ID_union_tag)
236  return from_integer(0, size_type());
237  else
238  return {};
239 }
240 
241 std::optional<exprt> member_offset_expr(
242  const struct_typet &type,
243  const irep_idt &member,
244  const namespacet &ns)
245 {
246  PRECONDITION(size_type().get_width() != 0);
247  exprt result=from_integer(0, size_type());
248  std::size_t bit_field_bits=0;
249 
250  for(const auto &c : type.components())
251  {
252  if(c.get_name() == member)
253  break;
254 
255  if(c.type().id() == ID_c_bit_field)
256  {
257  std::size_t w = to_c_bit_field_type(c.type()).get_width();
258  bit_field_bits += w;
259  const std::size_t bytes = bit_field_bits / config.ansi_c.char_width;
260  bit_field_bits %= config.ansi_c.char_width;
261  if(bytes > 0)
262  result = plus_exprt(result, from_integer(bytes, result.type()));
263  }
264  else if(c.is_boolean())
265  {
266  ++bit_field_bits;
267  const std::size_t bytes = bit_field_bits / config.ansi_c.char_width;
268  bit_field_bits %= config.ansi_c.char_width;
269  if(bytes > 0)
270  result = plus_exprt(result, from_integer(bytes, result.type()));
271  }
272  else
273  {
275  bit_field_bits == 0, "padding ensures offset at byte boundaries");
276  const typet &subtype = c.type();
277  auto sub_size = size_of_expr(subtype, ns);
278  if(!sub_size.has_value())
279  return {}; // give up
280  result = plus_exprt(result, sub_size.value());
281  }
282  }
283 
284  return simplify_expr(std::move(result), ns);
285 }
286 
287 std::optional<exprt> size_of_expr(const typet &type, const namespacet &ns)
288 {
289  if(type.id()==ID_array)
290  {
291  const auto &array_type = to_array_type(type);
292 
293  // special-case arrays of bits
294  if(array_type.element_type().id() == ID_bool)
295  {
296  auto bits = pointer_offset_bits(array_type, ns);
297 
298  if(bits.has_value())
299  return from_integer(
301  size_type());
302  }
303 
304  auto sub = size_of_expr(array_type.element_type(), ns);
305  if(!sub.has_value())
306  return {};
307 
308  const exprt &size = array_type.size();
309 
310  if(size.is_nil())
311  return {};
312 
313  const auto size_casted =
314  typecast_exprt::conditional_cast(size, sub.value().type());
315 
316  return simplify_expr(mult_exprt{size_casted, sub.value()}, ns);
317  }
318  else if(type.id()==ID_vector)
319  {
320  const auto &vector_type = to_vector_type(type);
321 
322  // special-case vectors of bits
323  if(vector_type.element_type().id() == ID_bool)
324  {
325  auto bits = pointer_offset_bits(vector_type, ns);
326 
327  if(bits.has_value())
328  return from_integer(
330  size_type());
331  }
332 
333  auto sub = size_of_expr(vector_type.element_type(), ns);
334  if(!sub.has_value())
335  return {};
336 
337  const exprt &size = to_vector_type(type).size();
338 
339  if(size.is_nil())
340  return {};
341 
342  const auto size_casted =
343  typecast_exprt::conditional_cast(size, sub.value().type());
344 
345  return simplify_expr(mult_exprt{size_casted, sub.value()}, ns);
346  }
347  else if(type.id()==ID_complex)
348  {
349  auto sub = size_of_expr(to_complex_type(type).subtype(), ns);
350  if(!sub.has_value())
351  return {};
352 
353  exprt size = from_integer(2, sub.value().type());
354  return simplify_expr(mult_exprt{std::move(size), sub.value()}, ns);
355  }
356  else if(type.id()==ID_struct)
357  {
358  const struct_typet &struct_type=to_struct_type(type);
359 
360  exprt result=from_integer(0, size_type());
361  std::size_t bit_field_bits=0;
362 
363  for(const auto &c : struct_type.components())
364  {
365  if(c.type().id() == ID_c_bit_field)
366  {
367  std::size_t w = to_c_bit_field_type(c.type()).get_width();
368  bit_field_bits += w;
369  const std::size_t bytes = bit_field_bits / config.ansi_c.char_width;
370  bit_field_bits %= config.ansi_c.char_width;
371  if(bytes > 0)
372  result = plus_exprt(result, from_integer(bytes, result.type()));
373  }
374  else if(c.is_boolean())
375  {
376  ++bit_field_bits;
377  const std::size_t bytes = bit_field_bits / config.ansi_c.char_width;
378  bit_field_bits %= config.ansi_c.char_width;
379  if(bytes > 0)
380  result = plus_exprt(result, from_integer(bytes, result.type()));
381  }
382  else if(c.type().get_bool(ID_C_flexible_array_member))
383  {
384  // flexible array members do not change the sizeof result
385  continue;
386  }
387  else
388  {
390  bit_field_bits == 0, "padding ensures offset at byte boundaries");
391  const typet &subtype = c.type();
392  auto sub_size_opt = size_of_expr(subtype, ns);
393  if(!sub_size_opt.has_value())
394  return {};
395 
396  result = plus_exprt(result, sub_size_opt.value());
397  }
398  }
399 
400  return simplify_expr(std::move(result), ns);
401  }
402  else if(type.id()==ID_union)
403  {
404  const union_typet &union_type=to_union_type(type);
405 
406  mp_integer max_bytes=0;
407  exprt result=from_integer(0, size_type());
408 
409  // compute max
410 
411  for(const auto &c : union_type.components())
412  {
413  const typet &subtype = c.type();
414  exprt sub_size;
415 
416  auto sub_bits = pointer_offset_bits(subtype, ns);
417 
418  if(!sub_bits.has_value())
419  {
420  max_bytes=-1;
421 
422  auto sub_size_opt = size_of_expr(subtype, ns);
423  if(!sub_size_opt.has_value())
424  return {};
425  sub_size = sub_size_opt.value();
426  }
427  else
428  {
429  mp_integer sub_bytes =
430  (*sub_bits + config.ansi_c.char_width - 1) / config.ansi_c.char_width;
431 
432  if(max_bytes>=0)
433  {
434  if(max_bytes<sub_bytes)
435  {
436  max_bytes=sub_bytes;
437  result=from_integer(sub_bytes, size_type());
438  }
439 
440  continue;
441  }
442 
443  sub_size=from_integer(sub_bytes, size_type());
444  }
445 
446  result=if_exprt(
447  binary_relation_exprt(result, ID_lt, sub_size),
448  sub_size, result);
449 
450  simplify(result, ns);
451  }
452 
453  return result;
454  }
455  else if(type.id()==ID_signedbv ||
456  type.id()==ID_unsignedbv ||
457  type.id()==ID_fixedbv ||
458  type.id()==ID_floatbv ||
459  type.id()==ID_bv ||
460  type.id()==ID_c_bool ||
461  type.id()==ID_c_bit_field)
462  {
463  std::size_t width=to_bitvector_type(type).get_width();
464  std::size_t bytes = width / config.ansi_c.char_width;
465  if(bytes * config.ansi_c.char_width != width)
466  bytes++;
467  return from_integer(bytes, size_type());
468  }
469  else if(type.id()==ID_c_enum)
470  {
471  return size_of_expr(to_c_enum_type(type).underlying_type(), ns);
472  }
473  else if(type.id()==ID_c_enum_tag)
474  {
475  return size_of_expr(ns.follow_tag(to_c_enum_tag_type(type)), ns);
476  }
477  else if(type.id()==ID_bool)
478  {
479  return from_integer(1, size_type());
480  }
481  else if(type.id()==ID_pointer)
482  {
483  // the following is an MS extension
484  if(type.get_bool(ID_C_ptr32))
486 
487  std::size_t width=to_bitvector_type(type).get_width();
488  std::size_t bytes = width / config.ansi_c.char_width;
489  if(bytes * config.ansi_c.char_width != width)
490  bytes++;
491  return from_integer(bytes, size_type());
492  }
493  else if(type.id() == ID_union_tag)
494  {
495  return size_of_expr(ns.follow_tag(to_union_tag_type(type)), ns);
496  }
497  else if(type.id() == ID_struct_tag)
498  {
499  return size_of_expr(ns.follow_tag(to_struct_tag_type(type)), ns);
500  }
501  else if(type.id()==ID_code)
502  {
503  return from_integer(0, size_type());
504  }
505  else if(type.id()==ID_string)
506  {
508  }
509  else
510  return {};
511 }
512 
513 std::optional<mp_integer>
514 compute_pointer_offset(const exprt &expr, const namespacet &ns)
515 {
516  if(expr.id()==ID_symbol)
517  {
518  if(is_ssa_expr(expr))
519  return compute_pointer_offset(
520  to_ssa_expr(expr).get_original_expr(), ns);
521  else
522  return mp_integer(0);
523  }
524  else if(expr.id()==ID_index)
525  {
526  const index_exprt &index_expr=to_index_expr(expr);
528  index_expr.array().type().id() == ID_array,
529  "index into array expected, found " +
530  index_expr.array().type().id_string());
531 
532  auto o = compute_pointer_offset(index_expr.array(), ns);
533 
534  if(o.has_value())
535  {
536  const auto &array_type = to_array_type(index_expr.array().type());
537  auto sub_size = pointer_offset_size(array_type.element_type(), ns);
538 
539  if(sub_size.has_value() && *sub_size > 0)
540  {
541  const auto i = numeric_cast<mp_integer>(index_expr.index());
542  if(i.has_value())
543  return (*o) + (*i) * (*sub_size);
544  }
545  }
546 
547  // don't know
548  }
549  else if(expr.id()==ID_member)
550  {
551  const member_exprt &member_expr=to_member_expr(expr);
552  const exprt &op=member_expr.struct_op();
553 
554  auto o = compute_pointer_offset(op, ns);
555 
556  if(o.has_value())
557  {
558  if(op.type().id() == ID_union || op.type().id() == ID_union_tag)
559  return *o;
560 
561  const struct_typet &struct_type =
562  op.type().id() == ID_struct_tag
564  : to_struct_type(op.type());
565  auto member_offset =
566  ::member_offset(struct_type, member_expr.get_component_name(), ns);
567 
568  if(member_offset.has_value())
569  return *o + *member_offset;
570  }
571  }
572  else if(expr.id()==ID_string_constant)
573  return mp_integer(0);
574 
575  return {}; // don't know
576 }
577 
578 std::optional<exprt> get_subexpression_at_offset(
579  const exprt &expr,
580  const mp_integer &offset_bytes,
581  const typet &target_type_raw,
582  const namespacet &ns)
583 {
584  if(offset_bytes == 0 && expr.type() == target_type_raw)
585  {
586  exprt result = expr;
587 
588  if(expr.type() != target_type_raw)
589  result.type() = target_type_raw;
590 
591  return result;
592  }
593 
594  if(
595  offset_bytes == 0 && expr.type().id() == ID_pointer &&
596  target_type_raw.id() == ID_pointer)
597  {
598  return typecast_exprt(expr, target_type_raw);
599  }
600 
601  const auto target_size_bits = pointer_offset_bits(target_type_raw, ns);
602  if(!target_size_bits.has_value())
603  return {};
604 
605  if(expr.type().id() == ID_struct || expr.type().id() == ID_struct_tag)
606  {
607  const struct_typet &struct_type =
608  expr.type().id() == ID_struct_tag
609  ? ns.follow_tag(to_struct_tag_type(expr.type()))
610  : to_struct_type(expr.type());
611 
612  mp_integer m_offset_bits = 0;
613  for(const auto &component : struct_type.components())
614  {
615  const auto m_size_bits = pointer_offset_bits(component.type(), ns);
616  if(!m_size_bits.has_value())
617  return {};
618 
619  // if this member completely contains the target, and this member is
620  // byte-aligned, recurse into it
621  if(
622  offset_bytes * config.ansi_c.char_width >= m_offset_bits &&
623  m_offset_bits % config.ansi_c.char_width == 0 &&
624  offset_bytes * config.ansi_c.char_width + *target_size_bits <=
625  m_offset_bits + *m_size_bits)
626  {
627  const member_exprt member(expr, component.get_name(), component.type());
629  member,
630  offset_bytes - m_offset_bits / config.ansi_c.char_width,
631  target_type_raw,
632  ns);
633  }
634 
635  m_offset_bits += *m_size_bits;
636  }
637  }
638  else if(expr.type().id() == ID_array)
639  {
640  const array_typet &array_type = to_array_type(expr.type());
641 
642  const auto elem_size_bits =
643  pointer_offset_bits(array_type.element_type(), ns);
644 
645  // no arrays of non-byte-aligned, zero-, or unknown-sized objects
646  if(
647  array_type.size().is_constant() && elem_size_bits.has_value() &&
648  *elem_size_bits > 0 && *elem_size_bits % config.ansi_c.char_width == 0 &&
649  *target_size_bits <= *elem_size_bits)
650  {
651  const mp_integer array_size =
652  numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
653  const mp_integer elem_size_bytes =
654  *elem_size_bits / config.ansi_c.char_width;
655  const mp_integer index = offset_bytes / elem_size_bytes;
656  const auto offset_inside_elem = offset_bytes % elem_size_bytes;
657  const auto target_size_bytes =
658  *target_size_bits / config.ansi_c.char_width;
659  // only recurse if the cell completely contains the target
660  if(
661  index < array_size &&
662  offset_inside_elem + target_size_bytes <= elem_size_bytes)
663  {
665  index_exprt(
666  expr,
667  from_integer(
668  offset_bytes / elem_size_bytes, array_type.index_type())),
669  offset_inside_elem,
670  target_type_raw,
671  ns);
672  }
673  }
674  }
675  else if(
676  object_descriptor_exprt(expr).root_object().id() == ID_union &&
677  (expr.type().id() == ID_union || expr.type().id() == ID_union_tag))
678  {
679  const union_typet &union_type =
680  expr.type().id() == ID_union_tag
681  ? ns.follow_tag(to_union_tag_type(expr.type()))
682  : to_union_type(expr.type());
683 
684  for(const auto &component : union_type.components())
685  {
686  const auto m_size_bits = pointer_offset_bits(component.type(), ns);
687  if(!m_size_bits.has_value())
688  continue;
689 
690  // if this member completely contains the target, recurse into it
691  if(
692  offset_bytes * config.ansi_c.char_width + *target_size_bits <=
693  *m_size_bits)
694  {
695  const member_exprt member(expr, component.get_name(), component.type());
697  member, offset_bytes, target_type_raw, ns);
698  }
699  }
700  }
701 
702  return make_byte_extract(
703  expr, from_integer(offset_bytes, c_index_type()), target_type_raw);
704 }
705 
706 std::optional<exprt> get_subexpression_at_offset(
707  const exprt &expr,
708  const exprt &offset,
709  const typet &target_type,
710  const namespacet &ns)
711 {
712  const auto offset_bytes = numeric_cast<mp_integer>(offset);
713 
714  if(!offset_bytes.has_value())
715  return {};
716  else
717  return get_subexpression_at_offset(expr, *offset_bytes, target_type, ns);
718 }
configt config
Definition: config.cpp:25
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
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.
bitvector_typet c_index_type()
Definition: c_types.cpp:16
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition: c_types.h:335
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition: c_types.h:80
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:184
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition: c_types.h:377
Arrays with given size.
Definition: std_types.h:807
typet index_type() const
The type of the index expressions into any instance of this type.
Definition: std_types.cpp:33
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:827
const exprt & size() const
Definition: std_types.h:840
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:762
std::size_t get_width() const
Definition: std_types.h:920
struct configt::ansi_ct ansi_c
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 is_constant() const
Return whether the expression is a constant.
Definition: expr.h:212
The trinary if-then-else operator.
Definition: std_expr.h:2370
Array index operator.
Definition: std_expr.h:1465
exprt & array()
Definition: std_expr.h:1495
exprt & index()
Definition: std_expr.h:1505
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
const std::string & id_string() const
Definition: irep.h:387
const irep_idt & id() const
Definition: irep.h:384
bool is_nil() const
Definition: irep.h:364
Extract member of struct or union.
Definition: std_expr.h:2841
const exprt & struct_op() const
Definition: std_expr.h:2879
irep_idt get_component_name() const
Definition: std_expr.h:2863
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1107
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
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:181
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const componentst & components() const
Definition: std_types.h:147
std::vector< componentt > componentst
Definition: std_types.h:140
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
The union type.
Definition: c_types.h:147
std::optional< std::pair< struct_union_typet::componentt, mp_integer > > find_widest_union_component(const namespacet &ns) const
Determine the member of maximum bit width in a union type.
Definition: c_types.cpp:300
const constant_exprt & size() const
Definition: std_types.cpp:275
API to expression classes for Pointers.
std::optional< mp_integer > compute_pointer_offset(const exprt &expr, const namespacet &ns)
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
std::optional< mp_integer > member_offset(const struct_typet &type, const irep_idt &member, const namespacet &ns)
std::optional< exprt > get_subexpression_at_offset(const exprt &expr, const mp_integer &offset_bytes, const typet &target_type_raw, const namespacet &ns)
std::optional< mp_integer > member_offset_bits(const struct_typet &type, const irep_idt &member, const namespacet &ns)
std::optional< exprt > member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
Pointer Logic.
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
BigInt mp_integer
Definition: smt_terms.h:17
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:534
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
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
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:80
API to expression classes.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:3037
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2933
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1533
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition: std_types.h:1104
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:888
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition: std_types.h:1146
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
std::size_t char_width
Definition: config.h:140
#define size_type
Definition: unistd.c:347