2323#include < util/prefix.h>
2424#include < util/range.h>
2525#include < util/simplify_expr.h>
26+ #include < util/ssa_expr.h>
2627#include < util/std_code.h>
2728#include < util/symbol.h>
2829#include < util/xml.h>
2930
3031#ifdef DEBUG
31- #include < iostream>
32- #include < util/format_expr.h>
33- #include < util/format_type.h>
32+ # include < iostream>
3433#endif
3534
3635#include " add_failed_symbols.h"
@@ -184,7 +183,7 @@ void value_sett::output(std::ostream &out, const std::string &indent) const
184183 stream << " <" << format (o) << " , " ;
185184
186185 if (o_it->second )
187- stream << *o_it->second ;
186+ stream << format ( *o_it->second ) ;
188187 else
189188 stream << ' *' ;
190189
@@ -261,7 +260,7 @@ exprt value_sett::to_expr(const object_map_dt::value_type &it) const
261260 od.object ()=object;
262261
263262 if (it.second )
264- od.offset () = from_integer ( *it.second , c_index_type ()) ;
263+ od.offset () = *it.second ;
265264
266265 od.type ()=od.object ().type ();
267266
@@ -352,17 +351,34 @@ bool value_sett::eval_pointer_offset(
352351 it=object_map.begin ();
353352 it!=object_map.end ();
354353 it++)
355- if (!it->second )
354+ {
355+ if (!it->second || !it->second ->is_constant ())
356356 return false ;
357357 else
358358 {
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;
359374 const exprt &object=object_numbering[it->first ];
360375 auto ptr_offset = compute_pointer_offset (object, ns);
361376
362377 if (!ptr_offset.has_value ())
363378 return false ;
364379
365- *ptr_offset += *it->second ;
380+ *ptr_offset +=
381+ numeric_cast_v<mp_integer>(to_constant_expr (*it->second ));
366382
367383 if (mod && *ptr_offset != previous_offset)
368384 return false ;
@@ -371,6 +387,7 @@ bool value_sett::eval_pointer_offset(
371387 previous_offset = *ptr_offset;
372388 mod=true ;
373389 }
390+ }
374391
375392 if (mod)
376393 expr.swap (new_expr);
@@ -556,8 +573,11 @@ void value_sett::get_value_set_rec(
556573 }
557574 else if (expr.id ()==ID_symbol)
558575 {
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);
561581
562582 if (entry_index.has_value ())
563583 make_union (dest, find_entry (*entry_index)->object_map );
@@ -623,7 +643,7 @@ void value_sett::get_value_set_rec(
623643 insert (
624644 dest,
625645 exprt (ID_null_object, to_pointer_type (expr.type ()).base_type ()),
626- mp_integer{ 0 } );
646+ from_integer ( 0 , c_index_type ()) );
627647 }
628648 else if (
629649 expr.type ().id () == ID_unsignedbv || expr.type ().id () == ID_signedbv)
@@ -655,7 +675,10 @@ void value_sett::get_value_set_rec(
655675
656676 if (op.is_zero ())
657677 {
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 ()));
659682 }
660683 else
661684 {
@@ -697,15 +720,14 @@ void value_sett::get_value_set_rec(
697720 expr.id_string () + " expected to have at least two operands" );
698721
699722 object_mapt pointer_expr_set;
700- std::optional<mp_integer> i ;
723+ std::optional<exprt> additional_offset ;
701724
702725 // special case for plus/minus and exactly one pointer
703726 std::optional<exprt> ptr_operand;
704727 if (
705728 expr.type ().id () == ID_pointer &&
706729 (expr.id () == ID_plus || expr.id () == ID_minus))
707730 {
708- bool non_const_offset = false ;
709731 for (const auto &op : expr.operands ())
710732 {
711733 if (op.type ().id () == ID_pointer)
@@ -718,24 +740,20 @@ void value_sett::get_value_set_rec(
718740
719741 ptr_operand = op;
720742 }
721- else if (!non_const_offset)
743+ else
722744 {
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;
729747 else
730748 {
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 ())} ;
734752 }
735753 }
736754 }
737755
738- if (ptr_operand.has_value () && i .has_value ())
756+ if (ptr_operand.has_value () && additional_offset .has_value ())
739757 {
740758 typet pointer_base_type =
741759 to_pointer_type (ptr_operand->type ()).base_type ();
@@ -746,18 +764,22 @@ void value_sett::get_value_set_rec(
746764
747765 if (!size.has_value () || (*size) == 0 )
748766 {
749- i .reset ();
767+ additional_offset .reset ();
750768 }
751769 else
752770 {
753- *i *= *size;
771+ additional_offset = mult_exprt{
772+ *additional_offset, from_integer (*size, additional_offset->type ())};
754773
755774 if (expr.id ()==ID_minus)
756775 {
757776 DATA_INVARIANT (
758777 to_minus_expr (expr).lhs () == *ptr_operand,
759778 " 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};
761783 }
762784 }
763785 }
@@ -791,8 +813,15 @@ void value_sett::get_value_set_rec(
791813 offsett offset = it->second ;
792814
793815 // 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+ }
796825 else
797826 offset.reset ();
798827
@@ -873,7 +902,7 @@ void value_sett::get_value_set_rec(
873902 dynamic_object.set_instance (location_number);
874903 dynamic_object.valid ()=true_exprt ();
875904
876- insert (dest, dynamic_object, mp_integer{ 0 } );
905+ insert (dest, dynamic_object, from_integer ( 0 , c_index_type ()) );
877906 }
878907 else if (statement==ID_cpp_new ||
879908 statement==ID_cpp_new_array)
@@ -888,7 +917,7 @@ void value_sett::get_value_set_rec(
888917 dynamic_object.set_instance (location_number);
889918 dynamic_object.valid ()=true_exprt ();
890919
891- insert (dest, dynamic_object, mp_integer{ 0 } );
920+ insert (dest, dynamic_object, from_integer ( 0 , c_index_type ()) );
892921 }
893922 else
894923 insert (dest, exprt (ID_unknown, original_type));
@@ -1335,12 +1364,17 @@ void value_sett::get_reference_set_rec(
13351364 expr.id ()==ID_string_constant ||
13361365 expr.id ()==ID_array)
13371366 {
1367+ exprt l1_expr =
1368+ is_ssa_expr (expr) ? remove_level_2 (to_ssa_expr (expr)) : expr;
1369+
13381370 if (
13391371 expr.type ().id () == ID_array &&
13401372 to_array_type (expr.type ()).element_type ().id () == ID_array)
1341- insert (dest, expr);
1373+ {
1374+ insert (dest, l1_expr);
1375+ }
13421376 else
1343- insert (dest, expr, mp_integer{ 0 } );
1377+ insert (dest, l1_expr, from_integer ( 0 , c_index_type ()) );
13441378
13451379 return ;
13461380 }
@@ -1366,7 +1400,7 @@ void value_sett::get_reference_set_rec(
13661400 {
13671401 const index_exprt &index_expr=to_index_expr (expr);
13681402 const exprt &array=index_expr.array ();
1369- const exprt &offset= index_expr.index ();
1403+ const exprt &index = index_expr.index ();
13701404
13711405 DATA_INVARIANT (
13721406 array.type ().id () == ID_array, " index takes array-typed operand" );
@@ -1394,22 +1428,24 @@ void value_sett::get_reference_set_rec(
13941428 from_integer (0 , c_index_type ()));
13951429
13961430 offsett o = a_it->second ;
1397- const auto i = numeric_cast<mp_integer>(offset);
13981431
1399- if (offset.is_zero ())
1400- {
1401- }
1402- else if (i.has_value () && o)
1432+ if (!index.is_zero () && o.has_value ())
14031433 {
14041434 auto size = pointer_offset_size (array_type.element_type (), ns);
14051435
14061436 if (!size.has_value () || *size == 0 )
14071437 o.reset ();
14081438 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+ }
14101448 }
1411- else
1412- o.reset ();
14131449
14141450 insert (dest, deref_index_expr, o);
14151451 }
@@ -1659,7 +1695,9 @@ void value_sett::assign_rec(
16591695
16601696 if (lhs.id ()==ID_symbol)
16611697 {
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 ();
16631701
16641702 update_entry (
16651703 entryt{identifier, suffix}, lhs.type (), values_rhs, add_to_sets);
@@ -1858,8 +1896,11 @@ void value_sett::apply_code_rec(
18581896 (symbol_type.id () == ID_array &&
18591897 to_array_type (symbol_type).element_type ().id () == ID_pointer))
18601898 {
1899+ const symbol_exprt symbol_l1 = is_ssa_expr (symbol)
1900+ ? remove_level_2 (to_ssa_expr (symbol))
1901+ : to_symbol_expr (symbol);
18611902 // 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))
18631904 {
18641905 address_of_exprt address_of_expr (*failed, to_pointer_type (symbol_type));
18651906 assign (symbol, address_of_expr, ns, false , false );
0 commit comments