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{
51
52 if(expr.type().id() == ID_code)
53 return false;
54
55 if(
56 expr.type().id() == ID_struct &&
57 to_struct_type(expr.type()).is_incomplete())
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 PRECONDITION(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
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
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 {
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 = to_pointer_type(sub_from).base_type();
149 sub_from.swap(tmp1);
150
151 typet tmp2 = sub_to.add_subtype();
152 sub_to.swap(tmp2);
153 }
154
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
201 qual_from.read(expr.type());
202
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;
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;
221 return true;
222 }
223
224 if(expr.is_boolean() || expr.type().id() == ID_c_bool)
225 {
227 return true;
228 }
229
230 if(expr.type().id()==ID_c_enum_tag)
231 {
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
264 qual_from.read(expr.type());
265
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.is_boolean() &&
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
321 qual_from.read(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
374 qual_from.read(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
415
416 qual_from.read(expr.type());
418 qual_from.write(new_expr.type());
419
420 return true;
421}
422
456 const exprt &expr,
457 const typet &type,
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;
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 {
498 qual_from.read(to_pointer_type(expr.type()).base_type());
500 qual_from.write(to_pointer_type(new_expr.type()).base_type());
501 return true;
502 }
503
504 // struct * to struct *
505 if(sub_from.id()==ID_struct && sub_to.id()==ID_struct)
506 {
510 {
512 qual_from.read(to_pointer_type(expr.type()).base_type());
513 new_expr=expr;
515 qual_from.write(to_pointer_type(new_expr.type()).base_type());
516 return true;
517 }
518 }
519
520 return false;
521}
522
554 const exprt &expr,
555 const typet &type,
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() !=
570 to_pointer_type(expr.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(to_pointer_type(expr.type()).base_type());
578 DATA_INVARIANT(!code1.parameters().empty(), "must have parameters");
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(to_pointer_type(type).base_type());
584 DATA_INVARIANT(!code2.parameters().empty(), "must have parameters");
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(
590 to_pointer_type(this2.type()).base_type().get_bool(ID_C_constant) &&
591 !to_pointer_type(this1.type()).base_type().get_bool(ID_C_constant))
592 return false;
593
594 // give a second chance ignoring `this'
595 if(code1!=code2)
596 return false;
597 }
598 else
599 return false;
600 }
601
602 if(expr.get_bool(ID_C_lvalue))
603 return false;
604
605 if(expr.is_constant() && is_null_pointer(to_constant_expr(expr)))
606 {
608 return true;
609 }
610
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
618 {
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.is_boolean() &&
644 expr.type().id() != ID_c_enum_tag)
645 {
646 return false;
647 }
648
650 qual_from.read(expr.type());
651
653 qual_from.write(Bool);
654
656 return true;
657}
658
680 const exprt &expr,
681 const typet &type,
683 unsigned &rank)
684{
685 PRECONDITION(!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)
692 expr, to_c_bit_field_type(type).underlying_type(), new_expr, rank);
693
694 // we turn bit fields into their underlying type
695 if(curr_expr.type().id()==ID_c_bit_field)
697 curr_expr, to_c_bit_field_type(curr_expr.type()).underlying_type());
698
699 if(curr_expr.type().id()==ID_array)
700 {
701 if(type.id()==ID_pointer)
702 {
704 return false;
705 }
706 }
707 else if(curr_expr.type().id()==ID_code &&
708 type.id()==ID_pointer)
709 {
711 return false;
712 }
713 else if(curr_expr.get_bool(ID_C_lvalue))
714 {
716 return false;
717 }
718 else
720
721 curr_expr.swap(new_expr);
722
723 // two enums are the same if the tag is the same,
724 // even if the width differs (enum bit-fields!)
725 if(follow(type).id()==ID_c_enum &&
726 follow(curr_expr.type()).id()==ID_c_enum)
727 {
728 if(follow(type).find(ID_tag)==
729 follow(curr_expr.type()).find(ID_tag))
730 return true;
731 else
732 {
733 // In contrast to C, we simply don't allow implicit conversions
734 // between enums.
735 return false;
736 }
737 }
738
739 // need to consider #c_type
740 if(follow(curr_expr.type())!=follow(type) ||
741 curr_expr.type().get(ID_C_c_type)!=type.get(ID_C_c_type))
742 {
743 if(type.id()==ID_signedbv ||
744 type.id()==ID_unsignedbv ||
745 follow(type).id()==ID_c_enum)
746 {
748 new_expr.type() != type)
749 {
751 {
753 curr_expr, type, new_expr))
754 return false;
755 }
756
757 rank+=3;
758 }
759 else
760 rank+=2;
761 }
762 else if(type.id()==ID_floatbv || type.id()==ID_fixedbv)
763 {
765 new_expr.type() != type)
766 {
768 curr_expr, type, new_expr) &&
770 curr_expr, type, new_expr))
771 return false;
772
773 rank += 3;
774 }
775 else
776 rank += 2;
777 }
778 else if(type.id()==ID_pointer)
779 {
780 if(
781 expr.type().id() == ID_pointer &&
782 to_pointer_type(expr.type()).base_type().id() == ID_nullptr)
783 {
784 // std::nullptr_t to _any_ pointer type is ok
786 }
788 {
790 return false;
791 }
792
793 rank += 3;
794 }
795 else if(type.id() == ID_c_bool)
796 {
798 return false;
799
800 rank += 3;
801 }
802 else if(type.id() == ID_bool)
803 {
805
806 rank += 3;
807 }
808 else
809 return false;
810 }
811 else
813
814 curr_expr.swap(new_expr);
815
816 if(curr_expr.type().id()==ID_pointer)
817 {
818 typet sub_from=curr_expr.type();
819 typet sub_to=type;
820
821 do
822 {
823 typet tmp_from = to_pointer_type(sub_from).base_type();
824 sub_from.swap(tmp_from);
825 typet tmp_to = sub_to.add_subtype();
826 sub_to.swap(tmp_to);
827
829 qual_from.read(sub_from);
830
832 qual_to.read(sub_to);
833
834 if(qual_from!=qual_to)
835 {
836 rank+=1;
837 break;
838 }
839 }
840 while(sub_from.id()==ID_pointer);
841
843 return false;
844 }
845 else
846 {
848 new_expr.type()=type;
849 }
850
851 return true;
852}
853
860 const exprt &expr,
861 const typet &type,
863 unsigned &rank)
864{
867
868 const typet &from=follow(expr.type());
869 const typet &to=follow(type);
870
871 new_expr.make_nil();
872
873 // special case:
874 // A conversion from a type to the same type is given an exact
875 // match rank even though a user-defined conversion is used
876
877 if(from==to)
878 rank+=0;
879 else
880 rank+=4; // higher than all the standard conversions
881
882 if(to.id()==ID_struct)
883 {
884 std::string err_msg;
885
886 if(cpp_is_pod(to))
887 {
888 if(from.id()==ID_struct)
889 {
892
893 // potentially requires
894 // expr.get_bool(ID_C_lvalue) ??
895
897 {
898 exprt address=address_of_exprt(expr);
899
900 // simplify address
901 if(expr.id()==ID_dereference)
902 address = to_dereference_expr(expr).pointer();
903
906 qual_from.read(expr.type());
907 qual_from.write(ptr_sub.base_type());
908 make_ptr_typecast(address, ptr_sub);
909
910 const dereference_exprt deref(address);
911
912 // create temporary object
915 tmp_object_expr.copy_to_operands(deref);
916 tmp_object_expr.set(ID_C_lvalue, true);
918
920 return true;
921 }
922 }
923 }
924 else
925 {
926 bool found=false;
927
928 for(const auto &component : to_struct_type(to).components())
929 {
930 if(component.get_bool(ID_from_base))
931 continue;
932
933 if(component.get_bool(ID_is_explicit))
934 continue;
935
936 const typet &comp_type = component.type();
937
938 if(comp_type.id() !=ID_code)
939 continue;
940
941 if(to_code_type(comp_type).return_type().id() != ID_constructor)
942 continue;
943
944 // TODO: ellipsis
945
946 const auto &parameters = to_code_type(comp_type).parameters();
947
948 if(parameters.size() != 2)
949 continue;
950
951 exprt curr_arg1 = parameters[1];
953
955 {
956 typet tmp = to_reference_type(arg1_type).base_type();
957 arg1_type.swap(tmp);
958 }
959
960 unsigned tmp_rank=0;
961 if(arg1_type.id() != ID_struct_tag)
962 {
965 expr, arg1_type, tmp_expr, tmp_rank))
966 {
967 // check if it's ambiguous
968 if(found)
969 return false;
970 found=true;
971
972 if(expr.get_bool(ID_C_lvalue))
973 tmp_expr.set(ID_C_lvalue, true);
974
975 tmp_expr.add_source_location()=expr.source_location();
976
978 func_symb.type()=comp_type;
980
981 // create temporary object
983 std::move(func_symb),
984 {tmp_expr},
986 expr.source_location());
989
990 new_expr.swap(ctor_expr);
991
992 if(to.get_bool(ID_C_constant))
993 new_expr.type().set(ID_C_constant, true);
994
995 rank += tmp_rank;
996 }
997 }
998 else if(from.id() == ID_struct && arg1_type.id() == ID_struct_tag)
999 {
1000 // try derived-to-base conversion
1003
1005 tmp_rank=0;
1008 {
1009 // check if it's ambiguous
1010 if(found)
1011 return false;
1012 found=true;
1013
1014 rank+=tmp_rank;
1015
1016 // create temporary object
1018 expr_deref.set(ID_C_lvalue, true);
1019 expr_deref.add_source_location()=expr.source_location();
1020
1022 new_object.set(ID_C_lvalue, true);
1023 new_object.type().set(ID_C_constant, false);
1024
1026 func_symb.type()=comp_type;
1028
1030 std::move(func_symb),
1031 {expr_deref},
1033 expr.source_location());
1035
1036 new_expr.swap(ctor_expr);
1037
1038 INVARIANT(
1040 "statement ID");
1041
1042 if(to.get_bool(ID_C_constant))
1043 new_expr.type().set(ID_C_constant, true);
1044 }
1045 }
1046 }
1047 if(found)
1048 return true;
1049 }
1050 }
1051
1052 // conversion operators
1053 if(from.id()==ID_struct)
1054 {
1055 bool found=false;
1056 for(const auto &component : to_struct_type(from).components())
1057 {
1058 if(component.get_bool(ID_from_base))
1059 continue;
1060
1061 if(!component.get_bool(ID_is_cast_operator))
1062 continue;
1063
1064 const code_typet &comp_type = to_code_type(component.type());
1066 comp_type.parameters().size() == 1, "expected exactly one parameter");
1067
1068 typet this_type = comp_type.parameters().front().type();
1069 this_type.set(ID_C_reference, true);
1070
1071 exprt this_expr(expr);
1072 this_type.set(ID_C_this, true);
1073
1074 unsigned tmp_rank=0;
1076
1078 this_expr, this_type, tmp_expr, tmp_rank))
1079 {
1080 // To take care of the possible virtual case,
1081 // we build the function as a member expression.
1082 const cpp_namet cpp_func_name(component.get_base_name());
1083
1086 member_func.copy_to_operands(already_typechecked_exprt{expr});
1087
1089 std::move(member_func),
1090 {},
1092 expr.source_location());
1094
1096 {
1097 // check if it's ambiguous
1098 if(found)
1099 return false;
1100 found=true;
1101
1102 rank+=tmp_rank;
1103 new_expr.swap(tmp_expr);
1104 }
1105 }
1106 }
1107 if(found)
1108 return true;
1109 }
1110
1111 return new_expr.is_not_nil();
1112}
1113
1119 const exprt &expr,
1120 const typet &type) const
1121{
1123 PRECONDITION(!is_reference(expr.type()));
1124
1125 typet from=follow(expr.type());
1126 typet to = follow(to_reference_type(type).base_type());
1127
1128 // need to check #c_type
1129 if(from.get(ID_C_c_type)!=to.get(ID_C_c_type))
1130 return false;
1131
1132 if(from==to)
1133 return true;
1134
1135 if(from.id()==ID_struct &&
1136 to.id()==ID_struct)
1139
1140 if(
1141 from.id() == ID_struct && type.get_bool(ID_C_this) &&
1142 to_pointer_type(type).base_type().id() == ID_empty)
1143 {
1144 // virtual-call case
1145 return true;
1146 }
1147
1148 return false;
1149}
1150
1156 const exprt &expr,
1157 const typet &type,
1158 unsigned &rank) const
1159{
1161 PRECONDITION(!is_reference(expr.type()));
1162
1163 if(!reference_related(expr, type))
1164 return false;
1165
1166 if(expr.type() != to_reference_type(type).base_type())
1167 rank+=3;
1168
1170 qual_from.read(expr.type());
1171
1173 qual_to.read(to_reference_type(type).base_type());
1174
1175 if(qual_from!=qual_to)
1176 rank+=1;
1177
1178 if(qual_from.is_subset_of(qual_to))
1179 return true;
1180
1181 return false;
1182}
1183
1219 exprt expr,
1220 const typet &type,
1221 exprt &new_expr,
1222 unsigned &rank)
1223{
1225 PRECONDITION(!is_reference(expr.type()));
1226
1227 unsigned backup_rank=rank;
1228
1229 if(type.get_bool(ID_C_this) &&
1230 !expr.get_bool(ID_C_lvalue))
1231 {
1232 // `this' has to be an lvalue
1234 expr.set(ID_C_lvalue, true);
1235 else if(expr.get(ID_statement)==ID_function_call)
1236 expr.set(ID_C_lvalue, true);
1237 else if(expr.get_bool(ID_C_temporary_avoided))
1238 {
1241 new_temporary(expr.source_location(), expr.type(), expr, temporary);
1242 expr.swap(temporary);
1243 expr.set(ID_C_lvalue, true);
1244 }
1245 else
1246 return false;
1247 }
1248
1249 if(
1250 expr.get_bool(ID_C_lvalue) ||
1251 to_reference_type(type).base_type().get_bool(ID_C_constant))
1252 {
1253 if(reference_compatible(expr, type, rank))
1254 {
1255 if(!expr.get_bool(ID_C_lvalue))
1256 {
1257 // create temporary object
1259 {std::move(expr)},
1260 to_reference_type(type).base_type(),
1261 expr.source_location()};
1262 tmp.set(ID_mode, ID_cpp);
1263 expr.swap(tmp);
1264 }
1265
1266 {
1267 address_of_exprt tmp(expr, reference_type(expr.type()));
1268 tmp.add_source_location()=expr.source_location();
1269 new_expr.swap(tmp);
1270 }
1271
1272 if(expr.type() != to_reference_type(type).base_type())
1273 {
1275 qual_from.read(expr.type());
1277 qual_from.write(to_reference_type(new_expr.type()).base_type());
1278 }
1279
1280 return true;
1281 }
1282
1284 }
1285
1286 // conversion operators
1287 const typet &from_type = follow(expr.type());
1288 if(from_type.id()==ID_struct)
1289 {
1290 for(const auto &component : to_struct_type(from_type).components())
1291 {
1292 if(component.get_bool(ID_from_base))
1293 continue;
1294
1295 if(!component.get_bool(ID_is_cast_operator))
1296 continue;
1297
1298 const code_typet &component_type = to_code_type(component.type());
1299
1300 // otherwise it cannot bind directly (not an lvalue)
1301 if(!is_reference(component_type.return_type()))
1302 continue;
1303
1305 component_type.parameters().size() == 1, "exactly one parameter");
1306
1308 component_type.parameters().front().type();
1309 this_type.set(ID_C_reference, true);
1310
1311 exprt this_expr(expr);
1312
1313 this_type.set(ID_C_this, true);
1314
1315 unsigned tmp_rank=0;
1316
1319 this_expr, this_type, tmp_expr, tmp_rank))
1320 {
1321 // To take care of the possible virtual case,
1322 // we build the function as a member expression.
1323 const cpp_namet cpp_func_name(component.get_base_name());
1324
1327 member_func.copy_to_operands(already_typechecked_exprt{expr});
1328
1330 std::move(member_func),
1331 {},
1333 expr.source_location());
1335
1336 // let's check if the returned value binds directly
1339
1340 if(returned_value.get_bool(ID_C_lvalue) &&
1342 {
1343 // returned values are lvalues in case of references only
1346 "the returned value must be pointer to reference");
1347
1349
1350 if(returned_value.type() != to_reference_type(type).base_type())
1351 {
1353 qual_from.read(returned_value.type());
1355 qual_from.write(to_reference_type(new_expr.type()).base_type());
1356 }
1357 rank+=4+tmp_rank;
1358 return true;
1359 }
1360 }
1361 }
1362 }
1363
1364 // No temporary allowed for `this'
1365 if(type.get_bool(ID_C_this))
1366 return false;
1367
1368 if(
1369 !to_reference_type(type).base_type().get_bool(ID_C_constant) ||
1370 to_reference_type(type).base_type().get_bool(ID_C_volatile))
1371 return false;
1372
1373 // TODO: handle the case for implicit parameters
1374 if(
1375 !to_reference_type(type).base_type().get_bool(ID_C_constant) &&
1376 !expr.get_bool(ID_C_lvalue))
1377 return false;
1378
1379 exprt arg_expr=expr;
1380
1381 if(arg_expr.type().id() == ID_struct_tag)
1382 {
1383 // required to initialize the temporary
1384 arg_expr.set(ID_C_lvalue, true);
1385 }
1386
1388 arg_expr, to_reference_type(type).base_type(), new_expr, rank))
1389 {
1391 tmp.add_source_location()=new_expr.source_location();
1392 new_expr.swap(tmp);
1393 return true;
1394 }
1395
1398 expr, to_reference_type(type).base_type(), new_expr, rank))
1399 {
1400 {
1401 // create temporary object
1404 to_reference_type(type).base_type(),
1405 expr.source_location());
1406 tmp.set(ID_mode, ID_cpp);
1407 // tmp.set(ID_C_lvalue, true);
1408 tmp.add_to_operands(std::move(new_expr));
1409 new_expr.swap(tmp);
1410 }
1411
1413 tmp.type().set(ID_C_reference, true);
1414 tmp.add_source_location()=new_expr.source_location();
1415
1416 new_expr=tmp;
1417 return true;
1418 }
1419
1420 return false;
1421}
1422
1430 const exprt &expr,
1431 const typet &type,
1432 exprt &new_expr,
1433 unsigned &rank)
1434{
1435 unsigned backup_rank=rank;
1436
1437 exprt e=expr;
1439
1440 if(is_reference(type))
1441 {
1442 if(!reference_binding(e, type, new_expr, rank))
1443 return false;
1444
1445 #if 0
1446 simplify_exprt simplify(*this);
1447 simplify.simplify(new_expr);
1448 new_expr.type().set(ID_C_reference, true);
1449 #endif
1450 }
1451 else if(!standard_conversion_sequence(e, type, new_expr, rank))
1452 {
1455 {
1456 if(
1457 type.id() == ID_integer &&
1458 (expr.type().id() == ID_signedbv || expr.type().id() == ID_unsignedbv))
1459 {
1460 // This is a nonstandard implicit conversion, from
1461 // bit-vectors to unbounded integers.
1462 rank = 0;
1463 new_expr = typecast_exprt(expr, type);
1464 return true;
1465 }
1466 else if(
1467 (type.id() == ID_signedbv || type.id() == ID_unsignedbv) &&
1468 expr.type().id() == ID_integer)
1469 {
1470 // This is a nonstandard implicit conversion, from
1471 // unbounded integers to bit-vectors.
1472 rank = 0;
1473 new_expr = typecast_exprt(expr, type);
1474 return true;
1475 }
1476
1477 // no conversion
1478 return false;
1479 }
1480
1481#if 0
1482 simplify_exprt simplify(*this);
1483 simplify.simplify(new_expr);
1484#endif
1485 }
1486
1487 return true;
1488}
1489
1496 const exprt &expr,
1497 const typet &type,
1498 exprt &new_expr)
1499{
1500 unsigned rank=0;
1501 return implicit_conversion_sequence(expr, type, new_expr, rank);
1502}
1503
1510 const exprt &expr,
1511 const typet &type,
1512 unsigned &rank)
1513{
1515 return implicit_conversion_sequence(expr, type, new_expr, rank);
1516}
1517
1519{
1520 exprt e=expr;
1521
1522 if(
1523 e.id() == ID_initializer_list && cpp_is_pod(type) &&
1524 e.operands().size() == 1)
1525 {
1526 e = to_unary_expr(expr).op();
1527 }
1528
1529 if(!implicit_conversion_sequence(e, type, expr))
1530 {
1533 error() << "invalid implicit conversion from '" << to_string(e.type())
1534 << "' to '" << to_string(type) << "'" << eom;
1535#if 0
1536 str << "\n " << follow(e.type()).pretty() << '\n';
1537 str << "\n " << type.pretty() << '\n';
1538#endif
1539 throw 0;
1540 }
1541}
1542
1586 exprt &expr,
1587 const typet &type)
1588{
1591
1592 unsigned rank=0;
1594 if(reference_binding(expr, type, new_expr, rank))
1595 {
1596 expr.swap(new_expr);
1597 return;
1598 }
1599
1601 error() << "bad reference initializer" << eom;
1602 throw 0;
1603}
1604
1606 const typet &t1,
1607 const typet &t2) const
1608{
1609 PRECONDITION(t1.id() == ID_pointer && t2.id() == ID_pointer);
1610 typet nt1=t1;
1611 typet nt2=t2;
1612
1613 if(is_reference(nt1))
1614 nt1.remove(ID_C_reference);
1615 nt1.remove(ID_to_member);
1616
1617 if(is_reference(nt2))
1618 nt2.remove(ID_C_reference);
1619 nt2.remove(ID_to_member);
1620
1621 // substitute final subtypes
1622 std::vector<typet> snt1;
1623 snt1.push_back(nt1);
1624
1625 while(snt1.back().has_subtype())
1626 {
1627 snt1.reserve(snt1.size()+1);
1628 snt1.push_back(to_type_with_subtype(snt1.back()).subtype());
1629 }
1630
1632 q1.read(snt1.back());
1633
1635 q1.write(newnt1);
1636 snt1.back()=newnt1;
1637
1638 std::vector<typet> snt2;
1639 snt2.push_back(nt2);
1640 while(snt2.back().has_subtype())
1641 {
1642 snt2.reserve(snt2.size()+1);
1643 snt2.push_back(to_type_with_subtype(snt2.back()).subtype());
1644 }
1645
1647 q2.read(snt2.back());
1648
1650 q2.write(newnt2);
1651 snt2.back()=newnt2;
1652
1653 const std::size_t k=snt1.size() < snt2.size() ? snt1.size() : snt2.size();
1654
1655 for(std::size_t i=k; i > 1; i--)
1656 {
1657 to_type_with_subtype(snt1[snt1.size() - 2]).subtype() =
1658 snt1[snt1.size() - 1];
1659 snt1.pop_back();
1660
1661 to_type_with_subtype(snt2[snt2.size() - 2]).subtype() =
1662 snt2[snt2.size() - 1];
1663 snt2.pop_back();
1664 }
1665
1666 exprt e1("Dummy", snt1.back());
1667 exprt e2;
1668
1669 return !standard_conversion_qualification(e1, snt2.back(), e2);
1670}
1671
1673 const exprt &expr,
1674 const typet &type,
1675 exprt &new_expr)
1676{
1677 PRECONDITION(!is_reference(expr.type()));
1678
1679 exprt curr_expr=expr;
1680
1681 if(curr_expr.type().id()==ID_array)
1682 {
1683 if(type.id()==ID_pointer)
1684 {
1686 return false;
1687 }
1688 }
1689 else if(curr_expr.type().id()==ID_code &&
1690 type.id()==ID_pointer)
1691 {
1693 return false;
1694 }
1695 else if(curr_expr.get_bool(ID_C_lvalue))
1696 {
1698 return false;
1699 }
1700 else
1702
1703 if(is_reference(type))
1704 {
1705 if(!expr.get_bool(ID_C_lvalue))
1706 return false;
1707
1708 if(new_expr.type() != to_reference_type(type).base_type())
1709 return false;
1710
1714 return true;
1715 }
1716 else if(type.id()==ID_pointer)
1717 {
1718 if(type!=new_expr.type())
1719 return false;
1720
1721 // add proper typecast
1722 typecast_exprt typecast_expr(expr, type);
1723 new_expr.swap(typecast_expr);
1724 return true;
1725 }
1726
1727 return false;
1728}
1729
1731 const exprt &expr,
1732 const typet &type,
1733 exprt &new_expr)
1734{
1735 exprt e(expr);
1736
1737 if(type.id()==ID_pointer)
1738 {
1740 e = to_dereference_expr(expr).pointer();
1741
1742 if(e.type().id()==ID_pointer &&
1743 cast_away_constness(e.type(), type))
1744 return false;
1745 }
1746
1748
1749 if(is_reference(type))
1750 {
1751 if(to_reference_type(type).base_type().id() != ID_struct_tag)
1752 return false;
1753 }
1754 else if(type.id()==ID_pointer)
1755 {
1756 if(type.find(ID_to_member).is_not_nil())
1757 return false;
1758
1759 if(to_pointer_type(type).base_type().id() == ID_empty)
1760 {
1761 if(!e.get_bool(ID_C_lvalue))
1762 return false;
1763 UNREACHABLE; // currently not supported
1764 }
1765 else if(to_pointer_type(type).base_type().id() == ID_struct_tag)
1766 {
1767 if(e.get_bool(ID_C_lvalue))
1768 {
1769 exprt tmp(e);
1770
1772 return false;
1773 }
1774 }
1775 else return false;
1776 }
1777 else return false;
1778
1779 return static_typecast(e, type, new_expr);
1780}
1781
1783 const exprt &expr,
1784 const typet &type,
1785 exprt &new_expr,
1786 bool check_constantness)
1787{
1788 exprt e=expr;
1789
1790 if(check_constantness && type.id()==ID_pointer)
1791 {
1793 e = to_dereference_expr(expr).pointer();
1794
1795 if(e.type().id()==ID_pointer &&
1796 cast_away_constness(e.type(), type))
1797 return false;
1798 }
1799
1801
1802 if(!is_reference(type))
1803 {
1804 exprt tmp;
1805
1806 if(e.id()==ID_code)
1807 {
1809 e.swap(tmp);
1810 else
1811 return false;
1812 }
1813
1814 if(e.type().id()==ID_array)
1815 {
1817 e.swap(tmp);
1818 else
1819 return false;
1820 }
1821
1822 if(e.get_bool(ID_C_lvalue))
1823 {
1825 e.swap(tmp);
1826 else
1827 return false;
1828 }
1829 }
1830
1831 if(e.type().id()==ID_pointer &&
1832 (type.id()==ID_unsignedbv || type.id()==ID_signedbv))
1833 {
1834 // pointer to integer, always ok
1836 return true;
1837 }
1838
1839 if(
1840 (e.type().id() == ID_unsignedbv || e.type().id() == ID_signedbv ||
1841 e.type().id() == ID_c_bool || e.is_boolean()) &&
1842 type.id() == ID_pointer && !is_reference(type))
1843 {
1844 // integer to pointer
1845 if(simplify_expr(e, *this).is_zero())
1846 {
1847 // NULL
1848 new_expr=e;
1850 new_expr.type()=type;
1851 }
1852 else
1853 {
1855 }
1856 return true;
1857 }
1858
1859 if(e.type().id()==ID_pointer &&
1860 type.id()==ID_pointer &&
1861 !is_reference(type))
1862 {
1863 // pointer to pointer: we ok it all.
1864 // This is more generous than the standard.
1866 return true;
1867 }
1868
1869 if(is_reference(type) && e.get_bool(ID_C_lvalue))
1870 {
1872 return true;
1873 }
1874
1875 return false;
1876}
1877
1879 const exprt &expr, // source expression
1880 const typet &type, // destination type
1881 exprt &new_expr,
1882 bool check_constantness)
1883{
1884 exprt e=expr;
1885
1886 if(check_constantness && type.id()==ID_pointer)
1887 {
1889 e = to_dereference_expr(expr).pointer();
1890
1891 if(e.type().id()==ID_pointer &&
1892 cast_away_constness(e.type(), type))
1893 return false;
1894 }
1895
1897
1898 if(type.get_bool(ID_C_reference))
1899 {
1900 unsigned rank=0;
1901 if(reference_binding(e, type, new_expr, rank))
1902 return true;
1903
1904 typet subto = follow(to_pointer_type(type).base_type());
1905 typet from=follow(e.type());
1906
1907 if(subto.id()==ID_struct && from.id()==ID_struct)
1908 {
1909 if(!expr.get_bool(ID_C_lvalue))
1910 return false;
1911
1913 qual_from.read(e.type());
1914
1916 qual_to.read(to_pointer_type(type).base_type());
1917
1918 if(!qual_to.is_subset_of(qual_from))
1919 return false;
1920
1923
1925 {
1926 if(e.id()==ID_dereference)
1927 {
1928 make_ptr_typecast(to_dereference_expr(e).pointer(), type);
1929 new_expr.swap(to_dereference_expr(e).pointer());
1930 return true;
1931 }
1932
1935 new_expr.swap(address_of);
1936 return true;
1937 }
1938 }
1939 return false;
1940 }
1941
1942 if(type.id()==ID_empty)
1943 {
1945 return true;
1946 }
1947
1948 // int/enum to enum
1949 if(type.id()==ID_c_enum_tag &&
1950 (e.type().id()==ID_signedbv ||
1951 e.type().id()==ID_unsignedbv ||
1952 e.type().id()==ID_c_enum_tag))
1953 {
1955 new_expr.remove(ID_C_lvalue);
1956 return true;
1957 }
1958
1960 {
1961 if(!cpp_is_pod(type))
1962 {
1965 e.source_location(),
1966 type,
1967 already_typechecked_exprt{new_expr},
1968 temporary);
1969 new_expr.swap(temporary);
1970 }
1971 else
1972 {
1973 // try to avoid temporary
1975 if(new_expr.get_bool(ID_C_lvalue))
1976 new_expr.remove(ID_C_lvalue);
1977 }
1978
1979 return true;
1980 }
1981
1982 if(type.id()==ID_pointer && e.type().id()==ID_pointer)
1983 {
1984 if(type.find(ID_to_member).is_nil() && e.type().find(ID_to_member).is_nil())
1985 {
1986 typet to = follow(to_pointer_type(type).base_type());
1987 typet from = follow(to_pointer_type(e.type()).base_type());
1988
1989 if(from.id()==ID_empty)
1990 {
1992 return true;
1993 }
1994
1995 if(to.id()==ID_struct && from.id()==ID_struct)
1996 {
1997 if(e.get_bool(ID_C_lvalue))
1998 {
1999 exprt tmp(e);
2001 return false;
2002 }
2003
2007 {
2008 make_ptr_typecast(e, type);
2009 new_expr.swap(e);
2010 return true;
2011 }
2012 }
2013
2014 return false;
2015 }
2016 else if(
2017 type.find(ID_to_member).is_not_nil() &&
2018 e.type().find(ID_to_member).is_not_nil())
2019 {
2020 if(
2021 to_pointer_type(type).base_type() !=
2022 to_pointer_type(e.type()).base_type())
2023 return false;
2024
2026 follow(static_cast<const typet &>(e.type().find(ID_to_member))));
2027
2029 follow(static_cast<const typet &>(type.find(ID_to_member))));
2030
2032 {
2034 return true;
2035 }
2036 }
2037 else if(
2038 type.find(ID_to_member).is_nil() &&
2039 e.type().find(ID_to_member).is_not_nil())
2040 {
2041 if(
2042 to_pointer_type(type).base_type() !=
2043 to_pointer_type(e.type()).base_type())
2044 {
2045 return false;
2046 }
2047
2049 follow(static_cast<const typet &>(e.type().find(ID_to_member))));
2050
2051 new_expr = e;
2052 new_expr.type().add(ID_to_member) = from_struct;
2053
2054 return true;
2055 }
2056 else
2057 return false;
2058 }
2059
2060 return false;
2061}
configt config
Definition config.cpp:25
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
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:182
reference_typet reference_type(const typet &subtype)
Definition c_types.cpp:245
signedbv_typet signed_int_type()
Definition c_types.cpp:27
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:240
typet c_bool_type()
Definition c_types.cpp:105
bitvector_typet c_index_type()
Definition c_types.cpp:16
floatbv_typet double_type()
Definition c_types.cpp:190
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
Operator to return the address of an object.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:563
static void make_already_typechecked(exprt &expr)
The Boolean type.
Definition std_types.h:36
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: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_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:216
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:204
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:223
Array index operator.
Definition std_expr.h:1410
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:490
const irept & find(const irep_idt &name) const
Definition irep.cpp:101
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void remove(const irep_idt &name)
Definition irep.cpp:95
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:420
void swap(irept &irep)
Definition irep.h:442
const irep_idt & id() const
Definition irep.h:396
source_locationt source_location
Definition message.h:247
mstreamt & error() const
Definition message.h:399
static eomt eom
Definition message.h:297
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 ...
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
Semantic type conversion.
Definition std_expr.h:2017
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2025
The type of an expression, extends irept.
Definition type.h:29
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
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
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 CHECK_RETURN(CONDITION)
Definition invariant.h:495
#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
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:77
API to expression classes.
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:361
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:932
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:2992
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
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:175