23
23
#include < util/prefix.h>
24
24
#include < util/range.h>
25
25
#include < util/simplify_expr.h>
26
+ #include < util/ssa_expr.h>
26
27
#include < util/std_code.h>
27
28
#include < util/symbol.h>
28
29
#include < util/xml.h>
29
30
30
31
#ifdef DEBUG
31
- #include < iostream>
32
- #include < util/format_expr.h>
33
- #include < util/format_type.h>
32
+ # include < iostream>
34
33
#endif
35
34
36
35
#include " add_failed_symbols.h"
@@ -184,7 +183,7 @@ void value_sett::output(std::ostream &out, const std::string &indent) const
184
183
stream << " <" << format (o) << " , " ;
185
184
186
185
if (o_it->second )
187
- stream << *o_it->second ;
186
+ stream << format ( *o_it->second ) ;
188
187
else
189
188
stream << ' *' ;
190
189
@@ -261,7 +260,7 @@ exprt value_sett::to_expr(const object_map_dt::value_type &it) const
261
260
od.object ()=object;
262
261
263
262
if (it.second )
264
- od.offset () = from_integer ( *it.second , c_index_type ()) ;
263
+ od.offset () = *it.second ;
265
264
266
265
od.type ()=od.object ().type ();
267
266
@@ -352,17 +351,34 @@ bool value_sett::eval_pointer_offset(
352
351
it=object_map.begin ();
353
352
it!=object_map.end ();
354
353
it++)
355
- if (!it->second )
354
+ {
355
+ if (!it->second || !it->second ->is_constant ())
356
356
return false ;
357
357
else
358
358
{
359
+ // This branch should not be reached as any constant offset will have
360
+ // been used before already. The following code will trigger
361
+ // `eval_pointer_offset`, yet we wouldn't end up in this branch:
362
+ // struct S { int a; char b; };
363
+ //
364
+ // int main()
365
+ // {
366
+ // struct S s;
367
+ // int offset;
368
+ // __CPROVER_assume(offset >= 0 && offset <= 1 && offset % 2 == 0);
369
+ // int *p = (char*)&s + offset;
370
+ // int x = *p;
371
+ // __CPROVER_assert(s.a == x, "");
372
+ // }
373
+ UNREACHABLE;
359
374
const exprt &object=object_numbering[it->first ];
360
375
auto ptr_offset = compute_pointer_offset (object, ns);
361
376
362
377
if (!ptr_offset.has_value ())
363
378
return false ;
364
379
365
- *ptr_offset += *it->second ;
380
+ *ptr_offset +=
381
+ numeric_cast_v<mp_integer>(to_constant_expr (*it->second ));
366
382
367
383
if (mod && *ptr_offset != previous_offset)
368
384
return false ;
@@ -371,6 +387,7 @@ bool value_sett::eval_pointer_offset(
371
387
previous_offset = *ptr_offset;
372
388
mod=true ;
373
389
}
390
+ }
374
391
375
392
if (mod)
376
393
expr.swap (new_expr);
@@ -556,8 +573,11 @@ void value_sett::get_value_set_rec(
556
573
}
557
574
else if (expr.id ()==ID_symbol)
558
575
{
559
- auto entry_index = get_index_of_symbol (
560
- to_symbol_expr (expr).get_identifier (), expr.type (), suffix, ns);
576
+ const symbol_exprt expr_l1 = is_ssa_expr (expr)
577
+ ? remove_level_2 (to_ssa_expr (expr))
578
+ : to_symbol_expr (expr);
579
+ auto entry_index =
580
+ get_index_of_symbol (expr_l1.get_identifier (), expr.type (), suffix, ns);
561
581
562
582
if (entry_index.has_value ())
563
583
make_union (dest, find_entry (*entry_index)->object_map );
@@ -623,7 +643,7 @@ void value_sett::get_value_set_rec(
623
643
insert (
624
644
dest,
625
645
exprt (ID_null_object, to_pointer_type (expr.type ()).base_type ()),
626
- mp_integer{ 0 } );
646
+ from_integer ( 0 , c_index_type ()) );
627
647
}
628
648
else if (
629
649
expr.type ().id () == ID_unsignedbv || expr.type ().id () == ID_signedbv)
@@ -655,7 +675,10 @@ void value_sett::get_value_set_rec(
655
675
656
676
if (op.is_zero ())
657
677
{
658
- insert (dest, exprt (ID_null_object, empty_typet{}), mp_integer{0 });
678
+ insert (
679
+ dest,
680
+ exprt (ID_null_object, empty_typet{}),
681
+ from_integer (0 , c_index_type ()));
659
682
}
660
683
else
661
684
{
@@ -697,15 +720,14 @@ void value_sett::get_value_set_rec(
697
720
expr.id_string () + " expected to have at least two operands" );
698
721
699
722
object_mapt pointer_expr_set;
700
- std::optional<mp_integer> i ;
723
+ std::optional<exprt> additional_offset ;
701
724
702
725
// special case for plus/minus and exactly one pointer
703
726
std::optional<exprt> ptr_operand;
704
727
if (
705
728
expr.type ().id () == ID_pointer &&
706
729
(expr.id () == ID_plus || expr.id () == ID_minus))
707
730
{
708
- bool non_const_offset = false ;
709
731
for (const auto &op : expr.operands ())
710
732
{
711
733
if (op.type ().id () == ID_pointer)
@@ -718,24 +740,20 @@ void value_sett::get_value_set_rec(
718
740
719
741
ptr_operand = op;
720
742
}
721
- else if (!non_const_offset)
743
+ else
722
744
{
723
- auto offset = numeric_cast<mp_integer>(op);
724
- if (!offset.has_value ())
725
- {
726
- i.reset ();
727
- non_const_offset = true ;
728
- }
745
+ if (!additional_offset.has_value ())
746
+ additional_offset = op;
729
747
else
730
748
{
731
- if (!i. has_value ())
732
- i = mp_integer{ 0 };
733
- i = *i + *offset ;
749
+ additional_offset = plus_exprt{
750
+ *additional_offset,
751
+ typecast_exprt::conditional_cast (op, additional_offset-> type ())} ;
734
752
}
735
753
}
736
754
}
737
755
738
- if (ptr_operand.has_value () && i .has_value ())
756
+ if (ptr_operand.has_value () && additional_offset .has_value ())
739
757
{
740
758
typet pointer_base_type =
741
759
to_pointer_type (ptr_operand->type ()).base_type ();
@@ -746,18 +764,22 @@ void value_sett::get_value_set_rec(
746
764
747
765
if (!size.has_value () || (*size) == 0 )
748
766
{
749
- i .reset ();
767
+ additional_offset .reset ();
750
768
}
751
769
else
752
770
{
753
- *i *= *size;
771
+ additional_offset = mult_exprt{
772
+ *additional_offset, from_integer (*size, additional_offset->type ())};
754
773
755
774
if (expr.id ()==ID_minus)
756
775
{
757
776
DATA_INVARIANT (
758
777
to_minus_expr (expr).lhs () == *ptr_operand,
759
778
" unexpected subtraction of pointer from integer" );
760
- i->negate ();
779
+ DATA_INVARIANT (
780
+ additional_offset->type ().id () != ID_unsignedbv,
781
+ " offset type must support negation" );
782
+ additional_offset = unary_minus_exprt{*additional_offset};
761
783
}
762
784
}
763
785
}
@@ -791,8 +813,15 @@ void value_sett::get_value_set_rec(
791
813
offsett offset = it->second ;
792
814
793
815
// adjust by offset
794
- if (offset && i.has_value ())
795
- *offset += *i;
816
+ if (offset && additional_offset.has_value ())
817
+ {
818
+ offset = simplify_expr (
819
+ plus_exprt{
820
+ *offset,
821
+ typecast_exprt::conditional_cast (
822
+ *additional_offset, offset->type ())},
823
+ ns);
824
+ }
796
825
else
797
826
offset.reset ();
798
827
@@ -873,7 +902,7 @@ void value_sett::get_value_set_rec(
873
902
dynamic_object.set_instance (location_number);
874
903
dynamic_object.valid ()=true_exprt ();
875
904
876
- insert (dest, dynamic_object, mp_integer{ 0 } );
905
+ insert (dest, dynamic_object, from_integer ( 0 , c_index_type ()) );
877
906
}
878
907
else if (statement==ID_cpp_new ||
879
908
statement==ID_cpp_new_array)
@@ -888,7 +917,7 @@ void value_sett::get_value_set_rec(
888
917
dynamic_object.set_instance (location_number);
889
918
dynamic_object.valid ()=true_exprt ();
890
919
891
- insert (dest, dynamic_object, mp_integer{ 0 } );
920
+ insert (dest, dynamic_object, from_integer ( 0 , c_index_type ()) );
892
921
}
893
922
else
894
923
insert (dest, exprt (ID_unknown, original_type));
@@ -1335,12 +1364,17 @@ void value_sett::get_reference_set_rec(
1335
1364
expr.id ()==ID_string_constant ||
1336
1365
expr.id ()==ID_array)
1337
1366
{
1367
+ exprt l1_expr =
1368
+ is_ssa_expr (expr) ? remove_level_2 (to_ssa_expr (expr)) : expr;
1369
+
1338
1370
if (
1339
1371
expr.type ().id () == ID_array &&
1340
1372
to_array_type (expr.type ()).element_type ().id () == ID_array)
1341
- insert (dest, expr);
1373
+ {
1374
+ insert (dest, l1_expr);
1375
+ }
1342
1376
else
1343
- insert (dest, expr, mp_integer{ 0 } );
1377
+ insert (dest, l1_expr, from_integer ( 0 , c_index_type ()) );
1344
1378
1345
1379
return ;
1346
1380
}
@@ -1366,7 +1400,7 @@ void value_sett::get_reference_set_rec(
1366
1400
{
1367
1401
const index_exprt &index_expr=to_index_expr (expr);
1368
1402
const exprt &array=index_expr.array ();
1369
- const exprt &offset= index_expr.index ();
1403
+ const exprt &index = index_expr.index ();
1370
1404
1371
1405
DATA_INVARIANT (
1372
1406
array.type ().id () == ID_array, " index takes array-typed operand" );
@@ -1394,22 +1428,24 @@ void value_sett::get_reference_set_rec(
1394
1428
from_integer (0 , c_index_type ()));
1395
1429
1396
1430
offsett o = a_it->second ;
1397
- const auto i = numeric_cast<mp_integer>(offset);
1398
1431
1399
- if (offset.is_zero ())
1400
- {
1401
- }
1402
- else if (i.has_value () && o)
1432
+ if (!index.is_zero () && o.has_value ())
1403
1433
{
1404
1434
auto size = pointer_offset_size (array_type.element_type (), ns);
1405
1435
1406
1436
if (!size.has_value () || *size == 0 )
1407
1437
o.reset ();
1408
1438
else
1409
- *o = *i * (*size);
1439
+ {
1440
+ o = simplify_expr (
1441
+ plus_exprt{
1442
+ *o,
1443
+ typecast_exprt::conditional_cast (
1444
+ mult_exprt{index, from_integer (*size, index.type ())},
1445
+ o->type ())},
1446
+ ns);
1447
+ }
1410
1448
}
1411
- else
1412
- o.reset ();
1413
1449
1414
1450
insert (dest, deref_index_expr, o);
1415
1451
}
@@ -1659,7 +1695,9 @@ void value_sett::assign_rec(
1659
1695
1660
1696
if (lhs.id ()==ID_symbol)
1661
1697
{
1662
- const irep_idt &identifier=to_symbol_expr (lhs).get_identifier ();
1698
+ const symbol_exprt lhs_l1 =
1699
+ is_ssa_expr (lhs) ? remove_level_2 (to_ssa_expr (lhs)) : to_symbol_expr (lhs);
1700
+ const irep_idt &identifier = lhs_l1.get_identifier ();
1663
1701
1664
1702
update_entry (
1665
1703
entryt{identifier, suffix}, lhs.type (), values_rhs, add_to_sets);
@@ -1858,8 +1896,11 @@ void value_sett::apply_code_rec(
1858
1896
(symbol_type.id () == ID_array &&
1859
1897
to_array_type (symbol_type).element_type ().id () == ID_pointer))
1860
1898
{
1899
+ const symbol_exprt symbol_l1 = is_ssa_expr (symbol)
1900
+ ? remove_level_2 (to_ssa_expr (symbol))
1901
+ : to_symbol_expr (symbol);
1861
1902
// assign the address of the failed object
1862
- if (auto failed = get_failed_symbol (symbol , ns))
1903
+ if (auto failed = get_failed_symbol (symbol_l1 , ns))
1863
1904
{
1864
1905
address_of_exprt address_of_expr (*failed, to_pointer_type (symbol_type));
1865
1906
assign (symbol, address_of_expr, ns, false , false );
0 commit comments