@@ -12,14 +12,14 @@ Author: Daniel Kroening, kroening@kroening.com
1212#include " goto_convert_class.h"
1313
1414#include < util/arith_tools.h>
15+ #include < util/bitvector_expr.h>
16+ #include < util/c_types.h>
1517#include < util/expr_util.h>
1618#include < util/fresh_symbol.h>
1719#include < util/mathematical_types.h>
1820#include < util/std_expr.h>
1921#include < util/symbol.h>
2022
21- #include < util/c_types.h>
22-
2323#include < ansi-c/c_expr.h>
2424
2525bool goto_convertt::has_function_call (const exprt &expr)
@@ -589,91 +589,65 @@ void goto_convertt::remove_overflow(
589589 const exprt &rhs = expr.rhs ();
590590 const exprt &result = expr.result ();
591591
592- // actual logic implementing the operators: perform operations on signed
593- // bitvector types of sufficiently large size to hold the result
594- auto const make_operation = [&statement](exprt lhs, exprt rhs) -> exprt {
595- std::size_t lhs_ssize = to_bitvector_type (lhs.type ()).get_width ();
596- if (lhs.type ().id () == ID_unsignedbv)
597- ++lhs_ssize;
598- std::size_t rhs_ssize = to_bitvector_type (rhs.type ()).get_width ();
599- if (rhs.type ().id () == ID_unsignedbv)
600- ++rhs_ssize;
601-
602- if (statement == ID_overflow_plus)
603- {
604- std::size_t ssize = std::max (lhs_ssize, rhs_ssize) + 1 ;
605- integer_bitvector_typet ssize_type{ID_signedbv, ssize};
606- return plus_exprt{typecast_exprt{lhs, ssize_type},
607- typecast_exprt{rhs, ssize_type}};
608- }
609- else if (statement == ID_overflow_minus)
592+ if (result.type ().id () != ID_pointer)
593+ {
594+ // result of the arithmetic operation is _not_ used, just evaluate side
595+ // effects
596+ exprt tmp = result;
597+ clean_expr (tmp, dest, mode, false );
598+
599+ // the is-there-an-overflow result may be used
600+ if (result_is_used)
610601 {
611- std::size_t ssize = std::max (lhs_ssize, rhs_ssize) + 1 ;
612- integer_bitvector_typet ssize_type{ID_signedbv, ssize};
613- return minus_exprt{typecast_exprt{lhs, ssize_type},
614- typecast_exprt{rhs, ssize_type}};
602+ binary_overflow_exprt overflow_check{
603+ typecast_exprt::conditional_cast (lhs, result.type ()),
604+ statement,
605+ typecast_exprt::conditional_cast (rhs, result.type ())};
606+ overflow_check.add_source_location () = expr.source_location ();
607+ expr.swap (overflow_check);
615608 }
616609 else
617- {
618- INVARIANT (
619- statement == ID_overflow_mult,
620- " the three overflow operations are add, sub and mul" );
621- std::size_t ssize = lhs_ssize + rhs_ssize;
622- integer_bitvector_typet ssize_type{ID_signedbv, ssize};
623- return mult_exprt{typecast_exprt{lhs, ssize_type},
624- typecast_exprt{rhs, ssize_type}};
625- }
626- };
627-
628- // Generating the following sequence of statements:
629- // large_signedbv tmp = (large_signedbv)lhs OP (large_signedbv)rhs;
630- // *result = (result_type)tmp; // only if result is a pointer
631- // (large_signedbv)(result_type)tmp != tmp;
632- // This performs the operation (+, -, *) on a signed bitvector type of
633- // sufficiently large width to store the precise result, cast to result
634- // type, check if the cast result is not equivalent to the full-length
635- // result.
636- auto operation = make_operation (lhs, rhs);
637- // Disable overflow checks as the operation cannot overflow on the larger
638- // type
639- operation.add_source_location () = expr.source_location ();
640- operation.add_source_location ().add_pragma (" disable:signed-overflow-check" );
641-
642- make_temp_symbol (operation, " large_bv" , dest, mode);
643-
644- optionalt<typet> result_type;
645- if (result.type ().id () == ID_pointer)
646- {
647- result_type = to_pointer_type (result.type ()).base_type ();
648- code_assignt result_assignment{dereference_exprt{result},
649- typecast_exprt{operation, *result_type},
650- expr.source_location ()};
651- convert_assign (result_assignment, dest, mode);
610+ expr.make_nil ();
652611 }
653612 else
654613 {
655- result_type = result.type ();
656- // evaluate side effects
657- exprt tmp = result;
658- clean_expr (tmp, dest, mode, false ); // result _not_ used
659- }
660-
661- if (result_is_used)
662- {
663- typecast_exprt inner_tc{operation, *result_type};
664- inner_tc.add_source_location () = expr.source_location ();
665- inner_tc.add_source_location ().add_pragma (" disable:conversion-check" );
666- typecast_exprt outer_tc{inner_tc, operation.type ()};
667- outer_tc.add_source_location () = expr.source_location ();
668- outer_tc.add_source_location ().add_pragma (" disable:conversion-check" );
614+ const typet &arith_type = to_pointer_type (result.type ()).base_type ();
615+ irep_idt arithmetic_operation =
616+ statement == ID_overflow_plus
617+ ? ID_plus
618+ : statement == ID_overflow_minus
619+ ? ID_minus
620+ : statement == ID_overflow_mult ? ID_mult : ID_nil;
621+ CHECK_RETURN (arithmetic_operation != ID_nil);
622+ exprt overflow_with_result = overflow_result_exprt{
623+ typecast_exprt::conditional_cast (lhs, arith_type),
624+ arithmetic_operation,
625+ typecast_exprt::conditional_cast (rhs, arith_type)};
626+ overflow_with_result.add_source_location () = expr.source_location ();
627+
628+ if (result_is_used)
629+ make_temp_symbol (overflow_with_result, " overflow_result" , dest, mode);
630+
631+ const struct_typet::componentst &result_comps =
632+ to_struct_type (overflow_with_result.type ()).components ();
633+ CHECK_RETURN (result_comps.size () == 2 );
634+ code_assignt result_assignment{
635+ dereference_exprt{result},
636+ typecast_exprt::conditional_cast (
637+ member_exprt{overflow_with_result, result_comps[0 ]}, arith_type),
638+ expr.source_location ()};
639+ convert_assign (result_assignment, dest, mode);
669640
670- notequal_exprt overflow_check{outer_tc, operation};
671- overflow_check.add_source_location () = expr.source_location ();
641+ if (result_is_used)
642+ {
643+ member_exprt overflow_check{overflow_with_result, result_comps[1 ]};
644+ overflow_check.add_source_location () = expr.source_location ();
672645
673- expr.swap (overflow_check);
646+ expr.swap (overflow_check);
647+ }
648+ else
649+ expr.make_nil ();
674650 }
675- else
676- expr.make_nil ();
677651}
678652
679653void goto_convertt::remove_side_effect (
0 commit comments