let get_bitwise_lshift_unsigned_assertion
~simplify_constants:simplify_constants
~warning:warning
exp loperand roperand =
(* result should be representable in result type *)
let t = Cil.typeOf exp in
let size = bitsSizeOf t in
let maxValResult =
(* compute greatest reprensentable "size bits" unsigned integer *)
max_unsigned_number size
in let ov_assertion () =
let term = translate_C_expr_to_term ~cast:false exp
in (* unsigned result is representable in result type if loperand times 2^roperand
(where loperand and roperand are nonnegative),
which should be equal to term (obtained with a shift),
is less than the maximal value for the result type *)
(* no cast to int since we check "true result" which is an integer*)
Logic_const.prel (Rle, term, Cil.lconstant maxValResult)
in let problem_with_ov_assertion () =
if simplify_constants then (
match get_expr_val loperand, get_expr_val roperand with
| None,_
| _, None -> (false,false)
| Some lval64, Some rval64 ->
(* both operands are constant:
check result is representable in result type *)
let result_true_val = Int.shift_left lval64 rval64 in
if Int.gt result_true_val maxValResult then
(true,false)(* constant operators and assertion does not hold *)
else (true,true)(* constant operators and assertion holds *)
) else (false,false)
in
match problem_with_ov_assertion () with
| (true,false) ->
let assertion = ov_assertion () in
if warning then
rte_warn
fmt_warn_shift_assert3
d_predicate_named assertion;
[ assertion, Some Property_status.False_if_reachable ]
| (true,true) -> [ ]
| (false,_) -> [ ov_assertion (), None ]