cprover
Loading...
Searching...
No Matches
cpp_typecheck_conversions.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: C++ Language Type Checking
4
5Author:
6
7\*******************************************************************/
8
11
12#include "cpp_typecheck.h"
13
14#include <util/arith_tools.h>
15#include <util/c_types.h>
16#include <util/config.h>
17#include <util/expr_util.h>
18#include <util/pointer_expr.h>
19#include <util/simplify_expr.h>
20#include <util/std_expr.h>
21
22#include <ansi-c/c_qualifiers.h>
23
24#include "cpp_util.h"
25
47 const exprt &expr,
48 exprt &new_expr) const
49{
50 assert(expr.get_bool(ID_C_lvalue));
51
52 if(expr.type().id() == ID_code)
53 return false;
54
55 if(
56 expr.type().id() == ID_struct &&
58 return false;
59
60 if(expr.type().id() == ID_union && to_union_type(expr.type()).is_incomplete())
61 return false;
62
63 new_expr=expr;
64 new_expr.remove(ID_C_lvalue);
65
66 return true;
67}
68
78 const exprt &expr,
79 exprt &new_expr) const
80{
81 assert(expr.type().id()==ID_array);
82
83 index_exprt index(expr, from_integer(0, c_index_type()));
84
85 index.set(ID_C_lvalue, true);
86
87 new_expr=address_of_exprt(index);
88
89 return true;
90}
91
100 const exprt &expr, exprt &new_expr) const
101{
102 if(!expr.get_bool(ID_C_lvalue))
103 return false;
104
105 new_expr=address_of_exprt(expr);
106
107 return true;
108}
109
116 const exprt &expr,
117 const typet &type,
118 exprt &new_expr) const
119{
120 if(expr.type().id()!=ID_pointer ||
121 is_reference(expr.type()))
122 return false;
123
124 if(expr.get_bool(ID_C_lvalue))
125 return false;
126
127 if(expr.type()!=type)
128 return false;
129
130 typet sub_from = to_pointer_type(expr.type()).base_type();
131 typet sub_to = to_pointer_type(type).base_type();
132 bool const_to=true;
133
134 while(sub_from.id()==ID_pointer)
135 {
136 c_qualifierst qual_from(sub_from);
137 c_qualifierst qual_to(sub_to);
138
139 if(!qual_to.is_constant)
140 const_to=false;
141
142 if(qual_from.is_constant && !qual_to.is_constant)
143 return false;
144
145 if(qual_from!=qual_to && !const_to)
146 return false;
147
148 typet tmp1=sub_from.subtype();
149 sub_from.swap(tmp1);
150
151 typet tmp2=sub_to.subtype();
152 sub_to.swap(tmp2);
153 }
154
155 c_qualifierst qual_from(sub_from);
156 c_qualifierst qual_to(sub_to);
157
158 if(qual_from.is_subset_of(qual_to))
159 {
160 new_expr=expr;
161 new_expr.type()=type;
162 return true;
163 }
164
165 return false;
166}
167
194 const exprt &expr,
195 exprt &new_expr) const
196{
197 if(expr.get_bool(ID_C_lvalue))
198 return false;
199
200 c_qualifierst qual_from;
201 qual_from.read(expr.type());
202
203 typet int_type=signed_int_type();
204 qual_from.write(int_type);
205
206 if(expr.type().id()==ID_signedbv)
207 {
208 std::size_t width=to_signedbv_type(expr.type()).get_width();
209 if(width >= config.ansi_c.int_width)
210 return false;
211 new_expr = typecast_exprt(expr, int_type);
212 return true;
213 }
214
215 if(expr.type().id()==ID_unsignedbv)
216 {
217 std::size_t width=to_unsignedbv_type(expr.type()).get_width();
218 if(width >= config.ansi_c.int_width)
219 return false;
220 new_expr = typecast_exprt(expr, int_type);
221 return true;
222 }
223
224 if(expr.type().id() == ID_bool || expr.type().id() == ID_c_bool)
225 {
226 new_expr = typecast_exprt(expr, int_type);
227 return true;
228 }
229
230 if(expr.type().id()==ID_c_enum_tag)
231 {
232 new_expr = typecast_exprt(expr, int_type);
233 return true;
234 }
235
236 return false;
237}
238
247 const exprt &expr,
248 exprt &new_expr) const
249{
250 if(expr.get_bool(ID_C_lvalue))
251 return false;
252
253 // we only do that with 'float',
254 // not with 'double' or 'long double'
255 if(expr.type()!=float_type())
256 return false;
257
258 std::size_t width=to_floatbv_type(expr.type()).get_width();
259
260 if(width!=config.ansi_c.single_width)
261 return false;
262
263 c_qualifierst qual_from;
264 qual_from.read(expr.type());
265
266 new_expr = typecast_exprt(expr, double_type());
267 qual_from.write(new_expr.type());
268
269 return true;
270}
271
301 const exprt &expr,
302 const typet &type,
303 exprt &new_expr) const
304{
305 if(type.id()!=ID_signedbv &&
306 type.id()!=ID_unsignedbv)
307 return false;
308
309 if(
310 expr.type().id() != ID_signedbv && expr.type().id() != ID_unsignedbv &&
311 expr.type().id() != ID_c_bool && expr.type().id() != ID_bool &&
312 expr.type().id() != ID_c_enum_tag)
313 {
314 return false;
315 }
316
317 if(expr.get_bool(ID_C_lvalue))
318 return false;
319
320 c_qualifierst qual_from;
321 qual_from.read(expr.type());
322 new_expr = typecast_exprt::conditional_cast(expr, type);
323 qual_from.write(new_expr.type());
324
325 return true;
326}
327
348 const exprt &expr,
349 const typet &type,
350 exprt &new_expr) const
351{
352 if(expr.get_bool(ID_C_lvalue))
353 return false;
354
355 if(expr.type().id()==ID_floatbv ||
356 expr.type().id()==ID_fixedbv)
357 {
358 if(type.id()!=ID_signedbv &&
359 type.id()!=ID_unsignedbv)
360 return false;
361 }
362 else if(expr.type().id()==ID_signedbv ||
363 expr.type().id()==ID_unsignedbv ||
364 expr.type().id()==ID_c_enum_tag)
365 {
366 if(type.id()!=ID_fixedbv &&
367 type.id()!=ID_floatbv)
368 return false;
369 }
370 else
371 return false;
372
373 c_qualifierst qual_from;
374 qual_from.read(expr.type());
375 new_expr = typecast_exprt::conditional_cast(expr, type);
376 qual_from.write(new_expr.type());
377
378 return true;
379}
380
381
399 const exprt &expr,
400 const typet &type,
401 exprt &new_expr) const
402{
403 if(expr.type().id()!=ID_floatbv &&
404 expr.type().id()!=ID_fixedbv)
405 return false;
406
407 if(type.id()!=ID_floatbv &&
408 type.id()!=ID_fixedbv)
409 return false;
410
411 if(expr.get_bool(ID_C_lvalue))
412 return false;
413
414 c_qualifierst qual_from;
415
416 qual_from.read(expr.type());
417 new_expr = typecast_exprt::conditional_cast(expr, type);
418 qual_from.write(new_expr.type());
419
420 return true;
421}
422
456 const exprt &expr,
457 const typet &type,
458 exprt &new_expr)
459{
460 if(type.id()!=ID_pointer ||
461 is_reference(type))
462 return false;
463
464 if(expr.get_bool(ID_C_lvalue))
465 return false;
466
467 // integer 0 to NULL pointer conversion?
468 if(simplify_expr(expr, *this).is_zero() &&
469 expr.type().id()!=ID_pointer)
470 {
471 new_expr=expr;
472 new_expr.set(ID_value, ID_NULL);
473 new_expr.type()=type;
474 return true;
475 }
476
477 if(type.find(ID_to_member).is_not_nil())
478 return false;
479
480 if(
481 expr.type().id() != ID_pointer ||
482 expr.type().find(ID_to_member).is_not_nil())
483 {
484 return false;
485 }
486
487 typet sub_from = follow(to_pointer_type(expr.type()).base_type());
488 typet sub_to = follow(to_pointer_type(type).base_type());
489
490 // std::nullptr_t to _any_ pointer type
491 if(sub_from.id()==ID_nullptr)
492 return true;
493
494 // anything but function pointer to void *
495 if(sub_from.id()!=ID_code && sub_to.id()==ID_empty)
496 {
497 c_qualifierst qual_from;
498 qual_from.read(to_pointer_type(expr.type()).base_type());
499 new_expr = typecast_exprt::conditional_cast(expr, type);
500 qual_from.write(new_expr.type().subtype());
501 return true;
502 }
503
504 // struct * to struct *
505 if(sub_from.id()==ID_struct && sub_to.id()==ID_struct)
506 {
507 const struct_typet &from_struct=to_struct_type(sub_from);
508 const struct_typet &to_struct=to_struct_type(sub_to);
509 if(subtype_typecast(from_struct, to_struct))
510 {
511 c_qualifierst qual_from;
512 qual_from.read(to_pointer_type(expr.type()).base_type());
513 new_expr=expr;
514 make_ptr_typecast(new_expr, type);
515 qual_from.write(new_expr.type().subtype());
516 return true;
517 }
518 }
519
520 return false;
521}
522
554 const exprt &expr,
555 const typet &type,
556 exprt &new_expr)
557{
558 if(
559 type.id() != ID_pointer || is_reference(type) ||
560 type.find(ID_to_member).is_nil())
561 {
562 return false;
563 }
564
565 if(expr.type().id() != ID_pointer || expr.type().find(ID_to_member).is_nil())
566 return false;
567
568 if(
569 to_pointer_type(type).base_type() !=
571 {
572 // base types are different
573 if(
574 to_pointer_type(type).base_type().id() == ID_code &&
575 to_pointer_type(expr.type()).base_type().id() == ID_code)
576 {
577 code_typet code1=to_code_type(expr.type().subtype());
578 assert(!code1.parameters().empty());
579 code_typet::parametert this1=code1.parameters()[0];
580 INVARIANT(this1.get_this(), "first parameter should be `this'");
581 code1.parameters().erase(code1.parameters().begin());
582
583 code_typet code2=to_code_type(type.subtype());
584 assert(!code2.parameters().empty());
585 code_typet::parametert this2=code2.parameters()[0];
586 INVARIANT(this2.get_this(), "first parameter should be `this'");
587 code2.parameters().erase(code2.parameters().begin());
588
589 if(this2.type().subtype().get_bool(ID_C_constant) &&
590 !this1.type().subtype().get_bool(ID_C_constant))
591 return false;
592
593 // give a second chance ignoring `this'
594 if(code1!=code2)
595 return false;
596 }
597 else
598 return false;
599 }
600
601 if(expr.get_bool(ID_C_lvalue))
602 return false;
603
604 if(expr.id()==ID_constant &&
605 expr.get(ID_value)==ID_NULL)
606 {
607 new_expr = typecast_exprt::conditional_cast(expr, type);
608 return true;
609 }
610
611 const struct_typet &from_struct = to_struct_type(
612 follow(static_cast<const typet &>(expr.type().find(ID_to_member))));
613
614 const struct_typet &to_struct =
615 to_struct_type(follow(static_cast<const typet &>(type.find(ID_to_member))));
616
617 if(subtype_typecast(to_struct, from_struct))
618 {
619 new_expr = typecast_exprt::conditional_cast(expr, type);
620 return true;
621 }
622
623 return false;
624}
625
636 const exprt &expr, exprt &new_expr) const
637{
638 if(expr.get_bool(ID_C_lvalue))
639 return false;
640
641 if(
642 expr.type().id() != ID_signedbv && expr.type().id() != ID_unsignedbv &&
643 expr.type().id() != ID_pointer && expr.type().id() != ID_bool &&
644 expr.type().id() != ID_c_enum_tag)
645 {
646 return false;
647 }
648
649 c_qualifierst qual_from;
650 qual_from.read(expr.type());
651
652 typet Bool = c_bool_type();
653 qual_from.write(Bool);
654
655 new_expr = typecast_exprt::conditional_cast(expr, Bool);
656 return true;
657}
658
680 const exprt &expr,
681 const typet &type,
682 exprt &new_expr,
683 unsigned &rank)
684{
685 assert(!is_reference(expr.type()) && !is_reference(type));
686
687 exprt curr_expr=expr;
688
689 // bit fields are converted like their underlying type
690 if(type.id()==ID_c_bit_field)
691 return standard_conversion_sequence(expr, type.subtype(), new_expr, rank);
692
693 // we turn bit fields into their underlying type
694 if(curr_expr.type().id()==ID_c_bit_field)
695 curr_expr = typecast_exprt(curr_expr, curr_expr.type().subtype());
696
697 if(curr_expr.type().id()==ID_array)
698 {
699 if(type.id()==ID_pointer)
700 {
701 if(!standard_conversion_array_to_pointer(curr_expr, new_expr))
702 return false;
703 }
704 }
705 else if(curr_expr.type().id()==ID_code &&
706 type.id()==ID_pointer)
707 {
708 if(!standard_conversion_function_to_pointer(curr_expr, new_expr))
709 return false;
710 }
711 else if(curr_expr.get_bool(ID_C_lvalue))
712 {
713 if(!standard_conversion_lvalue_to_rvalue(curr_expr, new_expr))
714 return false;
715 }
716 else
717 new_expr=curr_expr;
718
719 curr_expr.swap(new_expr);
720
721 // two enums are the same if the tag is the same,
722 // even if the width differs (enum bit-fields!)
723 if(follow(type).id()==ID_c_enum &&
724 follow(curr_expr.type()).id()==ID_c_enum)
725 {
726 if(follow(type).find(ID_tag)==
727 follow(curr_expr.type()).find(ID_tag))
728 return true;
729 else
730 {
731 // In contrast to C, we simply don't allow implicit conversions
732 // between enums.
733 return false;
734 }
735 }
736
737 // need to consider #c_type
738 if(follow(curr_expr.type())!=follow(type) ||
739 curr_expr.type().get(ID_C_c_type)!=type.get(ID_C_c_type))
740 {
741 if(type.id()==ID_signedbv ||
742 type.id()==ID_unsignedbv ||
743 follow(type).id()==ID_c_enum)
744 {
745 if(!standard_conversion_integral_promotion(curr_expr, new_expr) ||
746 new_expr.type() != type)
747 {
748 if(!standard_conversion_integral_conversion(curr_expr, type, new_expr))
749 {
751 curr_expr, type, new_expr))
752 return false;
753 }
754
755 rank+=3;
756 }
757 else
758 rank+=2;
759 }
760 else if(type.id()==ID_floatbv || type.id()==ID_fixedbv)
761 {
762 if(!standard_conversion_floating_point_promotion(curr_expr, new_expr) ||
763 new_expr.type() != type)
764 {
766 curr_expr, type, new_expr) &&
768 curr_expr, type, new_expr))
769 return false;
770
771 rank += 3;
772 }
773 else
774 rank += 2;
775 }
776 else if(type.id()==ID_pointer)
777 {
778 if(expr.type().subtype().id()==ID_nullptr)
779 {
780 // std::nullptr_t to _any_ pointer type is ok
781 new_expr = typecast_exprt::conditional_cast(new_expr, type);
782 }
783 else if(!standard_conversion_pointer(curr_expr, type, new_expr))
784 {
785 if(!standard_conversion_pointer_to_member(curr_expr, type, new_expr))
786 return false;
787 }
788
789 rank += 3;
790 }
791 else if(type.id() == ID_c_bool)
792 {
793 if(!standard_conversion_boolean(curr_expr, new_expr))
794 return false;
795
796 rank += 3;
797 }
798 else if(type.id() == ID_bool)
799 {
800 new_expr = is_not_zero(curr_expr, *this);
801
802 rank += 3;
803 }
804 else
805 return false;
806 }
807 else
808 new_expr=curr_expr;
809
810 curr_expr.swap(new_expr);
811
812 if(curr_expr.type().id()==ID_pointer)
813 {
814 typet sub_from=curr_expr.type();
815 typet sub_to=type;
816
817 do
818 {
819 typet tmp_from=sub_from.subtype();
820 sub_from.swap(tmp_from);
821 typet tmp_to=sub_to.subtype();
822 sub_to.swap(tmp_to);
823
824 c_qualifierst qual_from;
825 qual_from.read(sub_from);
826
827 c_qualifierst qual_to;
828 qual_to.read(sub_to);
829
830 if(qual_from!=qual_to)
831 {
832 rank+=1;
833 break;
834 }
835 }
836 while(sub_from.id()==ID_pointer);
837
838 if(!standard_conversion_qualification(curr_expr, type, new_expr))
839 return false;
840 }
841 else
842 {
843 new_expr=curr_expr;
844 new_expr.type()=type;
845 }
846
847 return true;
848}
849
856 const exprt &expr,
857 const typet &type,
858 exprt &new_expr,
859 unsigned &rank)
860{
861 assert(!is_reference(expr.type()));
862 assert(!is_reference(type));
863
864 const typet &from=follow(expr.type());
865 const typet &to=follow(type);
866
867 new_expr.make_nil();
868
869 // special case:
870 // A conversion from a type to the same type is given an exact
871 // match rank even though a user-defined conversion is used
872
873 if(from==to)
874 rank+=0;
875 else
876 rank+=4; // higher than all the standard conversions
877
878 if(to.id()==ID_struct)
879 {
880 std::string err_msg;
881
882 if(cpp_is_pod(to))
883 {
884 if(from.id()==ID_struct)
885 {
886 const struct_typet &from_struct=to_struct_type(from);
887 const struct_typet &to_struct=to_struct_type(to);
888
889 // potentially requires
890 // expr.get_bool(ID_C_lvalue) ??
891
892 if(subtype_typecast(from_struct, to_struct))
893 {
894 exprt address=address_of_exprt(expr);
895
896 // simplify address
897 if(expr.id()==ID_dereference)
898 address = to_dereference_expr(expr).pointer();
899
900 pointer_typet ptr_sub=pointer_type(type);
901 c_qualifierst qual_from;
902 qual_from.read(expr.type());
903 qual_from.write(ptr_sub.base_type());
904 make_ptr_typecast(address, ptr_sub);
905
906 const dereference_exprt deref(address);
907
908 // create temporary object
909 side_effect_exprt tmp_object_expr(
910 ID_temporary_object, type, expr.source_location());
911 tmp_object_expr.copy_to_operands(deref);
912 tmp_object_expr.set(ID_C_lvalue, true);
913 tmp_object_expr.set(ID_mode, ID_cpp);
914
915 new_expr.swap(tmp_object_expr);
916 return true;
917 }
918 }
919 }
920 else
921 {
922 bool found=false;
923
924 for(const auto &component : to_struct_type(to).components())
925 {
926 if(component.get_bool(ID_from_base))
927 continue;
928
929 if(component.get_bool(ID_is_explicit))
930 continue;
931
932 const typet &comp_type = component.type();
933
934 if(comp_type.id() !=ID_code)
935 continue;
936
937 if(to_code_type(comp_type).return_type().id() != ID_constructor)
938 continue;
939
940 // TODO: ellipsis
941
942 const auto &parameters = to_code_type(comp_type).parameters();
943
944 if(parameters.size() != 2)
945 continue;
946
947 exprt curr_arg1 = parameters[1];
948 typet arg1_type=curr_arg1.type();
949
950 if(is_reference(arg1_type))
951 {
952 typet tmp=arg1_type.subtype();
953 arg1_type.swap(tmp);
954 }
955
956 unsigned tmp_rank=0;
957 if(arg1_type.id() != ID_struct_tag)
958 {
959 exprt tmp_expr;
961 expr, arg1_type, tmp_expr, tmp_rank))
962 {
963 // check if it's ambiguous
964 if(found)
965 return false;
966 found=true;
967
968 if(expr.get_bool(ID_C_lvalue))
969 tmp_expr.set(ID_C_lvalue, true);
970
971 tmp_expr.add_source_location()=expr.source_location();
972
973 exprt func_symb = cpp_symbol_expr(lookup(component.get_name()));
974 func_symb.type()=comp_type;
976
977 // create temporary object
979 std::move(func_symb),
980 {tmp_expr},
982 expr.source_location());
984
985 new_expr.swap(ctor_expr);
986 assert(new_expr.get(ID_statement)==ID_temporary_object);
987
988 if(to.get_bool(ID_C_constant))
989 new_expr.type().set(ID_C_constant, true);
990
991 rank += tmp_rank;
992 }
993 }
994 else if(from.id() == ID_struct && arg1_type.id() == ID_struct_tag)
995 {
996 // try derived-to-base conversion
997 address_of_exprt expr_pfrom(expr, pointer_type(expr.type()));
998 pointer_typet pto=pointer_type(arg1_type);
999
1000 exprt expr_ptmp;
1001 tmp_rank=0;
1003 expr_pfrom, pto, expr_ptmp, tmp_rank))
1004 {
1005 // check if it's ambiguous
1006 if(found)
1007 return false;
1008 found=true;
1009
1010 rank+=tmp_rank;
1011
1012 // create temporary object
1013 dereference_exprt expr_deref(expr_ptmp);
1014 expr_deref.set(ID_C_lvalue, true);
1015 expr_deref.add_source_location()=expr.source_location();
1016
1017 exprt new_object(ID_new_object, type);
1018 new_object.set(ID_C_lvalue, true);
1019 new_object.type().set(ID_C_constant, false);
1020
1021 exprt func_symb = cpp_symbol_expr(lookup(component.get_name()));
1022 func_symb.type()=comp_type;
1024
1026 std::move(func_symb),
1027 {expr_deref},
1029 expr.source_location());
1031
1032 new_expr.swap(ctor_expr);
1033
1034 INVARIANT(
1035 new_expr.get(ID_statement)==ID_temporary_object,
1036 "statement ID");
1037
1038 if(to.get_bool(ID_C_constant))
1039 new_expr.type().set(ID_C_constant, true);
1040 }
1041 }
1042 }
1043 if(found)
1044 return true;
1045 }
1046 }
1047
1048 // conversion operators
1049 if(from.id()==ID_struct)
1050 {
1051 bool found=false;
1052 for(const auto &component : to_struct_type(from).components())
1053 {
1054 if(component.get_bool(ID_from_base))
1055 continue;
1056
1057 if(!component.get_bool(ID_is_cast_operator))
1058 continue;
1059
1060 const code_typet &comp_type = to_code_type(component.type());
1062 comp_type.parameters().size() == 1, "expected exactly one parameter");
1063
1064 typet this_type = comp_type.parameters().front().type();
1065 this_type.set(ID_C_reference, true);
1066
1067 exprt this_expr(expr);
1068 this_type.set(ID_C_this, true);
1069
1070 unsigned tmp_rank=0;
1071 exprt tmp_expr;
1072
1074 this_expr, this_type, tmp_expr, tmp_rank))
1075 {
1076 // To take care of the possible virtual case,
1077 // we build the function as a member expression.
1078 const cpp_namet cpp_func_name(component.get_base_name());
1079
1080 exprt member_func(ID_member);
1081 member_func.add(ID_component_cpp_name)=cpp_func_name;
1083
1085 std::move(member_func),
1086 {},
1088 expr.source_location());
1090
1091 if(standard_conversion_sequence(func_expr, type, tmp_expr, tmp_rank))
1092 {
1093 // check if it's ambiguous
1094 if(found)
1095 return false;
1096 found=true;
1097
1098 rank+=tmp_rank;
1099 new_expr.swap(tmp_expr);
1100 }
1101 }
1102 }
1103 if(found)
1104 return true;
1105 }
1106
1107 return new_expr.is_not_nil();
1108}
1109
1115 const exprt &expr,
1116 const typet &type) const
1117{
1118 assert(is_reference(type));
1119 assert(!is_reference(expr.type()));
1120
1121 typet from=follow(expr.type());
1122 typet to=follow(type.subtype());
1123
1124 // need to check #c_type
1125 if(from.get(ID_C_c_type)!=to.get(ID_C_c_type))
1126 return false;
1127
1128 if(from==to)
1129 return true;
1130
1131 if(from.id()==ID_struct &&
1132 to.id()==ID_struct)
1133 return subtype_typecast(to_struct_type(from),
1134 to_struct_type(to));
1135
1136 if(from.id()==ID_struct &&
1137 type.get_bool(ID_C_this) &&
1138 type.subtype().id()==ID_empty)
1139 {
1140 // virtual-call case
1141 return true;
1142 }
1143
1144 return false;
1145}
1146
1152 const exprt &expr,
1153 const typet &type,
1154 unsigned &rank) const
1155{
1156 assert(is_reference(type));
1157 assert(!is_reference(expr.type()));
1158
1159 if(!reference_related(expr, type))
1160 return false;
1161
1162 if(expr.type()!=type.subtype())
1163 rank+=3;
1164
1165 c_qualifierst qual_from;
1166 qual_from.read(expr.type());
1167
1168 c_qualifierst qual_to;
1169 qual_to.read(type.subtype());
1170
1171 if(qual_from!=qual_to)
1172 rank+=1;
1173
1174 if(qual_from.is_subset_of(qual_to))
1175 return true;
1176
1177 return false;
1178}
1179
1215 exprt expr,
1216 const typet &type,
1217 exprt &new_expr,
1218 unsigned &rank)
1219{
1220 assert(is_reference(type));
1221 assert(!is_reference(expr.type()));
1222
1223 unsigned backup_rank=rank;
1224
1225 if(type.get_bool(ID_C_this) &&
1226 !expr.get_bool(ID_C_lvalue))
1227 {
1228 // `this' has to be an lvalue
1229 if(expr.get(ID_statement)==ID_temporary_object)
1230 expr.set(ID_C_lvalue, true);
1231 else if(expr.get(ID_statement)==ID_function_call)
1232 expr.set(ID_C_lvalue, true);
1233 else if(expr.get_bool(ID_C_temporary_avoided))
1234 {
1235 expr.remove(ID_C_temporary_avoided);
1236 exprt temporary;
1237 new_temporary(expr.source_location(), expr.type(), expr, temporary);
1238 expr.swap(temporary);
1239 expr.set(ID_C_lvalue, true);
1240 }
1241 else
1242 return false;
1243 }
1244
1245 if(
1246 expr.get_bool(ID_C_lvalue) ||
1247 to_reference_type(type).base_type().get_bool(ID_C_constant))
1248 {
1249 if(reference_compatible(expr, type, rank))
1250 {
1251 if(!expr.get_bool(ID_C_lvalue))
1252 {
1253 // create temporary object
1254 side_effect_exprt tmp{ID_temporary_object,
1255 {std::move(expr)},
1257 expr.source_location()};
1258 tmp.set(ID_mode, ID_cpp);
1259 expr.swap(tmp);
1260 }
1261
1262 {
1263 address_of_exprt tmp(expr, reference_type(expr.type()));
1265 new_expr.swap(tmp);
1266 }
1267
1268 if(expr.type()!=type.subtype())
1269 {
1270 c_qualifierst qual_from;
1271 qual_from.read(expr.type());
1272 new_expr = typecast_exprt::conditional_cast(new_expr, type);
1273 qual_from.write(new_expr.type().subtype());
1274 }
1275
1276 return true;
1277 }
1278
1279 rank=backup_rank;
1280 }
1281
1282 // conversion operators
1283 const typet &from_type = follow(expr.type());
1284 if(from_type.id()==ID_struct)
1285 {
1286 for(const auto &component : to_struct_type(from_type).components())
1287 {
1288 if(component.get_bool(ID_from_base))
1289 continue;
1290
1291 if(!component.get_bool(ID_is_cast_operator))
1292 continue;
1293
1294 const code_typet &component_type = to_code_type(component.type());
1295
1296 // otherwise it cannot bind directly (not an lvalue)
1297 if(!is_reference(component_type.return_type()))
1298 continue;
1299
1300 assert(component_type.parameters().size()==1);
1301
1302 typet this_type =
1303 component_type.parameters().front().type();
1304 this_type.set(ID_C_reference, true);
1305
1306 exprt this_expr(expr);
1307
1308 this_type.set(ID_C_this, true);
1309
1310 unsigned tmp_rank=0;
1311
1312 exprt tmp_expr;
1314 this_expr, this_type, tmp_expr, tmp_rank))
1315 {
1316 // To take care of the possible virtual case,
1317 // we build the function as a member expression.
1318 const cpp_namet cpp_func_name(component.get_base_name());
1319
1320 exprt member_func(ID_member);
1321 member_func.add(ID_component_cpp_name)=cpp_func_name;
1323
1325 std::move(member_func),
1326 {},
1328 expr.source_location());
1330
1331 // let's check if the returned value binds directly
1332 exprt returned_value=func_expr;
1333 add_implicit_dereference(returned_value);
1334
1335 if(returned_value.get_bool(ID_C_lvalue) &&
1336 reference_compatible(returned_value, type, rank))
1337 {
1338 // returned values are lvalues in case of references only
1340 is_reference(to_dereference_expr(returned_value).op().type()),
1341 "the returned value must be pointer to reference");
1342
1343 new_expr = to_multi_ary_expr(returned_value).op0();
1344
1345 if(returned_value.type() != type.subtype())
1346 {
1347 c_qualifierst qual_from;
1348 qual_from.read(returned_value.type());
1349 make_ptr_typecast(new_expr, type);
1350 qual_from.write(new_expr.type().subtype());
1351 }
1352 rank+=4+tmp_rank;
1353 return true;
1354 }
1355 }
1356 }
1357 }
1358
1359 // No temporary allowed for `this'
1360 if(type.get_bool(ID_C_this))
1361 return false;
1362
1363 if(!type.subtype().get_bool(ID_C_constant) ||
1364 type.subtype().get_bool(ID_C_volatile))
1365 return false;
1366
1367 // TODO: handle the case for implicit parameters
1368 if(!type.subtype().get_bool(ID_C_constant) &&
1369 !expr.get_bool(ID_C_lvalue))
1370 return false;
1371
1372 exprt arg_expr=expr;
1373
1374 if(arg_expr.type().id() == ID_struct_tag)
1375 {
1376 // required to initialize the temporary
1377 arg_expr.set(ID_C_lvalue, true);
1378 }
1379
1380 if(user_defined_conversion_sequence(arg_expr, type.subtype(), new_expr, rank))
1381 {
1382 address_of_exprt tmp(new_expr, reference_type(new_expr.type()));
1383 tmp.add_source_location()=new_expr.source_location();
1384 new_expr.swap(tmp);
1385 return true;
1386 }
1387
1388 rank=backup_rank;
1389 if(standard_conversion_sequence(expr, type.subtype(), new_expr, rank))
1390 {
1391 {
1392 // create temporary object
1394 ID_temporary_object, type.subtype(), expr.source_location());
1395 tmp.set(ID_mode, ID_cpp);
1396 // tmp.set(ID_C_lvalue, true);
1397 tmp.add_to_operands(std::move(new_expr));
1398 new_expr.swap(tmp);
1399 }
1400
1401 address_of_exprt tmp(new_expr, pointer_type(new_expr.type()));
1402 tmp.type().set(ID_C_reference, true);
1403 tmp.add_source_location()=new_expr.source_location();
1404
1405 new_expr=tmp;
1406 return true;
1407 }
1408
1409 return false;
1410}
1411
1419 const exprt &expr,
1420 const typet &type,
1421 exprt &new_expr,
1422 unsigned &rank)
1423{
1424 unsigned backup_rank=rank;
1425
1426 exprt e=expr;
1428
1429 if(is_reference(type))
1430 {
1431 if(!reference_binding(e, type, new_expr, rank))
1432 return false;
1433
1434 #if 0
1435 simplify_exprt simplify(*this);
1436 simplify.simplify(new_expr);
1437 new_expr.type().set(ID_C_reference, true);
1438 #endif
1439 }
1440 else if(!standard_conversion_sequence(e, type, new_expr, rank))
1441 {
1442 rank=backup_rank;
1443 if(!user_defined_conversion_sequence(e, type, new_expr, rank))
1444 return false;
1445
1446 #if 0
1447 simplify_exprt simplify(*this);
1448 simplify.simplify(new_expr);
1449 #endif
1450 }
1451
1452 return true;
1453}
1454
1461 const exprt &expr,
1462 const typet &type,
1463 exprt &new_expr)
1464{
1465 unsigned rank=0;
1466 return implicit_conversion_sequence(expr, type, new_expr, rank);
1467}
1468
1475 const exprt &expr,
1476 const typet &type,
1477 unsigned &rank)
1478{
1479 exprt new_expr;
1480 return implicit_conversion_sequence(expr, type, new_expr, rank);
1481}
1482
1484{
1485 exprt e=expr;
1486
1487 if(
1488 e.id() == ID_initializer_list && cpp_is_pod(type) &&
1489 e.operands().size() == 1)
1490 {
1491 e = to_unary_expr(expr).op();
1492 }
1493
1494 if(!implicit_conversion_sequence(e, type, expr))
1495 {
1498 error() << "invalid implicit conversion from '" << to_string(e.type())
1499 << "' to '" << to_string(type) << "'" << eom;
1500#if 0
1501 str << "\n " << follow(e.type()).pretty() << '\n';
1502 str << "\n " << type.pretty() << '\n';
1503#endif
1504 throw 0;
1505 }
1506}
1507
1551 exprt &expr,
1552 const typet &type)
1553{
1554 assert(is_reference(type));
1556
1557 unsigned rank=0;
1558 exprt new_expr;
1559 if(reference_binding(expr, type, new_expr, rank))
1560 {
1561 expr.swap(new_expr);
1562 return;
1563 }
1564
1566 error() << "bad reference initializer" << eom;
1567 throw 0;
1568}
1569
1571 const typet &t1,
1572 const typet &t2) const
1573{
1574 assert(t1.id()==ID_pointer && t2.id()==ID_pointer);
1575 typet nt1=t1;
1576 typet nt2=t2;
1577
1578 if(is_reference(nt1))
1579 nt1.remove(ID_C_reference);
1580 nt1.remove(ID_to_member);
1581
1582 if(is_reference(nt2))
1583 nt2.remove(ID_C_reference);
1584 nt2.remove(ID_to_member);
1585
1586 // substitute final subtypes
1587 std::vector<typet> snt1;
1588 snt1.push_back(nt1);
1589
1590 while(snt1.back().has_subtype())
1591 {
1592 snt1.reserve(snt1.size()+1);
1593 snt1.push_back(snt1.back().subtype());
1594 }
1595
1596 c_qualifierst q1;
1597 q1.read(snt1.back());
1598
1599 bool_typet newnt1;
1600 q1.write(newnt1);
1601 snt1.back()=newnt1;
1602
1603 std::vector<typet> snt2;
1604 snt2.push_back(nt2);
1605 while(snt2.back().has_subtype())
1606 {
1607 snt2.reserve(snt2.size()+1);
1608 snt2.push_back(snt2.back().subtype());
1609 }
1610
1611 c_qualifierst q2;
1612 q2.read(snt2.back());
1613
1614 bool_typet newnt2;
1615 q2.write(newnt2);
1616 snt2.back()=newnt2;
1617
1618 const std::size_t k=snt1.size() < snt2.size() ? snt1.size() : snt2.size();
1619
1620 for(std::size_t i=k; i > 1; i--)
1621 {
1622 snt1[snt1.size()-2].subtype()=snt1[snt1.size()-1];
1623 snt1.pop_back();
1624
1625 snt2[snt2.size()-2].subtype()=snt2[snt2.size()-1];
1626 snt2.pop_back();
1627 }
1628
1629 exprt e1("Dummy", snt1.back());
1630 exprt e2;
1631
1632 return !standard_conversion_qualification(e1, snt2.back(), e2);
1633}
1634
1636 const exprt &expr,
1637 const typet &type,
1638 exprt &new_expr)
1639{
1640 PRECONDITION(!is_reference(expr.type()));
1641
1642 exprt curr_expr=expr;
1643
1644 if(curr_expr.type().id()==ID_array)
1645 {
1646 if(type.id()==ID_pointer)
1647 {
1648 if(!standard_conversion_array_to_pointer(curr_expr, new_expr))
1649 return false;
1650 }
1651 }
1652 else if(curr_expr.type().id()==ID_code &&
1653 type.id()==ID_pointer)
1654 {
1655 if(!standard_conversion_function_to_pointer(curr_expr, new_expr))
1656 return false;
1657 }
1658 else if(curr_expr.get_bool(ID_C_lvalue))
1659 {
1660 if(!standard_conversion_lvalue_to_rvalue(curr_expr, new_expr))
1661 return false;
1662 }
1663 else
1664 new_expr=curr_expr;
1665
1666 if(is_reference(type))
1667 {
1668 if(!expr.get_bool(ID_C_lvalue))
1669 return false;
1670
1671 if(new_expr.type()!=type.subtype())
1672 return false;
1673
1674 address_of_exprt address_of(expr, to_pointer_type(type));
1675 add_implicit_dereference(address_of);
1676 new_expr=address_of;
1677 return true;
1678 }
1679 else if(type.id()==ID_pointer)
1680 {
1681 if(type!=new_expr.type())
1682 return false;
1683
1684 // add proper typecast
1685 typecast_exprt typecast_expr(expr, type);
1686 new_expr.swap(typecast_expr);
1687 return true;
1688 }
1689
1690 return false;
1691}
1692
1694 const exprt &expr,
1695 const typet &type,
1696 exprt &new_expr)
1697{
1698 exprt e(expr);
1699
1700 if(type.id()==ID_pointer)
1701 {
1702 if(e.id()==ID_dereference && e.get_bool(ID_C_implicit))
1703 e = to_dereference_expr(expr).pointer();
1704
1705 if(e.type().id()==ID_pointer &&
1706 cast_away_constness(e.type(), type))
1707 return false;
1708 }
1709
1711
1712 if(is_reference(type))
1713 {
1714 if(type.subtype().id() != ID_struct_tag)
1715 return false;
1716 }
1717 else if(type.id()==ID_pointer)
1718 {
1719 if(type.find(ID_to_member).is_not_nil())
1720 return false;
1721
1722 if(type.subtype().id()==ID_empty)
1723 {
1724 if(!e.get_bool(ID_C_lvalue))
1725 return false;
1726 UNREACHABLE; // currently not supported
1727 }
1728 else if(type.subtype().id() == ID_struct_tag)
1729 {
1730 if(e.get_bool(ID_C_lvalue))
1731 {
1732 exprt tmp(e);
1733
1735 return false;
1736 }
1737 }
1738 else return false;
1739 }
1740 else return false;
1741
1742 return static_typecast(e, type, new_expr);
1743}
1744
1746 const exprt &expr,
1747 const typet &type,
1748 exprt &new_expr,
1749 bool check_constantness)
1750{
1751 exprt e=expr;
1752
1753 if(check_constantness && type.id()==ID_pointer)
1754 {
1755 if(e.id()==ID_dereference && e.get_bool(ID_C_implicit))
1756 e = to_dereference_expr(expr).pointer();
1757
1758 if(e.type().id()==ID_pointer &&
1759 cast_away_constness(e.type(), type))
1760 return false;
1761 }
1762
1764
1765 if(!is_reference(type))
1766 {
1767 exprt tmp;
1768
1769 if(e.id()==ID_code)
1770 {
1772 e.swap(tmp);
1773 else
1774 return false;
1775 }
1776
1777 if(e.type().id()==ID_array)
1778 {
1780 e.swap(tmp);
1781 else
1782 return false;
1783 }
1784
1785 if(e.get_bool(ID_C_lvalue))
1786 {
1788 e.swap(tmp);
1789 else
1790 return false;
1791 }
1792 }
1793
1794 if(e.type().id()==ID_pointer &&
1795 (type.id()==ID_unsignedbv || type.id()==ID_signedbv))
1796 {
1797 // pointer to integer, always ok
1798 new_expr = typecast_exprt::conditional_cast(e, type);
1799 return true;
1800 }
1801
1802 if(
1803 (e.type().id() == ID_unsignedbv || e.type().id() == ID_signedbv ||
1804 e.type().id() == ID_c_bool || e.type().id() == ID_bool) &&
1805 type.id() == ID_pointer && !is_reference(type))
1806 {
1807 // integer to pointer
1808 if(simplify_expr(e, *this).is_zero())
1809 {
1810 // NULL
1811 new_expr=e;
1812 new_expr.set(ID_value, ID_NULL);
1813 new_expr.type()=type;
1814 }
1815 else
1816 {
1817 new_expr = typecast_exprt::conditional_cast(e, type);
1818 }
1819 return true;
1820 }
1821
1822 if(e.type().id()==ID_pointer &&
1823 type.id()==ID_pointer &&
1824 !is_reference(type))
1825 {
1826 // pointer to pointer: we ok it all.
1827 // This is more generous than the standard.
1828 new_expr = typecast_exprt::conditional_cast(expr, type);
1829 return true;
1830 }
1831
1832 if(is_reference(type) && e.get_bool(ID_C_lvalue))
1833 {
1835 return true;
1836 }
1837
1838 return false;
1839}
1840
1842 const exprt &expr, // source expression
1843 const typet &type, // destination type
1844 exprt &new_expr,
1845 bool check_constantness)
1846{
1847 exprt e=expr;
1848
1849 if(check_constantness && type.id()==ID_pointer)
1850 {
1851 if(e.id()==ID_dereference && e.get_bool(ID_C_implicit))
1852 e = to_dereference_expr(expr).pointer();
1853
1854 if(e.type().id()==ID_pointer &&
1855 cast_away_constness(e.type(), type))
1856 return false;
1857 }
1858
1860
1861 if(type.get_bool(ID_C_reference))
1862 {
1863 unsigned rank=0;
1864 if(reference_binding(e, type, new_expr, rank))
1865 return true;
1866
1867 typet subto=follow(type.subtype());
1868 typet from=follow(e.type());
1869
1870 if(subto.id()==ID_struct && from.id()==ID_struct)
1871 {
1872 if(!expr.get_bool(ID_C_lvalue))
1873 return false;
1874
1875 c_qualifierst qual_from;
1876 qual_from.read(e.type());
1877
1878 c_qualifierst qual_to;
1879 qual_to.read(type.subtype());
1880
1881 if(!qual_to.is_subset_of(qual_from))
1882 return false;
1883
1884 const struct_typet &from_struct = to_struct_type(from);
1885 const struct_typet &subto_struct = to_struct_type(subto);
1886
1887 if(subtype_typecast(subto_struct, from_struct))
1888 {
1889 if(e.id()==ID_dereference)
1890 {
1891 make_ptr_typecast(to_dereference_expr(e).pointer(), type);
1892 new_expr.swap(to_dereference_expr(e).pointer());
1893 return true;
1894 }
1895
1896 exprt address_of=address_of_exprt(e);
1897 make_ptr_typecast(address_of, type);
1898 new_expr.swap(address_of);
1899 return true;
1900 }
1901 }
1902 return false;
1903 }
1904
1905 if(type.id()==ID_empty)
1906 {
1907 new_expr = typecast_exprt::conditional_cast(e, type);
1908 return true;
1909 }
1910
1911 // int/enum to enum
1912 if(type.id()==ID_c_enum_tag &&
1913 (e.type().id()==ID_signedbv ||
1914 e.type().id()==ID_unsignedbv ||
1915 e.type().id()==ID_c_enum_tag))
1916 {
1917 new_expr = typecast_exprt::conditional_cast(e, type);
1918 new_expr.remove(ID_C_lvalue);
1919 return true;
1920 }
1921
1922 if(implicit_conversion_sequence(e, type, new_expr))
1923 {
1924 if(!cpp_is_pod(type))
1925 {
1926 exprt temporary;
1928 e.source_location(),
1929 type,
1930 already_typechecked_exprt{new_expr},
1931 temporary);
1932 new_expr.swap(temporary);
1933 }
1934 else
1935 {
1936 // try to avoid temporary
1937 new_expr.set(ID_C_temporary_avoided, true);
1938 if(new_expr.get_bool(ID_C_lvalue))
1939 new_expr.remove(ID_C_lvalue);
1940 }
1941
1942 return true;
1943 }
1944
1945 if(type.id()==ID_pointer && e.type().id()==ID_pointer)
1946 {
1947 if(type.find(ID_to_member).is_nil() && e.type().find(ID_to_member).is_nil())
1948 {
1949 typet to=follow(type.subtype());
1950 typet from=follow(e.type().subtype());
1951
1952 if(from.id()==ID_empty)
1953 {
1954 new_expr = typecast_exprt::conditional_cast(e, type);
1955 return true;
1956 }
1957
1958 if(to.id()==ID_struct && from.id()==ID_struct)
1959 {
1960 if(e.get_bool(ID_C_lvalue))
1961 {
1962 exprt tmp(e);
1964 return false;
1965 }
1966
1967 const struct_typet &from_struct = to_struct_type(from);
1968 const struct_typet &to_struct = to_struct_type(to);
1969 if(subtype_typecast(to_struct, from_struct))
1970 {
1971 make_ptr_typecast(e, type);
1972 new_expr.swap(e);
1973 return true;
1974 }
1975 }
1976
1977 return false;
1978 }
1979 else if(
1980 type.find(ID_to_member).is_not_nil() &&
1981 e.type().find(ID_to_member).is_not_nil())
1982 {
1983 if(type.subtype()!=e.type().subtype())
1984 return false;
1985
1986 const struct_typet &from_struct = to_struct_type(
1987 follow(static_cast<const typet &>(e.type().find(ID_to_member))));
1988
1989 const struct_typet &to_struct = to_struct_type(
1990 follow(static_cast<const typet &>(type.find(ID_to_member))));
1991
1992 if(subtype_typecast(from_struct, to_struct))
1993 {
1994 new_expr = typecast_exprt::conditional_cast(e, type);
1995 return true;
1996 }
1997 }
1998 else if(
1999 type.find(ID_to_member).is_nil() &&
2000 e.type().find(ID_to_member).is_not_nil())
2001 {
2002 if(type.subtype() != e.type().subtype())
2003 return false;
2004
2005 const struct_typet &from_struct = to_struct_type(
2006 follow(static_cast<const typet &>(e.type().find(ID_to_member))));
2007
2008 new_expr = e;
2009 new_expr.type().add(ID_to_member) = from_struct;
2010
2011 return true;
2012 }
2013 else
2014 return false;
2015 }
2016
2017 return false;
2018}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
void base_type(typet &type, const namespacet &ns)
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
floatbv_typet float_type()
Definition c_types.cpp:195
reference_typet reference_type(const typet &subtype)
Definition c_types.cpp:258
signedbv_typet signed_int_type()
Definition c_types.cpp:40
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:253
typet c_bool_type()
Definition c_types.cpp:118
bitvector_typet c_index_type()
Definition c_types.cpp:16
floatbv_typet double_type()
Definition c_types.cpp:203
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:162
Operator to return the address of an object.
static void make_already_typechecked(exprt &expr)
std::size_t get_width() const
Definition std_types.h:864
The Boolean type.
Definition std_types.h:36
virtual void write(typet &src) const override
virtual void read(const typet &src) override
virtual bool is_subset_of(const qualifierst &other) const override
bool get_this() const
Definition std_types.h:600
Base type of functions.
Definition std_types.h:539
const parameterst & parameters() const
Definition std_types.h:655
const typet & return_type() const
Definition std_types.h:645
struct configt::ansi_ct ansi_c
bool implicit_conversion_sequence(const exprt &expr, const typet &type, exprt &new_expr, unsigned &rank)
implicit conversion sequence
bool reference_compatible(const exprt &expr, const typet &type, unsigned &rank) const
Reference-compatible.
bool standard_conversion_floating_point_conversion(const exprt &expr, const typet &type, exprt &new_expr) const
Floating-point conversion.
bool reinterpret_typecast(const exprt &expr, const typet &type, exprt &new_expr, bool check_constantness=true)
bool standard_conversion_boolean(const exprt &expr, exprt &new_expr) const
Boolean conversion.
bool standard_conversion_pointer(const exprt &expr, const typet &type, exprt &new_expr)
Pointer conversion.
void implicit_typecast(exprt &expr, const typet &type) override
bool standard_conversion_integral_conversion(const exprt &expr, const typet &type, exprt &new_expr) const
Integral conversion.
bool standard_conversion_sequence(const exprt &expr, const typet &type, exprt &new_expr, unsigned &rank)
Standard Conversion Sequence.
bool standard_conversion_qualification(const exprt &expr, const typet &, exprt &new_expr) const
Qualification conversion.
void typecheck_side_effect_function_call(side_effect_expr_function_callt &) override
bool cpp_is_pod(const typet &type) const
bool standard_conversion_floating_point_promotion(const exprt &expr, exprt &new_expr) const
Floating-point-promotion conversion.
bool standard_conversion_floating_integral_conversion(const exprt &expr, const typet &type, exprt &new_expr) const
Floating-integral conversion.
bool const_typecast(const exprt &expr, const typet &type, exprt &new_expr)
void new_temporary(const source_locationt &source_location, const typet &, const exprt::operandst &ops, exprt &temporary)
void show_instantiation_stack(std::ostream &)
bool standard_conversion_function_to_pointer(const exprt &expr, exprt &new_expr) const
Function-to-pointer conversion.
bool standard_conversion_array_to_pointer(const exprt &expr, exprt &new_expr) const
Array-to-pointer conversion.
bool dynamic_typecast(const exprt &expr, const typet &type, exprt &new_expr)
bool user_defined_conversion_sequence(const exprt &expr, const typet &type, exprt &new_expr, unsigned &rank)
User-defined conversion sequence.
bool standard_conversion_lvalue_to_rvalue(const exprt &expr, exprt &new_expr) const
Lvalue-to-rvalue conversion.
bool cast_away_constness(const typet &t1, const typet &t2) const
void add_implicit_dereference(exprt &)
bool static_typecast(const exprt &expr, const typet &type, exprt &new_expr, bool check_constantness=true)
bool subtype_typecast(const struct_typet &from, const struct_typet &to) const
bool standard_conversion_integral_promotion(const exprt &expr, exprt &new_expr) const
Integral-promotion conversion.
std::string to_string(const typet &) override
void make_ptr_typecast(exprt &expr, const typet &dest_type)
bool standard_conversion_pointer_to_member(const exprt &expr, const typet &type, exprt &new_expr)
Pointer-to-member conversion.
void reference_initializer(exprt &expr, const typet &type)
A reference to type "cv1 T1" is initialized by an expression of type "cv2 T2" as follows:
bool reference_binding(exprt expr, const typet &type, exprt &new_expr, unsigned &rank)
Reference binding.
bool reference_related(const exprt &expr, const typet &type) const
Reference-related.
Operator to dereference a pointer.
Base class for all expressions.
Definition expr.h:54
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:165
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition expr.h:129
typet & type()
Return the type of the expression.
Definition expr.h:82
operandst & operands()
Definition expr.h:92
const source_locationt & source_location() const
Definition expr.h:230
source_locationt & add_source_location()
Definition expr.h:235
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition expr.h:136
Array index operator.
Definition std_expr.h:1328
bool get_bool(const irep_idt &name) const
Definition irep.cpp:58
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:495
const irept & find(const irep_idt &name) const
Definition irep.cpp:106
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:45
void remove(const irep_idt &name)
Definition irep.cpp:96
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:420
bool is_not_nil() const
Definition irep.h:380
void make_nil()
Definition irep.h:454
void swap(irept &irep)
Definition irep.h:442
const irep_idt & id() const
Definition irep.h:396
irept & add(const irep_idt &name)
Definition irep.cpp:116
bool is_nil() const
Definition irep.h:376
source_locationt source_location
Definition message.h:247
mstreamt & error() const
Definition message.h:399
static eomt eom
Definition message.h:297
exprt & op0()
Definition std_expr.h:844
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition namespace.cpp:49
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
const typet & base_type() const
The type of the data what we point to.
A side_effect_exprt representation of a function call side effect.
Definition std_code.h:1692
An expression containing a side effect.
Definition std_code.h:1450
Structure type, corresponds to C style structs.
Definition std_types.h:231
const componentst & components() const
Definition std_types.h:147
bool is_incomplete() const
A struct/union may be incomplete.
Definition std_types.h:185
Semantic type conversion.
Definition std_expr.h:1920
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:1928
The type of an expression, extends irept.
Definition type.h:29
const typet & subtype() const
Definition type.h:48
const exprt & op() const
Definition std_expr.h:293
configt config
Definition config.cpp:25
C++ Language Type Checking.
symbol_exprt cpp_symbol_expr(const symbolt &symbol)
Definition cpp_util.cpp:14
exprt is_not_zero(const exprt &src, const namespacet &ns)
converts a scalar/float expression to C/C++ Booleans
Definition expr_util.cpp:97
Deprecated expression utility functions.
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
API to expression classes for Pointers.
bool is_reference(const typet &type)
Returns true if the type is a reference.
const reference_typet & to_reference_type(const typet &type)
Cast a typet to a reference_typet.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:503
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:510
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:48
API to expression classes.
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:328
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:899
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:744
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
std::size_t single_width
Definition config.h:116
std::size_t int_width
Definition config.h:109