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 // GCC and Clang ignore anything other than an untagged struct or
990 // union; we could print a warning, but there isn't any ambiguity in
991 // semantics here. Printing a warning could elevate this to an error
992 // when compiling code with goto-cc with -Werror.
993 // Note that our type checking always creates a struct_tag/union_tag
994 // type, but only named struct/union types have an ID_tag member.
995 if(
996 new_component.type().id() == ID_struct_tag &&
998 .find(ID_tag)
999 .is_nil())
1000 {
1001 // ok, anonymous struct
1002 }
1003 else if(
1004 new_component.type().id() == ID_union_tag &&
1006 .find(ID_tag)
1007 .is_nil())
1008 {
1009 // ok, anonymous union
1010 }
1011 else
1012 {
1013 continue;
1014 }
1015 }
1016 }
1017
1018 if(!is_complete_type(new_component.type()) &&
1019 (new_component.type().id()!=ID_array ||
1020 !to_array_type(new_component.type()).is_incomplete()))
1021 {
1022 throw errort().with_location(source_location)
1023 << "incomplete type not permitted here";
1024 }
1025
1026 if(new_component.type().id() == ID_empty)
1027 {
1028 throw errort().with_location(source_location)
1029 << "void-typed member not permitted";
1030 }
1031
1032 if(
1033 new_component.type().id() == ID_c_bit_field &&
1034 to_c_bit_field_type(new_component.type()).get_width() == 0 &&
1035 !new_component.get_name().empty())
1036 {
1037 throw errort().with_location(source_location)
1038 << "zero-width bit-field with declarator not permitted";
1039 }
1040
1041 components.push_back(new_component);
1042 }
1043 }
1044 }
1045
1046 unsigned anon_member_counter=0;
1047
1048 // scan for anonymous members, and name them
1049 for(auto &member : components)
1050 {
1051 if(!member.get_name().empty())
1052 continue;
1053
1054 member.set_name("$anon"+std::to_string(anon_member_counter++));
1055 member.set_anonymous(true);
1056 }
1057
1058 // scan for duplicate members
1059
1060 {
1061 std::unordered_set<irep_idt> members;
1062
1063 for(const auto &c : components)
1064 {
1065 if(!members.insert(c.get_name()).second)
1066 {
1067 throw errort().with_location(c.source_location())
1068 << "duplicate member '" << c.get_name() << '\'';
1069 }
1070 }
1071 }
1072
1073 // We allow an incomplete array as _last_ member of a struct,
1074 // C11 6.7.2.1 §18. These are called "flexible array members".
1075 // Zero-length (a gcc extension) is allowed everywhere.
1076 // Flexible array members are not allowed in unions in ISO C, but we allow
1077 // them as an extension on Windows.
1078 if(type.id() == ID_struct || type.id() == ID_union)
1079 {
1080 for(struct_union_typet::componentst::iterator it = components.begin();
1081 it != components.end();
1082 it++)
1083 {
1084 typet &component_type = it->type();
1085
1086 if(
1087 component_type.id() != ID_array ||
1088 !to_array_type(component_type).is_incomplete())
1089 {
1090 continue;
1091 }
1092
1093 if(type.id() == ID_struct)
1094 {
1095 // needs to be last member
1096 if(it != --components.end())
1097 {
1098 throw errort().with_location(it->source_location())
1099 << "flexible struct member must be last member";
1100 }
1101 }
1103 {
1104 throw errort().with_location(it->source_location())
1105 << "flexible array members in a union are a Microsoft "
1106 "extension, and not permitted in ISO C";
1107 }
1108
1109 // make it zero-length
1110 to_array_type(component_type).size() = from_integer(0, c_index_type());
1111 component_type.set(ID_C_flexible_array_member, true);
1112 }
1113 }
1114
1115 // We may add some minimal padding inside and at
1116 // the end of structs and
1117 // as additional member for unions.
1118
1119 if(type.id()==ID_struct)
1120 add_padding(to_struct_type(type), *this);
1121 else if(type.id()==ID_union)
1122 add_padding(to_union_type(type), *this);
1123
1124 // finally, check _Static_assert inside the compound
1125 for(struct_union_typet::componentst::iterator
1126 it=components.begin();
1127 it!=components.end();
1128 ) // no it++
1129 {
1130 if(it->id()==ID_static_assert)
1131 {
1133 {
1134 throw errort().with_location(it->source_location())
1135 << "static_assert not supported in compound body";
1136 }
1137
1138 exprt &assertion = to_binary_expr(*it).op0();
1139 typecheck_expr(assertion);
1140 typecheck_expr(to_binary_expr(*it).op1());
1141 assertion = typecast_exprt(assertion, bool_typet());
1142 make_constant(assertion);
1143
1144 if(assertion == false)
1145 {
1146 throw errort().with_location(it->source_location())
1147 << "failed _Static_assert";
1148 }
1149 else if(assertion != true)
1150 {
1151 // should warn/complain
1152 }
1153
1154 it=components.erase(it);
1155 }
1156 else
1157 it++;
1158 }
1159
1160 // Visual Studio strictly follows the C standard and does not permit empty
1161 // struct/union declarations
1162 if(
1163 components.empty() &&
1165 {
1166 throw errort().with_location(type.source_location())
1167 << "C requires that a struct or union has at least one member";
1168 }
1169}
1170
1172 const mp_integer &min_value,
1173 const mp_integer &max_value) const
1174{
1176 {
1177 return signed_int_type();
1178 }
1179 else
1180 {
1181 // enum constants are at least 'int', but may be made larger.
1182 // 'Packing' has no influence.
1183 if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
1184 min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
1185 return signed_int_type();
1186 else if(max_value<(mp_integer(1)<<config.ansi_c.int_width) &&
1187 min_value>=0)
1188 return unsigned_int_type();
1189 else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width) &&
1190 min_value>=0)
1191 return unsigned_long_int_type();
1192 else if(max_value<(mp_integer(1)<<config.ansi_c.long_long_int_width) &&
1193 min_value>=0)
1195 else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
1196 min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
1197 return signed_long_int_type();
1198 else
1200 }
1201}
1202
1204 const mp_integer &min_value,
1205 const mp_integer &max_value,
1206 bool is_packed) const
1207{
1209 {
1210 return signed_int_type();
1211 }
1212 else
1213 {
1214 if(min_value<0)
1215 {
1216 // We'll want a signed type.
1217
1218 if(is_packed)
1219 {
1220 // If packed, there are smaller options.
1221 if(max_value<(mp_integer(1)<<(config.ansi_c.char_width-1)) &&
1222 min_value>=-(mp_integer(1)<<(config.ansi_c.char_width-1)))
1223 return signed_char_type();
1224 else if(max_value<(mp_integer(1)<<(config.ansi_c.short_int_width-1)) &&
1225 min_value>=-(mp_integer(1)<<(config.ansi_c.short_int_width-1)))
1226 return signed_short_int_type();
1227 }
1228
1229 if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
1230 min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
1231 return signed_int_type();
1232 else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
1233 min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
1234 return signed_long_int_type();
1235 else
1237 }
1238 else
1239 {
1240 // We'll want an unsigned type.
1241
1242 if(is_packed)
1243 {
1244 // If packed, there are smaller options.
1245 if(max_value<(mp_integer(1)<<config.ansi_c.char_width))
1246 return unsigned_char_type();
1247 else if(max_value<(mp_integer(1)<<config.ansi_c.short_int_width))
1248 return unsigned_short_int_type();
1249 }
1250
1251 if(max_value<(mp_integer(1)<<config.ansi_c.int_width))
1252 return unsigned_int_type();
1253 else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width))
1254 return unsigned_long_int_type();
1255 else
1257 }
1258 }
1259}
1260
1262{
1263 // These come with the declarations
1264 // of the enum constants as operands.
1265
1266 exprt &as_expr=static_cast<exprt &>(static_cast<irept &>(type));
1267 source_locationt source_location=type.source_location();
1268
1269 // We allow empty enums in the grammar to get better
1270 // error messages.
1271 if(as_expr.operands().empty())
1272 {
1273 throw errort().with_location(source_location) << "empty enum";
1274 }
1275
1276 const bool have_underlying_type =
1277 type.find_type(ID_enum_underlying_type).is_not_nil();
1278
1280 {
1282
1283 const typet &underlying_type =
1284 static_cast<const typet &>(type.find(ID_enum_underlying_type));
1285
1286 if(!is_signed_or_unsigned_bitvector(underlying_type))
1287 {
1288 throw errort().with_location(source_location)
1289 << "non-integral type '" << underlying_type.get(ID_C_c_type)
1290 << "' is an invalid underlying type";
1291 }
1292 }
1293
1294 // enums start at zero;
1295 // we also track min and max to find a nice base type
1296 mp_integer value=0, min_value=0, max_value=0;
1297
1298 std::vector<c_enum_typet::c_enum_membert> enum_members;
1299 enum_members.reserve(as_expr.operands().size());
1300
1301 // We need to determine a width, and a signedness
1302 // to obtain an 'underlying type'.
1303 // We just do int, but gcc might pick smaller widths
1304 // if the type is marked as 'packed'.
1305 // gcc/clang may also pick a larger width. Visual Studio doesn't.
1306
1307 for(auto &op : as_expr.operands())
1308 {
1310 exprt &v=declaration.declarator().value();
1311
1312 if(v.is_not_nil()) // value given?
1313 {
1314 exprt tmp_v=v;
1317 simplify(tmp_v, *this);
1318 if(tmp_v == true)
1319 value=1;
1320 else if(tmp_v == false)
1321 value=0;
1322 else if(
1323 tmp_v.is_constant() && !to_integer(to_constant_expr(tmp_v), value))
1324 {
1325 }
1326 else
1327 {
1329 << "enum is not a constant";
1330 }
1331 }
1332
1333 if(value<min_value)
1334 min_value=value;
1335 if(value>max_value)
1336 max_value=value;
1337
1339
1341 {
1344
1345 if(value < tmp.smallest() || value > tmp.largest())
1346 {
1348 << "enumerator value is not representable in the underlying type '"
1349 << constant_type.get(ID_C_c_type) << "'";
1350 }
1351 }
1352 else
1353 {
1354 constant_type = enum_constant_type(min_value, max_value);
1355 }
1356
1357 v=from_integer(value, constant_type);
1358
1359 declaration.type()=constant_type;
1360 typecheck_declaration(declaration);
1361
1362 irep_idt base_name=
1363 declaration.declarator().get_base_name();
1364
1365 irep_idt identifier=
1366 declaration.declarator().get_name();
1367
1368 // store
1370 member.set_identifier(identifier);
1371 member.set_base_name(base_name);
1372 // Note: The value will be correctly set to a bv type when we know
1373 // the width of the bitvector
1374 member.set_value(integer2string(value));
1375 enum_members.push_back(member);
1376
1377 // produce value for next constant
1378 ++value;
1379 }
1380
1381 // Remove these now; we add them to the
1382 // c_enum symbol later.
1383 as_expr.operands().clear();
1384
1385 bool is_packed=type.get_bool(ID_C_packed);
1386
1387 // We use a subtype to store the underlying type.
1388 bitvector_typet underlying_type(ID_nil);
1389
1391 {
1392 underlying_type =
1394 }
1395 else
1396 {
1397 underlying_type = enum_underlying_type(min_value, max_value, is_packed);
1398 }
1399
1400 // Get the width to make the values have a bitvector type
1401 std::size_t width = underlying_type.get_width();
1402 for(auto &member : enum_members)
1403 {
1404 // Note: This is inefficient as it first turns integers to strings
1405 // and then turns them back to bvrep
1406 auto value = string2integer(id2string(member.get_value()));
1407 member.set_value(integer2bvrep(value, width));
1408 }
1409
1410 // tag?
1411 if(type.find(ID_tag).is_nil())
1412 {
1413 // None, it's anonymous. We generate a tag.
1414 std::string anon_identifier="#anon_enum";
1415
1416 for(const auto &member : enum_members)
1417 {
1418 anon_identifier+='$';
1419 anon_identifier+=id2string(member.get_base_name());
1420 anon_identifier+='=';
1421 anon_identifier+=id2string(member.get_value());
1422 }
1423
1424 if(is_packed)
1425 anon_identifier+="#packed";
1426
1428 }
1429
1430 irept &tag=type.add(ID_tag);
1431 irep_idt base_name=tag.get(ID_C_base_name);
1432 irep_idt identifier=tag.get(ID_identifier);
1433
1434 // Put into symbol table
1435 type_symbolt enum_tag_symbol{identifier, type, mode};
1436 enum_tag_symbol.location=source_location;
1437 enum_tag_symbol.is_file_local=true;
1438 enum_tag_symbol.base_name=base_name;
1439
1440 enum_tag_symbol.type.add_subtype() = underlying_type;
1441
1442 // throw in the enum members as 'body'
1443 to_c_enum_type(enum_tag_symbol.type).members() = std::move(enum_members);
1444
1445 // is it in the symbol table already?
1447
1448 if(existing_symbol)
1449 {
1450 // Yes.
1451 const symbolt &symbol = *existing_symbol;
1452
1453 if(symbol.type.id() != ID_c_enum)
1454 {
1455 throw errort().with_location(source_location)
1456 << "use of tag that does not match previous declaration";
1457 }
1458
1459 if(to_c_enum_type(symbol.type).is_incomplete())
1460 {
1461 // Ok, overwrite the type in the symbol table.
1462 // This gives us the members and the subtype.
1463 existing_symbol->type = enum_tag_symbol.type;
1464 }
1465 else
1466 {
1467 // We might already have the same anonymous enum, and this is
1468 // simply ok. Note that the C standard treats these as
1469 // different types.
1470 if(!base_name.empty())
1471 {
1472 throw errort().with_location(type.source_location())
1473 << "redeclaration of enum tag";
1474 }
1475 }
1476 }
1477 else
1478 {
1479 symbolt *new_symbol;
1480 move_symbol(enum_tag_symbol, new_symbol);
1481 }
1482
1483 // We produce a c_enum_tag as the resulting type.
1484 type.id(ID_c_enum_tag);
1485 type.remove(ID_tag);
1486 type.set(ID_identifier, identifier);
1487}
1488
1490{
1491 // It's just a tag.
1492
1493 if(type.find(ID_tag).is_nil())
1494 {
1495 throw errort().with_location(type.source_location())
1496 << "anonymous enum tag without members";
1497 }
1498
1499 if(type.find(ID_enum_underlying_type).is_not_nil())
1500 {
1502 warning() << "ignoring specification of underlying type for enum" << eom;
1503 }
1504
1505 source_locationt source_location=type.source_location();
1506
1507 irept &tag=type.add(ID_tag);
1508 irep_idt base_name=tag.get(ID_C_base_name);
1509 irep_idt identifier=tag.get(ID_identifier);
1510
1511 // is it in the symbol table?
1512 symbol_table_baset::symbolst::const_iterator s_it =
1513 symbol_table.symbols.find(identifier);
1514
1515 if(s_it!=symbol_table.symbols.end())
1516 {
1517 // Yes.
1518 const symbolt &symbol=s_it->second;
1519
1520 if(symbol.type.id() != ID_c_enum)
1521 {
1522 throw errort().with_location(source_location)
1523 << "use of tag that does not match previous declaration";
1524 }
1525 }
1526 else
1527 {
1528 // no, add it as an incomplete c_enum
1529 c_enum_typet new_type(signed_int_type()); // default subtype
1530 new_type.add(ID_tag)=tag;
1531 new_type.make_incomplete();
1532
1534 enum_tag_symbol.location=source_location;
1535 enum_tag_symbol.is_file_local=true;
1536 enum_tag_symbol.base_name=base_name;
1537
1538 symbolt *new_symbol;
1539 move_symbol(enum_tag_symbol, new_symbol);
1540 }
1541
1542 // Clean up resulting type
1543 type.remove(ID_tag);
1544 type.set_identifier(identifier);
1545}
1546
1548{
1550
1551 mp_integer i;
1552
1553 {
1554 exprt &width_expr=static_cast<exprt &>(type.add(ID_size));
1555
1558
1560 {
1561 throw errort().with_location(type.source_location())
1562 << "failed to convert bit field width";
1563 }
1564
1565 if(i<0)
1566 {
1567 throw errort().with_location(type.source_location())
1568 << "bit field width is negative";
1569 }
1570
1571 type.width(i);
1572 type.remove(ID_size);
1573 }
1574
1575 const typet &underlying_type = type.underlying_type();
1576
1577 std::size_t sub_width=0;
1578
1579 if(underlying_type.id() == ID_bool)
1580 {
1581 // This is the 'proper' bool.
1582 sub_width=1;
1583 }
1584 else if(
1585 underlying_type.id() == ID_signedbv ||
1586 underlying_type.id() == ID_unsignedbv || underlying_type.id() == ID_c_bool)
1587 {
1588 sub_width = to_bitvector_type(underlying_type).get_width();
1589 }
1590 else if(underlying_type.id() == ID_c_enum_tag)
1591 {
1592 // These point to an enum, which has a sub-subtype,
1593 // which may be smaller or larger than int, and we thus have
1594 // to check.
1595 const auto &c_enum_type =
1596 to_c_enum_type(follow_tag(to_c_enum_tag_type(underlying_type)));
1597
1598 if(c_enum_type.is_incomplete())
1599 {
1600 throw errort().with_location(type.source_location())
1601 << "bit field has incomplete enum type";
1602 }
1603
1604 sub_width = to_bitvector_type(c_enum_type.underlying_type()).get_width();
1605 }
1606 else
1607 {
1608 throw errort().with_location(type.source_location())
1609 << "bit field with non-integer type: " << to_string(underlying_type);
1610 }
1611
1612 if(i>sub_width)
1613 {
1614 throw errort().with_location(type.source_location())
1615 << "bit field (" << i << " bits) larger than type (" << sub_width
1616 << " bits)";
1617 }
1618}
1619
1621{
1622 // save location
1623 source_locationt source_location=type.source_location();
1624
1625 // retain the qualifiers as is
1626 c_qualifierst c_qualifiers;
1627 c_qualifiers.read(type);
1628
1629 const auto &as_expr = (const exprt &)type;
1630
1631 if(!as_expr.has_operands())
1632 {
1633 typet t=static_cast<const typet &>(type.find(ID_type_arg));
1634 typecheck_type(t);
1635 type.swap(t);
1636 }
1637 else
1638 {
1639 exprt expr = to_unary_expr(as_expr).op();
1640 typecheck_expr(expr);
1641
1642 // undo an implicit address-of
1643 if(expr.id()==ID_address_of &&
1644 expr.get_bool(ID_C_implicit))
1645 {
1646 expr = to_address_of_expr(expr).object();
1647 }
1648
1649 type.swap(expr.type());
1650 }
1651
1652 type.add_source_location()=source_location;
1653 c_qualifiers.write(type);
1654}
1655
1657{
1658 const irep_idt &identifier = to_typedef_type(type).get_identifier();
1659
1660 symbol_table_baset::symbolst::const_iterator s_it =
1661 symbol_table.symbols.find(identifier);
1662
1663 if(s_it == symbol_table.symbols.end())
1664 {
1665 throw errort().with_location(type.source_location())
1666 << "typedef symbol '" << identifier << "' not found";
1667 }
1668
1669 const symbolt &symbol = s_it->second;
1670
1671 if(!symbol.is_type)
1672 {
1673 throw errort().with_location(type.source_location())
1674 << "expected type symbol for typedef";
1675 }
1676
1677 // overwrite, but preserve (add) any qualifiers and other flags
1678
1679 c_qualifierst c_qualifiers(type);
1680 bool is_packed = type.get_bool(ID_C_packed);
1682
1683 c_qualifiers += c_qualifierst(symbol.type);
1684 type = symbol.type;
1685 c_qualifiers.write(type);
1686
1687 if(is_packed)
1688 type.set(ID_C_packed, true);
1689 if(alignment.is_not_nil())
1691
1692 // CPROVER extensions
1693 if(symbol.base_name == CPROVER_PREFIX "rational")
1694 {
1695 type=rational_typet();
1696 }
1697 else if(symbol.base_name == CPROVER_PREFIX "integer")
1698 {
1699 type=integer_typet();
1700 }
1701 else if(symbol.base_name == CPROVER_PREFIX "natural")
1702 {
1703 type = natural_typet();
1704 }
1705 else if(symbol.base_name == CPROVER_PREFIX "real")
1706 {
1707 type = real_typet();
1708 }
1709}
1710
1712{
1713 if(type.id()==ID_array)
1714 {
1715 source_locationt source_location=type.source_location();
1716 type = pointer_type(to_array_type(type).element_type());
1717 type.add_source_location()=source_location;
1718 }
1719 else if(type.id()==ID_code)
1720 {
1721 // see ISO/IEC 9899:1999 page 199 clause 8,
1722 // may be hidden in typedef
1723 source_locationt source_location=type.source_location();
1724 type=pointer_type(type);
1725 type.add_source_location()=source_location;
1726 }
1727 else if(type.id()==ID_KnR)
1728 {
1729 // any KnR args without type yet?
1730 type=signed_int_type(); // the default is integer!
1731 // no source location
1732 }
1733}
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 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