CBMC
Loading...
Searching...
No Matches
c_typecheck_type.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: C++ Language Type Checking
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include <util/arith_tools.h>
13#include <util/c_types.h>
14#include <util/config.h>
15#include <util/cprover_prefix.h>
16#include <util/fresh_symbol.h>
18#include <util/pointer_expr.h>
20#include <util/simplify_expr.h>
22
23#include "ansi_c_convert_type.h"
24#include "ansi_c_declaration.h"
25#include "c_qualifiers.h"
26#include "c_typecheck_base.h"
27#include "gcc_types.h"
28#include "padding.h"
29#include "type2name.h"
30#include "typedef_type.h"
31
32#include <unordered_set>
33
35{
36 // we first convert, and then check
37 {
39 ansi_c_convert_type.write(type);
40 }
41
42 if(type.id()==ID_already_typechecked)
43 {
44 already_typechecked_typet &already_typechecked =
46
47 // need to preserve any qualifiers
48 c_qualifierst c_qualifiers(type);
49 c_qualifiers += c_qualifierst(already_typechecked.get_type());
50 bool packed=type.get_bool(ID_C_packed);
51 exprt alignment=static_cast<const exprt &>(type.find(ID_C_alignment));
53
54 type = already_typechecked.get_type();
55
56 c_qualifiers.write(type);
57 if(packed)
58 type.set(ID_C_packed, true);
59 if(alignment.is_not_nil())
61 if(_typedef.is_not_nil())
63
64 return; // done
65 }
66
67 // do we have alignment?
68 if(type.find(ID_C_alignment).is_not_nil())
69 {
70 exprt &alignment=static_cast<exprt &>(type.add(ID_C_alignment));
71 if(alignment.id()!=ID_default)
72 {
75 }
76 }
77
78 if(type.id()==ID_code)
80 else if(type.id()==ID_array)
82 else if(type.id()==ID_pointer)
83 {
84 typecheck_type(to_pointer_type(type).base_type());
86 to_bitvector_type(type).get_width() > 0, "pointers must have width");
87 }
88 else if(type.id()==ID_struct ||
89 type.id()==ID_union)
91 else if(type.id()==ID_c_enum)
93 else if(type.id()==ID_c_enum_tag)
95 else if(type.id()==ID_c_bit_field)
97 else if(type.id() == ID_typeof || type.id() == ID_c_typeof_unqual)
99 else if(type.id() == ID_typedef_type)
101 else if(type.id() == ID_struct_tag ||
102 type.id() == ID_union_tag)
103 {
104 // nothing to do, these stay as is
105 }
106 else if(type.id()==ID_vector)
107 {
108 // already done
109 }
110 else if(type.id() == ID_frontend_vector)
111 {
113 }
114 else if(type.id()==ID_custom_unsignedbv ||
115 type.id()==ID_custom_signedbv ||
116 type.id()==ID_custom_floatbv ||
117 type.id()==ID_custom_fixedbv)
119 else if(type.id() == ID_c_signed_bitint || type.id() == ID_c_unsigned_bitint)
120 {
122 }
123 else if(type.id()==ID_gcc_attribute_mode)
124 {
125 // get that mode
126 const irep_idt gcc_attr_mode = type.get(ID_size);
127
128 // A list of all modes is at
129 // http://www.delorie.com/gnu/docs/gcc/gccint_53.html
130 typecheck_type(to_type_with_subtype(type).subtype());
131
132 typet underlying_type = to_type_with_subtype(type).subtype();
133
134 // gcc allows this, but clang doesn't; it's a compiler hint only,
135 // but we'll try to interpret it the GCC way
136 if(underlying_type.id()==ID_c_enum_tag)
137 {
138 underlying_type =
139 follow_tag(to_c_enum_tag_type(underlying_type)).underlying_type();
140
142 underlying_type.id() == ID_signedbv ||
143 underlying_type.id() == ID_unsignedbv,
144 "underlying type must be bitvector");
145 }
146
147 if(underlying_type.id()==ID_signedbv ||
148 underlying_type.id()==ID_unsignedbv)
149 {
150 bool is_signed=underlying_type.id()==ID_signedbv;
151
153
154 if(gcc_attr_mode == "__QI__") // 8 bits
155 {
156 if(is_signed)
158 else
160 }
161 else if(gcc_attr_mode == "__byte__") // 8 bits
162 {
163 if(is_signed)
165 else
167 }
168 else if(gcc_attr_mode == "__HI__") // 16 bits
169 {
170 if(is_signed)
172 else
174 }
175 else if(gcc_attr_mode == "__SI__") // 32 bits
176 {
177 if(is_signed)
179 else
181 }
182 else if(gcc_attr_mode == "__word__") // long int, we think
183 {
184 if(is_signed)
186 else
188 }
189 else if(gcc_attr_mode == "__pointer__") // size_t/ssize_t, we think
190 {
191 if(is_signed)
193 else
195 }
196 else if(gcc_attr_mode == "__DI__") // 64 bits
197 {
198 if(config.ansi_c.long_int_width==64)
199 {
200 if(is_signed)
202 else
204 }
205 else
206 {
207 PRECONDITION(config.ansi_c.long_long_int_width == 64);
208
209 if(is_signed)
211 else
213 }
214 }
215 else if(gcc_attr_mode == "__TI__") // 128 bits
216 {
217 if(is_signed)
219 else
221 }
222 else if(gcc_attr_mode == "__V2SI__") // vector of 2 ints, deprecated
223 {
224 if(is_signed)
225 {
228 }
229 else
230 {
233 }
234 }
235 else if(gcc_attr_mode == "__V4SI__") // vector of 4 ints, deprecated
236 {
237 if(is_signed)
238 {
241 }
242 else
243 {
246 }
247 }
248 else // give up, just use subtype
249 result = to_type_with_subtype(type).subtype();
250
251 // save the location
252 result.add_source_location()=type.source_location();
253
254 if(to_type_with_subtype(type).subtype().id() == ID_c_enum_tag)
255 {
256 const irep_idt &tag_name =
258 .get_identifier();
260 .subtype() = result;
261 }
262
263 type=result;
264 }
265 else if(underlying_type.id()==ID_floatbv)
266 {
268
269 if(gcc_attr_mode == "__SF__") // 32 bits
271 else if(gcc_attr_mode == "__DF__") // 64 bits
273 else if(gcc_attr_mode == "__TF__") // 128 bits
275 else if(gcc_attr_mode == "__V2SF__") // deprecated vector of 2 floats
278 else if(gcc_attr_mode == "__V2DF__") // deprecated vector of 2 doubles
281 else if(gcc_attr_mode == "__V4SF__") // deprecated vector of 4 floats
284 else if(gcc_attr_mode == "__V4DF__") // deprecated vector of 4 doubles
287 else // give up, just use subtype
288 result = to_type_with_subtype(type).subtype();
289
290 // preserve the location
291 type = result.with_source_location(type);
292 }
293 else if(underlying_type.id()==ID_complex)
294 {
295 // gcc allows this, but clang doesn't -- see enums above
297
298 if(gcc_attr_mode == "__SC__") // 32 bits
300 else if(gcc_attr_mode == "__DC__") // 64 bits
302 else if(gcc_attr_mode == "__TC__") // 128 bits
304 else // give up, just use subtype
305 result = to_type_with_subtype(type).subtype();
306
307 // save the location
309 }
310 else
311 {
312 throw errort().with_location(type.source_location())
313 << "attribute mode '" << gcc_attr_mode
314 << "' applied to inappropriate type '" << to_string(type) << "'";
315 }
316 }
317
318 // do a mild bit of rule checking
319
320 if(type.get_bool(ID_C_restricted) &&
321 type.id()!=ID_pointer &&
322 type.id()!=ID_array)
323 {
324 throw errort().with_location(type.source_location())
325 << "only a pointer can be 'restrict'";
326 }
327}
328
330{
331 // they all have a width
333 static_cast<const exprt &>(type.find(ID_size));
334
336 source_locationt source_location=size_expr.source_location();
338
341 {
342 throw errort().with_location(source_location)
343 << "failed to convert bit vector width to constant";
344 }
345
346 if(size_int<1)
347 {
348 throw errort().with_location(source_location) << "bit vector width invalid";
349 }
350
351 type.remove(ID_size);
353
354 // depending on type, there may be a number of fractional bits
355
356 if(type.id()==ID_custom_unsignedbv)
357 type.id(ID_unsignedbv);
358 else if(type.id()==ID_custom_signedbv)
359 type.id(ID_signedbv);
360 else if(type.id()==ID_custom_fixedbv)
361 {
362 type.id(ID_fixedbv);
363
365 static_cast<const exprt &>(type.find(ID_f));
366
368 f_expr.find_source_location();
369
371
373
376 {
378 << "failed to convert number of fraction bits to constant";
379 }
380
382 {
384 << "fixedbv fraction width invalid";
385 }
386
387 type.remove(ID_f);
389 }
390 else if(type.id()==ID_custom_floatbv)
391 {
392 type.id(ID_floatbv);
393
395 static_cast<const exprt &>(type.find(ID_f));
396
398 f_expr.find_source_location();
399
401
403
406 {
408 << "failed to convert number of fraction bits to constant";
409 }
410
412 {
414 << "floatbv fraction width invalid";
415 }
416
417 type.remove(ID_f);
419 }
420 else
422}
423
425{
426 // These have a given width, which is the sum of the number of
427 // value bits and, if signed, one for the sign bit (ISO C 2024, 6.2.6.2)
428 exprt width_expr = static_cast<const exprt &>(type.find(ID_width));
429
431 source_locationt source_location = width_expr.source_location();
433
436 {
437 throw errort().with_location(source_location)
438 << "failed to convert _BitInt width to constant";
439 }
440
441 bool is_signed = type.id() == ID_c_signed_bitint;
442
443 // Must have at least one value bit
444 if(!is_signed)
445 {
446 if(width_int < 1)
447 {
448 throw errort().with_location(source_location)
449 << "unsigned _BitInt must have at least one bit";
450 }
451 }
452 else
453 {
454 if(width_int < 2)
455 {
456 throw errort().with_location(source_location)
457 << "signed _BitInt must have at least two bits";
458 }
459 }
460
461 // These get padded up, much like _Bool.
462 // The padding is implementation-defined,
463 // and takes unspecified values.
464 auto bytes = (width_int % 8) == 0 ? width_int / 8 : width_int / 8 + 1;
465
466 // We pad up to until the number of bytes is a power of two.
467 auto bytes_padded = power(2, bytes == 1 ? 0 : address_bits(bytes));
468
469 auto width = 8 * bytes_padded;
470
471 type.set(ID_width, integer2string(width));
472 type.set(ID_C_c_type, type.id());
473 type.id(ID_bv);
474
475 // We remember the original number of bits before padding,
476 // since these determine semantics
478}
479
481{
482 // the return type is still 'subtype()'
483 type.return_type() = to_type_with_subtype(type).subtype();
484 type.remove_subtype();
485
486 code_typet::parameterst &parameters=type.parameters();
487
488 // if we don't have any parameters, we assume it's (...)
489 if(parameters.empty())
490 {
491 type.make_ellipsis();
492 }
493 else // we do have parameters
494 {
495 // is the last one ellipsis?
496 if(type.parameters().back().id()==ID_ellipsis)
497 {
498 type.make_ellipsis();
499 type.parameters().pop_back();
500 }
501
503
504 for(auto &param : type.parameters())
505 {
506 // turn the declarations into parameters
507 if(param.id()==ID_declaration)
508 {
509 ansi_c_declarationt &declaration=
511
512
513 // first fix type
515 declaration.full_type(declaration.declarator()));
516 typet &param_type = parameter.type();
517 std::list<codet> tmp_clean_code;
518 tmp_clean_code.swap(clean_code); // ignore side-effects
522
523 // adjust the identifier
524 irep_idt identifier=declaration.declarator().get_name();
525
526 // abstract or not?
527 if(identifier.empty())
528 {
529 // abstract
530 parameter.add_source_location()=declaration.type().source_location();
531 }
532 else
533 {
534 // make visible now, later parameters might use it
535 parameter_map[identifier] = param_type;
536 parameter.set_base_name(declaration.declarator().get_base_name());
537 parameter.add_source_location()=
538 declaration.declarator().source_location();
539 }
540
541 // put the parameter in place of the declaration
542 param.swap(parameter);
543 }
544 }
545
547
548 if(parameters.size() == 1 && parameters[0].type().id() == ID_empty)
549 {
550 // if we just have one parameter of type void, remove it
551 parameters.clear();
552 }
553 }
554
556
557 // 6.7.6.3:
558 // "A function declarator shall not specify a return type that
559 // is a function type or an array type."
560
561 const typet &decl_return_type = type.return_type();
562
563 if(decl_return_type.id() == ID_array)
564 {
565 throw errort().with_location(type.source_location())
566 << "function must not return array";
567 }
568
569 if(decl_return_type.id() == ID_code)
570 {
571 throw errort().with_location(type.source_location())
572 << "function must not return function type";
573 }
574}
575
577{
578 // Typecheck the element type.
580
581 // We don't allow void as the element type.
582 if(type.element_type().id() == ID_empty)
583 {
584 throw errort().with_location(type.source_location()) << "array of voids";
585 }
586
587 // We don't allow incomplete structs or unions as element type.
588 if(
589 (type.element_type().id() == ID_struct_tag &&
590 follow_tag(to_struct_tag_type(type.element_type())).is_incomplete()) ||
591 (type.element_type().id() == ID_union_tag &&
592 follow_tag(to_union_tag_type(type.element_type())).is_incomplete()))
593 {
594 // ISO/IEC 9899 6.7.5.2
595 throw errort().with_location(type.source_location())
596 << "array has incomplete element type";
597 }
598
599 // We don't allow functions as element type.
600 if(type.element_type().id() == ID_code)
601 {
602 // ISO/IEC 9899 6.7.5.2
603 throw errort().with_location(type.source_location())
604 << "array of function element type";
605 }
606
607 // We add the index type.
609
610 // Check the array size, if given.
611 if(type.is_complete())
612 {
613 exprt &size = type.size();
615 typecheck_expr(size);
616 make_index_type(size);
617
618 // The size need not be a constant!
619 // We simplify it, for the benefit of array initialisation.
620
621 exprt tmp_size=size;
623 simplify(tmp_size, *this);
624
625 if(tmp_size.is_constant())
626 {
627 mp_integer s;
629 {
631 << "failed to convert constant: " << tmp_size.pretty();
632 }
633
634 if(s<0)
635 {
637 << "array size must not be negative, "
638 "but got "
639 << s;
640 }
641
642 size=tmp_size;
643 }
644 else if(tmp_size.id()==ID_infinity)
645 {
646 size=tmp_size;
647 }
648 else if(tmp_size.id()==ID_symbol &&
649 tmp_size.type().get_bool(ID_C_constant))
650 {
651 // We allow a constant variable as array size, assuming
652 // it won't change.
653 // This criterion can be tricked:
654 // Of course we can modify a 'const' symbol, e.g.,
655 // using a pointer type cast. Interestingly,
656 // at least gcc 4.2.1 makes the very same mistake!
657 size=tmp_size;
658 }
659 else
660 {
661 // not a constant and not infinity
662
664
666 {
668 << "array size of static symbol '" << current_symbol.base_name
669 << "' is not constant";
670 }
671
672 symbolt &new_symbol = get_fresh_aux_symbol(
673 size_type(),
674 id2string(current_symbol.name) + "$array_size",
675 id2string(current_symbol.base_name) + "$array_size",
677 mode,
679 new_symbol.type.set(ID_C_constant, true);
681
682 // produce the code that declares and initializes the symbol
683 symbol_exprt symbol_expr = new_symbol.symbol_expr();
684
685 code_frontend_declt declaration(symbol_expr);
687
688 code_frontend_assignt assignment;
689 assignment.lhs()=symbol_expr;
690 assignment.rhs() = new_symbol.value;
692
693 // store the code
694 clean_code.push_back(declaration);
695 clean_code.push_back(assignment);
696
697 // fix type
698 size=symbol_expr;
699 }
700 }
701}
702
704{
705 // This turns the type with ID_frontend_vector into the type
706 // with ID_vector; the difference is that the latter has
707 // a constant as size, which we establish now.
708 exprt size = static_cast<const exprt &>(type.find(ID_size));
709 const source_locationt source_location = size.find_source_location();
710
711 typecheck_expr(size);
712
713 typet subtype = to_type_with_subtype(type).subtype();
714 typecheck_type(subtype);
715
716 // we are willing to combine 'vector' with various
717 // other types, but not everything!
718
719 if(subtype.id()!=ID_signedbv &&
720 subtype.id()!=ID_unsignedbv &&
721 subtype.id()!=ID_floatbv &&
722 subtype.id()!=ID_fixedbv)
723 {
724 throw errort().with_location(source_location)
725 << "cannot make a vector of subtype " << to_string(subtype);
726 }
727
729
730 mp_integer s;
731 if(to_integer(to_constant_expr(size), s))
732 {
733 throw errort().with_location(source_location)
734 << "failed to convert constant: " << size.pretty();
735 }
736
737 if(s<=0)
738 {
739 throw errort().with_location(source_location)
740 << "vector size must be positive, "
741 "but got "
742 << s;
743 }
744
745 // the subtype must have constant size
746 auto sub_size_expr_opt = size_of_expr(subtype, *this);
747
748 if(!sub_size_expr_opt.has_value())
749 {
750 throw errort().with_location(source_location)
751 << "failed to determine size of vector base type '" << to_string(subtype)
752 << "'";
753 }
754
755 simplify(sub_size_expr_opt.value(), *this);
756
758
759 if(!sub_size.has_value())
760 {
761 throw errort().with_location(source_location)
762 << "failed to determine size of vector base type '" << to_string(subtype)
763 << "'";
764 }
765
766 if(*sub_size == 0)
767 {
768 throw errort().with_location(source_location)
769 << "type had size 0: '" << to_string(subtype) << "'";
770 }
771
772 // adjust by width of base type
773 if(s % *sub_size != 0)
774 {
775 throw errort().with_location(source_location)
776 << "vector size (" << s << ") expected to be multiple of base type size ("
777 << *sub_size << ")";
778 }
779
780 s /= *sub_size;
781
782 // produce the type with ID_vector
784 c_index_type(), subtype, from_integer(s, signed_size_type()));
785 new_type.size().add_source_location() = source_location;
786 type = new_type.with_source_location(source_location);
787}
788
790{
791 // These get replaced by symbol types later.
792 irep_idt identifier;
793
794 bool have_body=type.find(ID_components).is_not_nil();
795
797
798 // the type symbol, which may get re-used in other declarations, must not
799 // carry any qualifiers (other than transparent_union, which isn't really a
800 // qualifier)
802 remove_qualifiers.is_transparent_union =
803 original_qualifiers.is_transparent_union;
804 remove_qualifiers.write(type);
805
806 bool is_packed = type.get_bool(ID_C_packed);
808
809 if(type.find(ID_tag).is_nil())
810 {
811 // Anonymous? Must come with body.
813
814 // produce symbol
816 compound_symbol.location=type.source_location();
817
819
820 std::string typestr = type2name(compound_symbol.type, *this);
821 compound_symbol.base_name = "#anon#" + typestr;
822 compound_symbol.name="tag-#anon#"+typestr;
823 identifier=compound_symbol.name;
824
825 // We might already have the same anonymous union/struct,
826 // and this is simply ok. Note that the C standard treats
827 // these as different types.
828 if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end())
829 {
830 symbolt *new_symbol;
831 move_symbol(compound_symbol, new_symbol);
832 }
833 }
834 else
835 {
836 identifier=type.find(ID_tag).get(ID_identifier);
837
838 // does it exist already?
839 symbol_table_baset::symbolst::const_iterator s_it =
840 symbol_table.symbols.find(identifier);
841
842 if(s_it==symbol_table.symbols.end())
843 {
844 // no, add new symbol
845 irep_idt base_name=type.find(ID_tag).get(ID_C_base_name);
846 type.remove(ID_tag);
847 type.set(ID_tag, base_name);
848
849 type_symbolt compound_symbol{identifier, type, mode};
850 compound_symbol.base_name=base_name;
851 compound_symbol.location=type.source_location();
852 compound_symbol.pretty_name=id2string(type.id())+" "+id2string(base_name);
853
855
856 // mark as incomplete
857 to_struct_union_type(compound_symbol.type).make_incomplete();
858
859 symbolt *new_symbol;
860 move_symbol(compound_symbol, new_symbol);
861
862 if(have_body)
863 {
865
866 new_symbol->type.swap(new_type);
867 }
868 }
869 else
870 {
871 // yes, it exists already
872 if(
873 s_it->second.type.id() == type.id() &&
874 to_struct_union_type(s_it->second.type).is_incomplete())
875 {
876 // Maybe we got a body now.
877 if(have_body)
878 {
879 irep_idt base_name=type.find(ID_tag).get(ID_C_base_name);
880 type.remove(ID_tag);
881 type.set(ID_tag, base_name);
882
885 }
886 }
887 else if(s_it->second.type.id() != type.id())
888 {
889 throw errort().with_location(type.source_location())
890 << "redefinition of '" << s_it->second.pretty_name << "'"
891 << " as different kind of tag";
892 }
893 else if(have_body)
894 {
895 throw errort().with_location(type.source_location())
896 << "redefinition of body of '" << s_it->second.pretty_name << "'";
897 }
898 }
899 }
900
902
903 if(type.id() == ID_union)
904 tag_type = union_tag_typet(identifier);
905 else if(type.id() == ID_struct)
906 tag_type = struct_tag_typet(identifier);
907 else
909
910 tag_type.add_source_location() = type.source_location();
911 type.swap(tag_type);
912
913 original_qualifiers.write(type);
914
915 if(is_packed)
916 type.set(ID_C_packed, true);
917 if(alignment.is_not_nil())
919}
920
922 struct_union_typet &type)
923{
925
927 old_components.swap(components);
928
929 // We get these as declarations!
930 for(auto &decl : old_components)
931 {
932 // the arguments are member declarations or static assertions
933 PRECONDITION(decl.id() == ID_declaration);
934
935 ansi_c_declarationt &declaration=
936 to_ansi_c_declaration(static_cast<exprt &>(decl));
937
938 if(declaration.get_is_static_assert())
939 {
942 new_component.add_source_location()=declaration.source_location();
943 PRECONDITION(declaration.operands().size() == 2);
944 new_component.operands().swap(declaration.operands());
945 components.push_back(new_component);
946 }
947 else
948 {
949 // do first half of type
950 typecheck_type(declaration.type());
952
953 for(const auto &declarator : declaration.declarators())
954 {
956 declarator.get_base_name(), declaration.full_type(declarator));
957
958 // There may be a declarator, which we use as location for
959 // the component. Otherwise, use location of the declaration.
960 const source_locationt source_location =
961 declarator.get_name().empty() ? declaration.source_location()
962 : declarator.source_location();
963
964 new_component.add_source_location() = source_location;
965 new_component.set_pretty_name(declarator.get_base_name());
966
968
969 // the rules for anonymous members depend on the type and the compiler,
970 // just bit fields are accepted everywhere
971 if(
972 new_component.get_name().empty() &&
973 new_component.type().id() != ID_c_bit_field)
974 {
976 {
977 // Visual Studio rejects anything other than a struct or union
978 // declaration, but also accepts those when they introduce a tag
979 if(
980 new_component.type().id() != ID_struct_tag &&
981 new_component.type().id() != ID_union_tag)
982 {
983 throw errort().with_location(source_location)
984 << "no members defined";
985 }
986 }
987 else
988 {
989 // C11 allows an *untagged* struct/union as an anonymous member.
990 // -fms-extensions (and MSVC) additionally allow a *tagged*
991 // struct/union as an anonymous member, injecting its members
992 // and contributing its size -- used throughout the Linux kernel
993 // (e.g. `struct __filename_head;` embedded in struct filename).
994 // Anything else -- a non-struct/union unnamed member (e.g. a bare
995 // `int;`), or a tagged struct/union without -fms-extensions -- is
996 // ignored (the GCC/Clang behaviour we preserve).
997 const typet &member_type = new_component.type();
998 if(
999 member_type.id() != ID_struct_tag &&
1000 member_type.id() != ID_union_tag)
1001 continue; // not a struct/union: ignore
1002 const bool is_untagged =
1004 .find(ID_tag)
1005 .is_nil();
1006 if(!is_untagged && !config.ansi_c.allow_anonymous_struct_embedding)
1007 continue; // tagged anonymous member needs -fms-extensions
1008 }
1009 }
1010
1011 if(!is_complete_type(new_component.type()) &&
1012 (new_component.type().id()!=ID_array ||
1013 !to_array_type(new_component.type()).is_incomplete()))
1014 {
1015 throw errort().with_location(source_location)
1016 << "incomplete type not permitted here";
1017 }
1018
1019 if(new_component.type().id() == ID_empty)
1020 {
1021 throw errort().with_location(source_location)
1022 << "void-typed member not permitted";
1023 }
1024
1025 if(
1026 new_component.type().id() == ID_c_bit_field &&
1027 to_c_bit_field_type(new_component.type()).get_width() == 0 &&
1028 !new_component.get_name().empty())
1029 {
1030 throw errort().with_location(source_location)
1031 << "zero-width bit-field with declarator not permitted";
1032 }
1033
1034 components.push_back(new_component);
1035 }
1036 }
1037 }
1038
1039 unsigned anon_member_counter=0;
1040
1041 // scan for anonymous members, and name them
1042 for(auto &member : components)
1043 {
1044 if(!member.get_name().empty())
1045 continue;
1046
1047 member.set_name("$anon"+std::to_string(anon_member_counter++));
1048 member.set_anonymous(true);
1049 }
1050
1051 // scan for duplicate members
1052
1053 {
1054 std::unordered_set<irep_idt> members;
1055
1056 for(const auto &c : components)
1057 {
1058 if(!members.insert(c.get_name()).second)
1059 {
1060 throw errort().with_location(c.source_location())
1061 << "duplicate member '" << c.get_name() << '\'';
1062 }
1063 }
1064 }
1065
1066 // We allow an incomplete array as _last_ member of a struct,
1067 // C11 6.7.2.1 §18. These are called "flexible array members".
1068 // Zero-length (a gcc extension) is allowed everywhere.
1069 // Flexible array members are not allowed in unions in ISO C, but we allow
1070 // them as an extension on Windows.
1071 if(type.id() == ID_struct || type.id() == ID_union)
1072 {
1073 for(struct_union_typet::componentst::iterator it = components.begin();
1074 it != components.end();
1075 it++)
1076 {
1077 typet &component_type = it->type();
1078
1079 if(
1080 component_type.id() != ID_array ||
1081 !to_array_type(component_type).is_incomplete())
1082 {
1083 continue;
1084 }
1085
1086 if(type.id() == ID_struct)
1087 {
1088 // needs to be last member
1089 if(it != --components.end())
1090 {
1091 throw errort().with_location(it->source_location())
1092 << "flexible struct member must be last member";
1093 }
1094 }
1096 {
1097 throw errort().with_location(it->source_location())
1098 << "flexible array members in a union are a Microsoft "
1099 "extension, and not permitted in ISO C";
1100 }
1101
1102 // make it zero-length
1103 to_array_type(component_type).size() = from_integer(0, c_index_type());
1104 component_type.set(ID_C_flexible_array_member, true);
1105 }
1106 }
1107
1108 // We may add some minimal padding inside and at
1109 // the end of structs and
1110 // as additional member for unions.
1111
1112 if(type.id()==ID_struct)
1113 add_padding(to_struct_type(type), *this);
1114 else if(type.id()==ID_union)
1115 add_padding(to_union_type(type), *this);
1116
1117 // finally, check _Static_assert inside the compound
1118 for(struct_union_typet::componentst::iterator
1119 it=components.begin();
1120 it!=components.end();
1121 ) // no it++
1122 {
1123 if(it->id()==ID_static_assert)
1124 {
1126 {
1127 throw errort().with_location(it->source_location())
1128 << "static_assert not supported in compound body";
1129 }
1130
1131 exprt &assertion = to_binary_expr(*it).op0();
1132 typecheck_expr(assertion);
1133 typecheck_expr(to_binary_expr(*it).op1());
1134 assertion = typecast_exprt(assertion, bool_typet());
1135 make_constant(assertion);
1136
1137 if(assertion == false)
1138 {
1139 throw errort().with_location(it->source_location())
1140 << "failed _Static_assert";
1141 }
1142 else if(assertion != true)
1143 {
1144 // should warn/complain
1145 }
1146
1147 it=components.erase(it);
1148 }
1149 else
1150 it++;
1151 }
1152
1153 // Visual Studio strictly follows the C standard and does not permit empty
1154 // struct/union declarations
1155 if(
1156 components.empty() &&
1158 {
1159 throw errort().with_location(type.source_location())
1160 << "C requires that a struct or union has at least one member";
1161 }
1162}
1163
1165 const mp_integer &min_value,
1166 const mp_integer &max_value) const
1167{
1169 {
1170 return signed_int_type();
1171 }
1172 else
1173 {
1174 // enum constants are at least 'int', but may be made larger.
1175 // 'Packing' has no influence.
1176 if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
1177 min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
1178 return signed_int_type();
1179 else if(max_value<(mp_integer(1)<<config.ansi_c.int_width) &&
1180 min_value>=0)
1181 return unsigned_int_type();
1182 else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width) &&
1183 min_value>=0)
1184 return unsigned_long_int_type();
1185 else if(max_value<(mp_integer(1)<<config.ansi_c.long_long_int_width) &&
1186 min_value>=0)
1188 else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
1189 min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
1190 return signed_long_int_type();
1191 else
1193 }
1194}
1195
1197 const mp_integer &min_value,
1198 const mp_integer &max_value,
1199 bool is_packed) const
1200{
1202 {
1203 return signed_int_type();
1204 }
1205 else
1206 {
1207 if(min_value<0)
1208 {
1209 // We'll want a signed type.
1210
1211 if(is_packed)
1212 {
1213 // If packed, there are smaller options.
1214 if(max_value<(mp_integer(1)<<(config.ansi_c.char_width-1)) &&
1215 min_value>=-(mp_integer(1)<<(config.ansi_c.char_width-1)))
1216 return signed_char_type();
1217 else if(max_value<(mp_integer(1)<<(config.ansi_c.short_int_width-1)) &&
1218 min_value>=-(mp_integer(1)<<(config.ansi_c.short_int_width-1)))
1219 return signed_short_int_type();
1220 }
1221
1222 if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
1223 min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
1224 return signed_int_type();
1225 else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
1226 min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
1227 return signed_long_int_type();
1228 else
1230 }
1231 else
1232 {
1233 // We'll want an unsigned type.
1234
1235 if(is_packed)
1236 {
1237 // If packed, there are smaller options.
1238 if(max_value<(mp_integer(1)<<config.ansi_c.char_width))
1239 return unsigned_char_type();
1240 else if(max_value<(mp_integer(1)<<config.ansi_c.short_int_width))
1241 return unsigned_short_int_type();
1242 }
1243
1244 if(max_value<(mp_integer(1)<<config.ansi_c.int_width))
1245 return unsigned_int_type();
1246 else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width))
1247 return unsigned_long_int_type();
1248 else
1250 }
1251 }
1252}
1253
1255{
1256 // These come with the declarations
1257 // of the enum constants as operands.
1258
1259 exprt &as_expr=static_cast<exprt &>(static_cast<irept &>(type));
1260 source_locationt source_location=type.source_location();
1261
1262 // We allow empty enums in the grammar to get better
1263 // error messages.
1264 if(as_expr.operands().empty())
1265 {
1266 throw errort().with_location(source_location) << "empty enum";
1267 }
1268
1269 const bool have_underlying_type =
1270 type.find_type(ID_enum_underlying_type).is_not_nil();
1271
1273 {
1275
1276 const typet &underlying_type =
1277 static_cast<const typet &>(type.find(ID_enum_underlying_type));
1278
1279 if(!is_signed_or_unsigned_bitvector(underlying_type))
1280 {
1281 throw errort().with_location(source_location)
1282 << "non-integral type '" << underlying_type.get(ID_C_c_type)
1283 << "' is an invalid underlying type";
1284 }
1285 }
1286
1287 // enums start at zero;
1288 // we also track min and max to find a nice base type
1289 mp_integer value=0, min_value=0, max_value=0;
1290
1291 std::vector<c_enum_typet::c_enum_membert> enum_members;
1292 enum_members.reserve(as_expr.operands().size());
1293
1294 // We need to determine a width, and a signedness
1295 // to obtain an 'underlying type'.
1296 // We just do int, but gcc might pick smaller widths
1297 // if the type is marked as 'packed'.
1298 // gcc/clang may also pick a larger width. Visual Studio doesn't.
1299
1300 for(auto &op : as_expr.operands())
1301 {
1303 exprt &v=declaration.declarator().value();
1304
1305 if(v.is_not_nil()) // value given?
1306 {
1307 exprt tmp_v=v;
1310 simplify(tmp_v, *this);
1311 if(tmp_v == true)
1312 value=1;
1313 else if(tmp_v == false)
1314 value=0;
1315 else if(
1316 tmp_v.is_constant() && !to_integer(to_constant_expr(tmp_v), value))
1317 {
1318 }
1319 else
1320 {
1322 << "enum is not a constant";
1323 }
1324 }
1325
1326 if(value<min_value)
1327 min_value=value;
1328 if(value>max_value)
1329 max_value=value;
1330
1332
1334 {
1337
1338 if(value < tmp.smallest() || value > tmp.largest())
1339 {
1341 << "enumerator value is not representable in the underlying type '"
1342 << constant_type.get(ID_C_c_type) << "'";
1343 }
1344 }
1345 else
1346 {
1347 constant_type = enum_constant_type(min_value, max_value);
1348 }
1349
1350 v=from_integer(value, constant_type);
1351
1352 declaration.type()=constant_type;
1353 typecheck_declaration(declaration);
1354
1355 irep_idt base_name=
1356 declaration.declarator().get_base_name();
1357
1358 irep_idt identifier=
1359 declaration.declarator().get_name();
1360
1361 // store
1363 member.set_identifier(identifier);
1364 member.set_base_name(base_name);
1365 // Note: The value will be correctly set to a bv type when we know
1366 // the width of the bitvector
1367 member.set_value(integer2string(value));
1368 enum_members.push_back(member);
1369
1370 // produce value for next constant
1371 ++value;
1372 }
1373
1374 // Remove these now; we add them to the
1375 // c_enum symbol later.
1376 as_expr.operands().clear();
1377
1378 bool is_packed=type.get_bool(ID_C_packed);
1379
1380 // We use a subtype to store the underlying type.
1381 bitvector_typet underlying_type(ID_nil);
1382
1384 {
1385 underlying_type =
1387 }
1388 else
1389 {
1390 underlying_type = enum_underlying_type(min_value, max_value, is_packed);
1391 }
1392
1393 // Get the width to make the values have a bitvector type
1394 std::size_t width = underlying_type.get_width();
1395 for(auto &member : enum_members)
1396 {
1397 // Note: This is inefficient as it first turns integers to strings
1398 // and then turns them back to bvrep
1399 auto value = string2integer(id2string(member.get_value()));
1400 member.set_value(integer2bvrep(value, width));
1401 }
1402
1403 // tag?
1404 if(type.find(ID_tag).is_nil())
1405 {
1406 // None, it's anonymous. We generate a tag.
1407 std::string anon_identifier="#anon_enum";
1408
1409 for(const auto &member : enum_members)
1410 {
1411 anon_identifier+='$';
1412 anon_identifier+=id2string(member.get_base_name());
1413 anon_identifier+='=';
1414 anon_identifier+=id2string(member.get_value());
1415 }
1416
1417 if(is_packed)
1418 anon_identifier+="#packed";
1419
1421 }
1422
1423 irept &tag=type.add(ID_tag);
1424 irep_idt base_name=tag.get(ID_C_base_name);
1425 irep_idt identifier=tag.get(ID_identifier);
1426
1427 // Put into symbol table
1428 type_symbolt enum_tag_symbol{identifier, type, mode};
1429 enum_tag_symbol.location=source_location;
1430 enum_tag_symbol.is_file_local=true;
1431 enum_tag_symbol.base_name=base_name;
1432
1433 enum_tag_symbol.type.add_subtype() = underlying_type;
1434
1435 // throw in the enum members as 'body'
1436 to_c_enum_type(enum_tag_symbol.type).members() = std::move(enum_members);
1437
1438 // is it in the symbol table already?
1440
1441 if(existing_symbol)
1442 {
1443 // Yes.
1444 const symbolt &symbol = *existing_symbol;
1445
1446 if(symbol.type.id() != ID_c_enum)
1447 {
1448 throw errort().with_location(source_location)
1449 << "use of tag that does not match previous declaration";
1450 }
1451
1452 if(to_c_enum_type(symbol.type).is_incomplete())
1453 {
1454 // Ok, overwrite the type in the symbol table.
1455 // This gives us the members and the subtype.
1456 existing_symbol->type = enum_tag_symbol.type;
1457 }
1458 else
1459 {
1460 // We might already have the same anonymous enum, and this is
1461 // simply ok. Note that the C standard treats these as
1462 // different types.
1463 if(!base_name.empty())
1464 {
1465 throw errort().with_location(type.source_location())
1466 << "redeclaration of enum tag";
1467 }
1468 }
1469 }
1470 else
1471 {
1472 symbolt *new_symbol;
1473 move_symbol(enum_tag_symbol, new_symbol);
1474 }
1475
1476 // We produce a c_enum_tag as the resulting type.
1477 type.id(ID_c_enum_tag);
1478 type.remove(ID_tag);
1479 type.set(ID_identifier, identifier);
1480}
1481
1483{
1484 // It's just a tag.
1485
1486 if(type.find(ID_tag).is_nil())
1487 {
1488 throw errort().with_location(type.source_location())
1489 << "anonymous enum tag without members";
1490 }
1491
1492 if(type.find(ID_enum_underlying_type).is_not_nil())
1493 {
1495 warning() << "ignoring specification of underlying type for enum" << eom;
1496 }
1497
1498 source_locationt source_location=type.source_location();
1499
1500 irept &tag=type.add(ID_tag);
1501 irep_idt base_name=tag.get(ID_C_base_name);
1502 irep_idt identifier=tag.get(ID_identifier);
1503
1504 // is it in the symbol table?
1505 symbol_table_baset::symbolst::const_iterator s_it =
1506 symbol_table.symbols.find(identifier);
1507
1508 if(s_it!=symbol_table.symbols.end())
1509 {
1510 // Yes.
1511 const symbolt &symbol=s_it->second;
1512
1513 if(symbol.type.id() != ID_c_enum)
1514 {
1515 throw errort().with_location(source_location)
1516 << "use of tag that does not match previous declaration";
1517 }
1518 }
1519 else
1520 {
1521 // no, add it as an incomplete c_enum
1522 c_enum_typet new_type(signed_int_type()); // default subtype
1523 new_type.add(ID_tag)=tag;
1524 new_type.make_incomplete();
1525
1527 enum_tag_symbol.location=source_location;
1528 enum_tag_symbol.is_file_local=true;
1529 enum_tag_symbol.base_name=base_name;
1530
1531 symbolt *new_symbol;
1532 move_symbol(enum_tag_symbol, new_symbol);
1533 }
1534
1535 // Clean up resulting type
1536 type.remove(ID_tag);
1537 type.set_identifier(identifier);
1538}
1539
1541{
1543
1544 mp_integer i;
1545
1546 {
1547 exprt &width_expr=static_cast<exprt &>(type.add(ID_size));
1548
1551
1553 {
1554 throw errort().with_location(type.source_location())
1555 << "failed to convert bit field width";
1556 }
1557
1558 if(i<0)
1559 {
1560 throw errort().with_location(type.source_location())
1561 << "bit field width is negative";
1562 }
1563
1564 type.width(i);
1565 type.remove(ID_size);
1566 }
1567
1568 const typet &underlying_type = type.underlying_type();
1569
1570 std::size_t sub_width=0;
1571
1572 if(underlying_type.id() == ID_bool)
1573 {
1574 // This is the 'proper' bool.
1575 sub_width=1;
1576 }
1577 else if(
1578 underlying_type.id() == ID_signedbv ||
1579 underlying_type.id() == ID_unsignedbv || underlying_type.id() == ID_c_bool)
1580 {
1581 sub_width = to_bitvector_type(underlying_type).get_width();
1582 }
1583 else if(underlying_type.id() == ID_c_enum_tag)
1584 {
1585 // These point to an enum, which has a sub-subtype,
1586 // which may be smaller or larger than int, and we thus have
1587 // to check.
1588 const auto &c_enum_type =
1589 to_c_enum_type(follow_tag(to_c_enum_tag_type(underlying_type)));
1590
1591 if(c_enum_type.is_incomplete())
1592 {
1593 throw errort().with_location(type.source_location())
1594 << "bit field has incomplete enum type";
1595 }
1596
1597 sub_width = to_bitvector_type(c_enum_type.underlying_type()).get_width();
1598 }
1599 else
1600 {
1601 throw errort().with_location(type.source_location())
1602 << "bit field with non-integer type: " << to_string(underlying_type);
1603 }
1604
1605 if(i>sub_width)
1606 {
1607 throw errort().with_location(type.source_location())
1608 << "bit field (" << i << " bits) larger than type (" << sub_width
1609 << " bits)";
1610 }
1611}
1612
1614{
1615 // save location
1616 source_locationt source_location=type.source_location();
1617
1618 // retain the qualifiers as is
1619 c_qualifierst c_qualifiers;
1620 c_qualifiers.read(type);
1621
1622 const auto &as_expr = (const exprt &)type;
1623
1624 if(!as_expr.has_operands())
1625 {
1626 typet t=static_cast<const typet &>(type.find(ID_type_arg));
1627 typecheck_type(t);
1628 type.swap(t);
1629 }
1630 else
1631 {
1632 exprt expr = to_unary_expr(as_expr).op();
1633 typecheck_expr(expr);
1634
1635 // undo an implicit address-of
1636 if(expr.id()==ID_address_of &&
1637 expr.get_bool(ID_C_implicit))
1638 {
1639 expr = to_address_of_expr(expr).object();
1640 }
1641
1642 type.swap(expr.type());
1643 }
1644
1645 type.add_source_location()=source_location;
1646 c_qualifiers.write(type);
1647}
1648
1650{
1651 const irep_idt &identifier = to_typedef_type(type).get_identifier();
1652
1653 symbol_table_baset::symbolst::const_iterator s_it =
1654 symbol_table.symbols.find(identifier);
1655
1656 if(s_it == symbol_table.symbols.end())
1657 {
1658 throw errort().with_location(type.source_location())
1659 << "typedef symbol '" << identifier << "' not found";
1660 }
1661
1662 const symbolt &symbol = s_it->second;
1663
1664 if(!symbol.is_type)
1665 {
1666 throw errort().with_location(type.source_location())
1667 << "expected type symbol for typedef";
1668 }
1669
1670 // overwrite, but preserve (add) any qualifiers and other flags
1671
1672 c_qualifierst c_qualifiers(type);
1673 bool is_packed = type.get_bool(ID_C_packed);
1675
1676 c_qualifiers += c_qualifierst(symbol.type);
1677 type = symbol.type;
1678 c_qualifiers.write(type);
1679
1680 if(is_packed)
1681 type.set(ID_C_packed, true);
1682 if(alignment.is_not_nil())
1684
1685 // CPROVER extensions
1686 if(symbol.base_name == CPROVER_PREFIX "rational")
1687 {
1688 type=rational_typet();
1689 }
1690 else if(symbol.base_name == CPROVER_PREFIX "integer")
1691 {
1692 type=integer_typet();
1693 }
1694 else if(symbol.base_name == CPROVER_PREFIX "natural")
1695 {
1696 type = natural_typet();
1697 }
1698 else if(symbol.base_name == CPROVER_PREFIX "real")
1699 {
1700 type = real_typet();
1701 }
1702}
1703
1705{
1706 if(type.id()==ID_array)
1707 {
1708 source_locationt source_location=type.source_location();
1709 type = pointer_type(to_array_type(type).element_type());
1710 type.add_source_location()=source_location;
1711 }
1712 else if(type.id()==ID_code)
1713 {
1714 // see ISO/IEC 9899:1999 page 199 clause 8,
1715 // may be hidden in typedef
1716 source_locationt source_location=type.source_location();
1717 type=pointer_type(type);
1718 type.add_source_location()=source_location;
1719 }
1720 else if(type.id()==ID_KnR)
1721 {
1722 // any KnR args without type yet?
1723 type=signed_int_type(); // the default is integer!
1724 // no source location
1725 }
1726}
ANSI-C Language Conversion.
ANSI-CC Language Type Checking.
ansi_c_declarationt & to_ansi_c_declaration(exprt &expr)
configt config
Definition config.cpp:25
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
bool is_signed_or_unsigned_bitvector(const typet &type)
This method tests, if the given typet is a signed or unsigned bitvector.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const integer_bitvector_typet & to_integer_bitvector_type(const typet &type)
Cast a typet to an integer_bitvector_typet.
ANSI-C Language Type Checking.
already_typechecked_typet & to_already_typechecked_type(typet &type)
floatbv_typet float_type()
Definition c_types.cpp:177
signedbv_typet signed_long_int_type()
Definition c_types.cpp:72
signedbv_typet signed_char_type()
Definition c_types.cpp:134
unsignedbv_typet unsigned_int_type()
Definition c_types.cpp:36
unsignedbv_typet unsigned_long_long_int_type()
Definition c_types.cpp:93
unsignedbv_typet unsigned_long_int_type()
Definition c_types.cpp:86
signedbv_typet signed_int_type()
Definition c_types.cpp:22
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
unsignedbv_typet unsigned_char_type()
Definition c_types.cpp:127
signedbv_typet signed_size_type()
Definition c_types.cpp:66
signedbv_typet signed_long_long_int_type()
Definition c_types.cpp:79
bitvector_typet c_index_type()
Definition c_types.cpp:16
floatbv_typet double_type()
Definition c_types.cpp:185
signedbv_typet signed_short_int_type()
Definition c_types.cpp:29
unsignedbv_typet unsigned_short_int_type()
Definition c_types.cpp:43
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 c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
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
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
virtual void clear()
Reset the abstract state.
Definition ai.h:269
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
static void make_already_typechecked(typet &type)
const ansi_c_declaratort & declarator() const
const declaratorst & declarators() const
typet full_type(const ansi_c_declaratort &) const
bool get_is_static_assert() const
Arrays with given size.
Definition std_types.h:806
bool is_complete() const
Definition std_types.h:851
const exprt & size() const
Definition std_types.h:839
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:826
typet & index_type_nonconst()
The type of the index expressions into any instance of this type.
Definition std_types.h:820
Base class of fixed-width bit-vector types.
std::size_t get_width() const
std::size_t width() const
The Boolean type.
Definition std_types.h:35
Type for C bit fields These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (...
Definition c_types.h:20
const typet & underlying_type() const
Definition c_types.h:30
C enum tag type, i.e., c_enum_typet with an identifier.
Definition c_types.h:352
void set_identifier(const irep_idt &identifier)
Definition c_types.h:261
void set_value(const irep_idt &value)
Definition c_types.h:253
void set_base_name(const irep_idt &base_name)
Definition c_types.h:269
The type of C enums.
Definition c_types.h:239
virtual void write(typet &src) const
virtual void read(const typet &src)
symbol_table_baset & symbol_table
virtual void typecheck_compound_body(struct_union_typet &type)
virtual void make_index_type(exprt &expr)
virtual void typecheck_code_type(code_typet &type)
virtual void typecheck_expr(exprt &expr)
void move_symbol(symbolt &symbol, symbolt *&new_symbol)
virtual void typecheck_vector_type(typet &type)
virtual void typecheck_c_enum_type(typet &type)
virtual void make_constant(exprt &expr)
virtual void typecheck_c_bit_field_type(c_bit_field_typet &type)
static void add_rounding_mode(exprt &)
std::list< codet > clean_code
virtual std::string to_string(const exprt &expr)
void typecheck_declaration(ansi_c_declarationt &)
virtual void typecheck_c_enum_tag_type(c_enum_tag_typet &type)
virtual void adjust_function_parameter(typet &type) const
typet enum_constant_type(const mp_integer &min, const mp_integer &max) const
virtual void typecheck_custom_type(typet &type)
const irep_idt const irep_idt mode
virtual void make_constant_index(exprt &expr)
bitvector_typet enum_underlying_type(const mp_integer &min, const mp_integer &max, bool is_packed) const
virtual void typecheck_compound_type(struct_union_typet &type)
virtual bool is_complete_type(const typet &type) const
id_type_mapt parameter_map
virtual void typecheck_typedef_type(typet &type)
virtual void typecheck_bitint_type(typet &)
virtual void typecheck_array_type(array_typet &type)
virtual void typecheck_typeof_type(typet &type)
virtual void typecheck_type(typet &type)
A codet representing an assignment in the program.
Definition std_code.h:24
A codet representing the declaration of a local variable.
Definition std_code.h:347
Base type of functions.
Definition std_types.h:582
std::vector< parametert > parameterst
Definition std_types.h:585
const parameterst & parameters() const
Definition std_types.h:698
const typet & return_type() const
Definition std_types.h:688
void make_ellipsis()
Definition std_types.h:678
Complex numbers made of pair of given subtype.
Definition std_types.h:1023
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
bool empty() const
Definition dstring.h:101
Base class for all expressions.
Definition expr.h:57
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:68
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
const source_locationt & source_location() const
Definition expr.h:236
source_locationt & add_source_location()
Definition expr.h:241
Unbounded, signed integers (mathematical integers, not bitvectors)
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void remove(const irep_idt &name)
Definition irep.cpp:87
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:412
bool is_not_nil() const
Definition irep.h:372
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
irept & add(const irep_idt &name)
Definition irep.cpp:103
source_locationt source_location
Definition message.h:239
message_handlert & get_message_handler()
Definition message.h:183
mstreamt & warning() const
Definition message.h:406
mstreamt & result() const
Definition message.h:411
static eomt eom
Definition message.h:289
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
Natural numbers including zero (mathematical integers, not bitvectors)
Unbounded, signed rational numbers.
Unbounded, signed real numbers.
A struct tag type, i.e., struct_typet with an identifier.
Definition std_types.h:492
Base type for structs and unions.
Definition std_types.h:61
const componentst & components() const
Definition std_types.h:146
std::vector< componentt > componentst
Definition std_types.h:139
Expression to hold a symbol (variable)
Definition std_expr.h:132
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
virtual symbolt * get_writeable(const irep_idt &name)=0
Find a symbol in the symbol table for read-write access.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Symbol table entry.
Definition symbol.h:28
bool is_static_lifetime
Definition symbol.h:70
bool is_type
Definition symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
typet type
Type of symbol.
Definition symbol.h:31
irep_idt name
The unique identifier.
Definition symbol.h:40
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
exprt value
Initial value of symbol.
Definition symbol.h:34
void set_identifier(const irep_idt &identifier)
Definition std_types.h:404
Symbol table entry describing a data typeThis is a symbol generated as part of type checking.
Definition symbol.h:139
Semantic type conversion.
Definition std_expr.h:1995
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2003
errort with_location(source_locationt _location) &&
Definition typecheck.h:47
The type of an expression, extends irept.
Definition type.h:29
typet & add_type(const irep_idt &name)
Definition type.h:115
const typet & find_type(const irep_idt &name) const
Definition type.h:120
source_locationt & add_source_location()
Definition type.h:77
const source_locationt & source_location() const
Definition type.h:72
typet && with_source_location(source_locationt location) &&
This is a 'fluent style' method for creating a new type with an added-on source location.
Definition type.h:84
void remove_subtype()
Definition type.h:69
A union tag type, i.e., union_typet with an identifier.
Definition c_types.h:199
The vector type.
Definition std_types.h:954
#define CPROVER_PREFIX
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
signedbv_typet gcc_signed_int128_type()
Definition gcc_types.cpp:82
unsignedbv_typet gcc_unsigned_int128_type()
Definition gcc_types.cpp:75
floatbv_typet gcc_float128_type()
Definition gcc_types.cpp:57
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
Mathematical types.
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
mp_integer alignment(const typet &type, const namespacet &ns)
Definition padding.cpp:23
void add_padding(struct_typet &type, const namespacet &ns)
Definition padding.cpp:459
ANSI-C Language Type Checking.
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 pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
Pointer Logic.
bool simplify(exprt &expr, const namespacet &ns)
BigInt mp_integer
Definition smt_terms.h:17
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#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
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:721
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:424
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3078
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:787
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:307
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:517
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
Definition std_types.h:477
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:887
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:213
Author: Diffblue Ltd.
static std::string type2name(const typet &type, const namespacet &ns, symbol_numbert &symbol_number)
Definition type2name.cpp:82
Type Naming for C.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208
const typedef_typet & to_typedef_type(const typet &type)
Cast a generic typet to a typedef_typet.
#define size_type
Definition unistd.c:186
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition util.cpp:45