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 (C99) array as _last_ member!
1074 // Zero-length is allowed everywhere.
1075
1076 if(type.id()==ID_struct ||
1077 type.id()==ID_union)
1078 {
1079 for(struct_union_typet::componentst::iterator
1080 it=components.begin();
1081 it!=components.end();
1082 it++)
1083 {
1084 typet &c_type=it->type();
1085
1086 if(c_type.id()==ID_array &&
1087 to_array_type(c_type).is_incomplete())
1088 {
1089 // needs to be last member
1090 if(type.id()==ID_struct && it!=--components.end())
1091 {
1092 throw errort().with_location(it->source_location())
1093 << "flexible struct member must be last member";
1094 }
1095
1096 // make it zero-length
1099 }
1100 }
1101 }
1102
1103 // We may add some minimal padding inside and at
1104 // the end of structs and
1105 // as additional member for unions.
1106
1107 if(type.id()==ID_struct)
1108 add_padding(to_struct_type(type), *this);
1109 else if(type.id()==ID_union)
1110 add_padding(to_union_type(type), *this);
1111
1112 // finally, check _Static_assert inside the compound
1113 for(struct_union_typet::componentst::iterator
1114 it=components.begin();
1115 it!=components.end();
1116 ) // no it++
1117 {
1118 if(it->id()==ID_static_assert)
1119 {
1121 {
1122 throw errort().with_location(it->source_location())
1123 << "static_assert not supported in compound body";
1124 }
1125
1126 exprt &assertion = to_binary_expr(*it).op0();
1127 typecheck_expr(assertion);
1128 typecheck_expr(to_binary_expr(*it).op1());
1129 assertion = typecast_exprt(assertion, bool_typet());
1130 make_constant(assertion);
1131
1132 if(assertion.is_false())
1133 {
1134 throw errort().with_location(it->source_location())
1135 << "failed _Static_assert";
1136 }
1137 else if(!assertion.is_true())
1138 {
1139 // should warn/complain
1140 }
1141
1142 it=components.erase(it);
1143 }
1144 else
1145 it++;
1146 }
1147
1148 // Visual Studio strictly follows the C standard and does not permit empty
1149 // struct/union declarations
1150 if(
1151 components.empty() &&
1153 {
1154 throw errort().with_location(type.source_location())
1155 << "C requires that a struct or union has at least one member";
1156 }
1157}
1158
1160 const mp_integer &min_value,
1161 const mp_integer &max_value) const
1162{
1164 {
1165 return signed_int_type();
1166 }
1167 else
1168 {
1169 // enum constants are at least 'int', but may be made larger.
1170 // 'Packing' has no influence.
1171 if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
1172 min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
1173 return signed_int_type();
1174 else if(max_value<(mp_integer(1)<<config.ansi_c.int_width) &&
1175 min_value>=0)
1176 return unsigned_int_type();
1177 else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width) &&
1178 min_value>=0)
1179 return unsigned_long_int_type();
1180 else if(max_value<(mp_integer(1)<<config.ansi_c.long_long_int_width) &&
1181 min_value>=0)
1183 else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
1184 min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
1185 return signed_long_int_type();
1186 else
1188 }
1189}
1190
1192 const mp_integer &min_value,
1193 const mp_integer &max_value,
1194 bool is_packed) const
1195{
1197 {
1198 return signed_int_type();
1199 }
1200 else
1201 {
1202 if(min_value<0)
1203 {
1204 // We'll want a signed type.
1205
1206 if(is_packed)
1207 {
1208 // If packed, there are smaller options.
1209 if(max_value<(mp_integer(1)<<(config.ansi_c.char_width-1)) &&
1210 min_value>=-(mp_integer(1)<<(config.ansi_c.char_width-1)))
1211 return signed_char_type();
1212 else if(max_value<(mp_integer(1)<<(config.ansi_c.short_int_width-1)) &&
1213 min_value>=-(mp_integer(1)<<(config.ansi_c.short_int_width-1)))
1214 return signed_short_int_type();
1215 }
1216
1217 if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
1218 min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
1219 return signed_int_type();
1220 else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
1221 min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
1222 return signed_long_int_type();
1223 else
1225 }
1226 else
1227 {
1228 // We'll want an unsigned type.
1229
1230 if(is_packed)
1231 {
1232 // If packed, there are smaller options.
1233 if(max_value<(mp_integer(1)<<config.ansi_c.char_width))
1234 return unsigned_char_type();
1235 else if(max_value<(mp_integer(1)<<config.ansi_c.short_int_width))
1236 return unsigned_short_int_type();
1237 }
1238
1239 if(max_value<(mp_integer(1)<<config.ansi_c.int_width))
1240 return unsigned_int_type();
1241 else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width))
1242 return unsigned_long_int_type();
1243 else
1245 }
1246 }
1247}
1248
1250{
1251 // These come with the declarations
1252 // of the enum constants as operands.
1253
1254 exprt &as_expr=static_cast<exprt &>(static_cast<irept &>(type));
1255 source_locationt source_location=type.source_location();
1256
1257 // We allow empty enums in the grammar to get better
1258 // error messages.
1259 if(as_expr.operands().empty())
1260 {
1261 throw errort().with_location(source_location) << "empty enum";
1262 }
1263
1264 const bool have_underlying_type =
1265 type.find_type(ID_enum_underlying_type).is_not_nil();
1266
1268 {
1270
1271 const typet &underlying_type =
1272 static_cast<const typet &>(type.find(ID_enum_underlying_type));
1273
1274 if(!is_signed_or_unsigned_bitvector(underlying_type))
1275 {
1276 throw errort().with_location(source_location)
1277 << "non-integral type '" << underlying_type.get(ID_C_c_type)
1278 << "' is an invalid underlying type";
1279 }
1280 }
1281
1282 // enums start at zero;
1283 // we also track min and max to find a nice base type
1284 mp_integer value=0, min_value=0, max_value=0;
1285
1286 std::vector<c_enum_typet::c_enum_membert> enum_members;
1287 enum_members.reserve(as_expr.operands().size());
1288
1289 // We need to determine a width, and a signedness
1290 // to obtain an 'underlying type'.
1291 // We just do int, but gcc might pick smaller widths
1292 // if the type is marked as 'packed'.
1293 // gcc/clang may also pick a larger width. Visual Studio doesn't.
1294
1295 for(auto &op : as_expr.operands())
1296 {
1298 exprt &v=declaration.declarator().value();
1299
1300 if(v.is_not_nil()) // value given?
1301 {
1302 exprt tmp_v=v;
1305 simplify(tmp_v, *this);
1306 if(tmp_v.is_true())
1307 value=1;
1308 else if(tmp_v.is_false())
1309 value=0;
1310 else if(
1311 tmp_v.is_constant() && !to_integer(to_constant_expr(tmp_v), value))
1312 {
1313 }
1314 else
1315 {
1317 << "enum is not a constant";
1318 }
1319 }
1320
1321 if(value<min_value)
1322 min_value=value;
1323 if(value>max_value)
1324 max_value=value;
1325
1327
1329 {
1332
1333 if(value < tmp.smallest() || value > tmp.largest())
1334 {
1336 << "enumerator value is not representable in the underlying type '"
1337 << constant_type.get(ID_C_c_type) << "'";
1338 }
1339 }
1340 else
1341 {
1342 constant_type = enum_constant_type(min_value, max_value);
1343 }
1344
1345 v=from_integer(value, constant_type);
1346
1347 declaration.type()=constant_type;
1348 typecheck_declaration(declaration);
1349
1350 irep_idt base_name=
1351 declaration.declarator().get_base_name();
1352
1353 irep_idt identifier=
1354 declaration.declarator().get_name();
1355
1356 // store
1358 member.set_identifier(identifier);
1359 member.set_base_name(base_name);
1360 // Note: The value will be correctly set to a bv type when we know
1361 // the width of the bitvector
1362 member.set_value(integer2string(value));
1363 enum_members.push_back(member);
1364
1365 // produce value for next constant
1366 ++value;
1367 }
1368
1369 // Remove these now; we add them to the
1370 // c_enum symbol later.
1371 as_expr.operands().clear();
1372
1373 bool is_packed=type.get_bool(ID_C_packed);
1374
1375 // We use a subtype to store the underlying type.
1376 bitvector_typet underlying_type(ID_nil);
1377
1379 {
1380 underlying_type =
1382 }
1383 else
1384 {
1385 underlying_type = enum_underlying_type(min_value, max_value, is_packed);
1386 }
1387
1388 // Get the width to make the values have a bitvector type
1389 std::size_t width = underlying_type.get_width();
1390 for(auto &member : enum_members)
1391 {
1392 // Note: This is inefficient as it first turns integers to strings
1393 // and then turns them back to bvrep
1394 auto value = string2integer(id2string(member.get_value()));
1395 member.set_value(integer2bvrep(value, width));
1396 }
1397
1398 // tag?
1399 if(type.find(ID_tag).is_nil())
1400 {
1401 // None, it's anonymous. We generate a tag.
1402 std::string anon_identifier="#anon_enum";
1403
1404 for(const auto &member : enum_members)
1405 {
1406 anon_identifier+='$';
1407 anon_identifier+=id2string(member.get_base_name());
1408 anon_identifier+='=';
1409 anon_identifier+=id2string(member.get_value());
1410 }
1411
1412 if(is_packed)
1413 anon_identifier+="#packed";
1414
1416 }
1417
1418 irept &tag=type.add(ID_tag);
1419 irep_idt base_name=tag.get(ID_C_base_name);
1420 irep_idt identifier=tag.get(ID_identifier);
1421
1422 // Put into symbol table
1423 type_symbolt enum_tag_symbol{identifier, type, mode};
1424 enum_tag_symbol.location=source_location;
1425 enum_tag_symbol.is_file_local=true;
1426 enum_tag_symbol.base_name=base_name;
1427
1428 enum_tag_symbol.type.add_subtype() = underlying_type;
1429
1430 // throw in the enum members as 'body'
1431 to_c_enum_type(enum_tag_symbol.type).members() = std::move(enum_members);
1432
1433 // is it in the symbol table already?
1435
1436 if(existing_symbol)
1437 {
1438 // Yes.
1439 const symbolt &symbol = *existing_symbol;
1440
1441 if(symbol.type.id() != ID_c_enum)
1442 {
1443 throw errort().with_location(source_location)
1444 << "use of tag that does not match previous declaration";
1445 }
1446
1447 if(to_c_enum_type(symbol.type).is_incomplete())
1448 {
1449 // Ok, overwrite the type in the symbol table.
1450 // This gives us the members and the subtype.
1451 existing_symbol->type = enum_tag_symbol.type;
1452 }
1453 else
1454 {
1455 // We might already have the same anonymous enum, and this is
1456 // simply ok. Note that the C standard treats these as
1457 // different types.
1458 if(!base_name.empty())
1459 {
1460 throw errort().with_location(type.source_location())
1461 << "redeclaration of enum tag";
1462 }
1463 }
1464 }
1465 else
1466 {
1467 symbolt *new_symbol;
1468 move_symbol(enum_tag_symbol, new_symbol);
1469 }
1470
1471 // We produce a c_enum_tag as the resulting type.
1472 type.id(ID_c_enum_tag);
1473 type.remove(ID_tag);
1474 type.set(ID_identifier, identifier);
1475}
1476
1478{
1479 // It's just a tag.
1480
1481 if(type.find(ID_tag).is_nil())
1482 {
1483 throw errort().with_location(type.source_location())
1484 << "anonymous enum tag without members";
1485 }
1486
1487 if(type.find(ID_enum_underlying_type).is_not_nil())
1488 {
1490 warning() << "ignoring specification of underlying type for enum" << eom;
1491 }
1492
1493 source_locationt source_location=type.source_location();
1494
1495 irept &tag=type.add(ID_tag);
1496 irep_idt base_name=tag.get(ID_C_base_name);
1497 irep_idt identifier=tag.get(ID_identifier);
1498
1499 // is it in the symbol table?
1500 symbol_table_baset::symbolst::const_iterator s_it =
1501 symbol_table.symbols.find(identifier);
1502
1503 if(s_it!=symbol_table.symbols.end())
1504 {
1505 // Yes.
1506 const symbolt &symbol=s_it->second;
1507
1508 if(symbol.type.id() != ID_c_enum)
1509 {
1510 throw errort().with_location(source_location)
1511 << "use of tag that does not match previous declaration";
1512 }
1513 }
1514 else
1515 {
1516 // no, add it as an incomplete c_enum
1517 c_enum_typet new_type(signed_int_type()); // default subtype
1518 new_type.add(ID_tag)=tag;
1519 new_type.make_incomplete();
1520
1522 enum_tag_symbol.location=source_location;
1523 enum_tag_symbol.is_file_local=true;
1524 enum_tag_symbol.base_name=base_name;
1525
1526 symbolt *new_symbol;
1527 move_symbol(enum_tag_symbol, new_symbol);
1528 }
1529
1530 // Clean up resulting type
1531 type.remove(ID_tag);
1532 type.set_identifier(identifier);
1533}
1534
1536{
1538
1539 mp_integer i;
1540
1541 {
1542 exprt &width_expr=static_cast<exprt &>(type.add(ID_size));
1543
1546
1548 {
1549 throw errort().with_location(type.source_location())
1550 << "failed to convert bit field width";
1551 }
1552
1553 if(i<0)
1554 {
1555 throw errort().with_location(type.source_location())
1556 << "bit field width is negative";
1557 }
1558
1559 type.width(i);
1560 type.remove(ID_size);
1561 }
1562
1563 const typet &underlying_type = type.underlying_type();
1564
1565 std::size_t sub_width=0;
1566
1567 if(underlying_type.id() == ID_bool)
1568 {
1569 // This is the 'proper' bool.
1570 sub_width=1;
1571 }
1572 else if(
1573 underlying_type.id() == ID_signedbv ||
1574 underlying_type.id() == ID_unsignedbv || underlying_type.id() == ID_c_bool)
1575 {
1576 sub_width = to_bitvector_type(underlying_type).get_width();
1577 }
1578 else if(underlying_type.id() == ID_c_enum_tag)
1579 {
1580 // These point to an enum, which has a sub-subtype,
1581 // which may be smaller or larger than int, and we thus have
1582 // to check.
1583 const auto &c_enum_type =
1584 to_c_enum_type(follow_tag(to_c_enum_tag_type(underlying_type)));
1585
1586 if(c_enum_type.is_incomplete())
1587 {
1588 throw errort().with_location(type.source_location())
1589 << "bit field has incomplete enum type";
1590 }
1591
1592 sub_width = to_bitvector_type(c_enum_type.underlying_type()).get_width();
1593 }
1594 else
1595 {
1596 throw errort().with_location(type.source_location())
1597 << "bit field with non-integer type: " << to_string(underlying_type);
1598 }
1599
1600 if(i>sub_width)
1601 {
1602 throw errort().with_location(type.source_location())
1603 << "bit field (" << i << " bits) larger than type (" << sub_width
1604 << " bits)";
1605 }
1606}
1607
1609{
1610 // save location
1611 source_locationt source_location=type.source_location();
1612
1613 // retain the qualifiers as is
1614 c_qualifierst c_qualifiers;
1615 c_qualifiers.read(type);
1616
1617 const auto &as_expr = (const exprt &)type;
1618
1619 if(!as_expr.has_operands())
1620 {
1621 typet t=static_cast<const typet &>(type.find(ID_type_arg));
1622 typecheck_type(t);
1623 type.swap(t);
1624 }
1625 else
1626 {
1627 exprt expr = to_unary_expr(as_expr).op();
1628 typecheck_expr(expr);
1629
1630 // undo an implicit address-of
1631 if(expr.id()==ID_address_of &&
1632 expr.get_bool(ID_C_implicit))
1633 {
1634 expr = to_address_of_expr(expr).object();
1635 }
1636
1637 type.swap(expr.type());
1638 }
1639
1640 type.add_source_location()=source_location;
1641 c_qualifiers.write(type);
1642}
1643
1645{
1646 const irep_idt &identifier = to_typedef_type(type).get_identifier();
1647
1648 symbol_table_baset::symbolst::const_iterator s_it =
1649 symbol_table.symbols.find(identifier);
1650
1651 if(s_it == symbol_table.symbols.end())
1652 {
1653 throw errort().with_location(type.source_location())
1654 << "typedef symbol '" << identifier << "' not found";
1655 }
1656
1657 const symbolt &symbol = s_it->second;
1658
1659 if(!symbol.is_type)
1660 {
1661 throw errort().with_location(type.source_location())
1662 << "expected type symbol for typedef";
1663 }
1664
1665 // overwrite, but preserve (add) any qualifiers and other flags
1666
1667 c_qualifierst c_qualifiers(type);
1668 bool is_packed = type.get_bool(ID_C_packed);
1670
1671 c_qualifiers += c_qualifierst(symbol.type);
1672 type = symbol.type;
1673 c_qualifiers.write(type);
1674
1675 if(is_packed)
1676 type.set(ID_C_packed, true);
1677 if(alignment.is_not_nil())
1679
1680 // CPROVER extensions
1681 if(symbol.base_name == CPROVER_PREFIX "rational")
1682 {
1683 type=rational_typet();
1684 }
1685 else if(symbol.base_name == CPROVER_PREFIX "integer")
1686 {
1687 type=integer_typet();
1688 }
1689}
1690
1692{
1693 if(type.id()==ID_array)
1694 {
1695 source_locationt source_location=type.source_location();
1696 type = pointer_type(to_array_type(type).element_type());
1697 type.add_source_location()=source_location;
1698 }
1699 else if(type.id()==ID_code)
1700 {
1701 // see ISO/IEC 9899:1999 page 199 clause 8,
1702 // may be hidden in typedef
1703 source_locationt source_location=type.source_location();
1704 type=pointer_type(type);
1705 type.add_source_location()=source_location;
1706 }
1707 else if(type.id()==ID_KnR)
1708 {
1709 // any KnR args without type yet?
1710 type=signed_int_type(); // the default is integer!
1711 // no source location
1712 }
1713}
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:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
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:807
bool is_complete() const
Definition std_types.h:852
const exprt & size() const
Definition std_types.h:840
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:827
typet & index_type_nonconst()
The type of the index expressions into any instance of this type.
Definition std_types.h:821
Base class of fixed-width bit-vector types.
Definition std_types.h:909
std::size_t get_width() const
Definition std_types.h:925
std::size_t width() const
The Boolean type.
Definition std_types.h:36
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:583
std::vector< parametert > parameterst
Definition std_types.h:586
const parameterst & parameters() const
Definition std_types.h:699
const typet & return_type() const
Definition std_types.h:689
void make_ellipsis()
Definition std_types.h:679
Complex numbers made of pair of given subtype.
Definition std_types.h:1133
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:89
Base class for all expressions.
Definition expr.h:56
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:147
bool is_true() const
Return whether the expression is a constant representing true.
Definition expr.cpp:27
bool is_false() const
Return whether the expression is a constant representing false.
Definition expr.cpp:34
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
const source_locationt & source_location() const
Definition expr.h:231
source_locationt & add_source_location()
Definition expr.h:236
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:396
mstreamt & result() const
Definition message.h:401
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
Unbounded, signed rational numbers.
A struct tag type, i.e., struct_typet with an identifier.
Definition std_types.h:493
Base type for structs and unions.
Definition std_types.h:62
const componentst & components() const
Definition std_types.h:147
std::vector< componentt > componentst
Definition std_types.h:140
Expression to hold a symbol (variable)
Definition std_expr.h:131
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:405
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:2073
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2081
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:1064
#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:715
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3173
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
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