Skip to content

Commit a202116

Browse files
authored
Merge pull request #7570 from tautschnig/feature/simp-overflow-result-minus
Simplify overflow-result-minus over (X + n), X
2 parents cc64b04 + ff20d39 commit a202116

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef __GNUC__
2+
_Bool __builtin_sub_overflow();
3+
#endif
4+
5+
int main(void)
6+
{
7+
__CPROVER_size_t result;
8+
int x;
9+
__CPROVER_assert(
10+
!__builtin_sub_overflow(
11+
(__CPROVER_size_t)((char *)&x + 1), (__CPROVER_size_t)&x, &result),
12+
"cannot overflow");
13+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
simplify.c
3+
4+
^Generated 1 VCC\(s\), 0 remaining after simplification$
5+
^VERIFICATION SUCCESSFUL$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring

src/util/simplify_expr.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,58 @@ simplify_exprt::simplify_overflow_result(const overflow_result_exprt &expr)
25902590
if(op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
25912591
return unchanged(expr);
25922592

2593+
// a special case of overflow-minus checking with operands (X + n) and X
2594+
if(expr.id() == ID_overflow_result_minus)
2595+
{
2596+
const exprt &tc_op0 = skip_typecast(expr.op0());
2597+
const exprt &tc_op1 = skip_typecast(expr.op1());
2598+
2599+
if(auto sum = expr_try_dynamic_cast<plus_exprt>(tc_op0))
2600+
{
2601+
if(skip_typecast(sum->op0()) == tc_op1 && sum->operands().size() == 2)
2602+
{
2603+
optionalt<exprt> offset;
2604+
if(sum->type().id() == ID_pointer)
2605+
{
2606+
offset = std::move(simplify_pointer_offset(
2607+
pointer_offset_exprt{*sum, expr.op0().type()})
2608+
.expr);
2609+
if(offset->id() == ID_pointer_offset)
2610+
return unchanged(expr);
2611+
}
2612+
else
2613+
offset = std::move(
2614+
simplify_typecast(typecast_exprt{sum->op1(), expr.op0().type()})
2615+
.expr);
2616+
2617+
exprt offset_op = skip_typecast(*offset);
2618+
if(
2619+
offset_op.type().id() != ID_signedbv &&
2620+
offset_op.type().id() != ID_unsignedbv)
2621+
{
2622+
return unchanged(expr);
2623+
}
2624+
2625+
const std::size_t width =
2626+
to_bitvector_type(expr.op0().type()).get_width();
2627+
const integer_bitvector_typet bv_type{op_type_id, width};
2628+
2629+
or_exprt not_representable{
2630+
binary_relation_exprt{
2631+
offset_op,
2632+
ID_lt,
2633+
from_integer(bv_type.smallest(), offset_op.type())},
2634+
binary_relation_exprt{
2635+
offset_op,
2636+
ID_gt,
2637+
from_integer(bv_type.largest(), offset_op.type())}};
2638+
2639+
return struct_exprt{
2640+
{*offset, simplify_rec(not_representable)}, expr.type()};
2641+
}
2642+
}
2643+
}
2644+
25932645
if(!expr.op0().is_constant() || !expr.op1().is_constant())
25942646
return unchanged(expr);
25952647

0 commit comments

Comments
 (0)