@@ -105,6 +105,7 @@ class goto_checkt
105105 void bounds_check (const index_exprt &, const guardt &);
106106 void div_by_zero_check (const div_exprt &, const guardt &);
107107 void mod_by_zero_check (const mod_exprt &, const guardt &);
108+ void mod_overflow_check (const mod_exprt &, const guardt &);
108109 void undefined_shift_check (const shift_exprt &, const guardt &);
109110 void pointer_rel_check (const exprt &, const guardt &);
110111 void pointer_overflow_check (const exprt &, const guardt &);
@@ -328,7 +329,7 @@ void goto_checkt::mod_by_zero_check(
328329 const mod_exprt &expr,
329330 const guardt &guard)
330331{
331- if (!enable_div_by_zero_check)
332+ if (!enable_div_by_zero_check || mode == ID_java )
332333 return ;
333334
334335 // add divison by zero subgoal
@@ -349,6 +350,37 @@ void goto_checkt::mod_by_zero_check(
349350 guard);
350351}
351352
353+ // / check a mod expression for the case INT_MIN % -1
354+ void goto_checkt::mod_overflow_check (const mod_exprt &expr, const guardt &guard)
355+ {
356+ if (!enable_signed_overflow_check)
357+ return ;
358+
359+ const auto &type = expr.type ();
360+
361+ if (type.id () == ID_signedbv)
362+ {
363+ // INT_MIN % -1 is, in principle, defined to be zero in
364+ // ANSI C, C99, C++98, and C++11. Most compilers, however,
365+ // fail to produce 0, and in some cases generate an exception.
366+ // C11 explicitly makes this case undefined.
367+
368+ notequal_exprt int_min_neq (
369+ expr.op0 (), to_signedbv_type (type).smallest_expr ());
370+
371+ notequal_exprt minus_one_neq (
372+ expr.op1 (), from_integer (-1 , expr.op1 ().type ()));
373+
374+ add_guarded_claim (
375+ or_exprt (int_min_neq, minus_one_neq),
376+ " result of signed mod is not representable" ,
377+ " overflow" ,
378+ expr.find_source_location (),
379+ expr,
380+ guard);
381+ }
382+ }
383+
352384void goto_checkt::conversion_check (
353385 const exprt &expr,
354386 const guardt &guard)
@@ -564,11 +596,6 @@ void goto_checkt::integer_overflow_check(
564596
565597 return ;
566598 }
567- else if (expr.id ()==ID_mod)
568- {
569- // these can't overflow
570- return ;
571- }
572599 else if (expr.id ()==ID_unary_minus)
573600 {
574601 if (type.id ()==ID_signedbv)
@@ -1544,6 +1571,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
15441571 else if (expr.id ()==ID_mod)
15451572 {
15461573 mod_by_zero_check (to_mod_expr (expr), guard);
1574+ mod_overflow_check (to_mod_expr (expr), guard);
15471575 }
15481576 else if (expr.id ()==ID_plus || expr.id ()==ID_minus ||
15491577 expr.id ()==ID_mult ||
0 commit comments