method vexpr exp =
    debug "considering exp %a\n" Cil.d_exp exp ;
    match exp.enode with
      | BinOp((Div|Modas op,dividend,divisor,TInt(kind,_)) ->
          (* add assertion "divisor not zero" *)
          if self#is_DoDivMod () then
            self#queue_assertion
              (get_divmod_assertion
                 ~simplify_constants:(self#is_ConstFold ())
                 ~warning:(self#is_Warning ())
                 divisor)
          ;
          if (self#is_DoSignedOverflow ()) && (op = Div&& (isSigned kind) then
            begin
              (* treat the special case of signed division overflow
                 (no signed modulo overflow) *)

              self#queue_assertion
                (get_signed_div_assertion
                   ~simplify_constants:(self#is_ConstFold ())
                   ~warning:(self#is_Warning ())
                   dividend divisor)

            end
          ;
          DoChildren

      | BinOp((Shiftlt|Shiftrtas shiftop,loperand,roperand,TInt(kind,_)) ->

          if self#is_DoSignedOverflow () || self#is_DoUnsignedOverflow () then (
            let (a, isOk) =
              (* generate and check assertion on right operand of shift *)
              get_bitwise_shift_right_operand_assertion
                ~simplify_constants:(self#is_ConstFold ())
                ~warning:(self#is_Warning ())
                exp roperand
            in
              self#queue_assertion a ;
              if isOk (* right operand is correct:
                         otherwise no need to proceed with other assertions *)

              then
                (
                  (* assertions specific to signed shift *)
                  if (self#is_DoSignedOverflow ()) && (isSigned kind) then (

                    self#queue_assertion
                      (get_bitwise_shift_assertion
                         ~simplify_constants:(self#is_ConstFold ())
                         ~warning:(self#is_Warning ())
                         exp shiftop loperand roperand)
                  )
                  ;

                  (* assertions specific to unsigned shift *)
                  if self#is_DoUnsignedOverflow () &&
                    (shiftop = Shiftlt&& not(isSigned kind) then (
                      self#queue_assertion
                        (get_bitwise_lshift_unsigned_assertion
                           ~simplify_constants:(self#is_ConstFold ())
                           ~warning:(self#is_Warning ())
                           exp loperand roperand)
                    )
                )
          )
          ;
          DoChildren

      | BinOp((PlusA|MinusA|Mult)
                as op,loperand,roperand,TInt(kind,_)) when (isSigned kind) ->
          (* may be skipped if enclosing expression is a downcast to a signed type *)
          if (self#is_DoSignedOverflow ()) &&
            not(self#is_in_skip_set exp.eid SkipBoundingthen
              self#queue_assertion
                (get_multsubadd_assertion
                   ~simplify_constants:(self#is_ConstFold ())
                   ~warning:(self#is_Warning ())
                   exp op loperand roperand)
          ;
          DoChildren

      | BinOp((PlusA|MinusA|Mult)
                as op,loperand,roperand,TInt(kind,_)) when not(isSigned kind) ->
          if self#is_DoUnsignedOverflow () then
            self#queue_assertion
              (get_multsubadd_unsigned_assertion
                 ~simplify_constants:(self#is_ConstFold ())
                 ~warning:(self#is_Warning ())
                 exp op loperand roperand)
          ;
          DoChildren

      | UnOp(Neg,operand,TInt(kind,_)) when (isSigned kind) ->
          if self#is_DoSignedOverflow () then
            self#queue_assertion
              (get_uminus_assertion
                 ~simplify_constants:(self#is_ConstFold ())
                 ~warning:(self#is_Warning ())
                 operand)
          ;
          DoChildren

      (* Note: if unary minus on unsigned integer is to be understood as
         "subtracting the promoted value from the largest value
         of the promoted type and adding one"
         the result is always representable so no overflow
      *)


      | Lval lval ->
          (* left values are checked for valid access *)
          if self#is_DoMemAccess () then (
            debug "exp %a is an lval: validity of potential mem access checked\n"
              Cil.d_exp exp ;
            self#queue_assertion (get_lval_assertion lval)
          )
          ;
          DoChildren

      | CastE (TInt (kind,_) as typ, e) when (isSigned kind) ->
          if self#is_DoDownCast () then (
            let downcast_asserts =
              get_downcast_assertion
                ~simplify_constants:(self#is_ConstFold ())
                ~warning:(self#is_Warning ())
                typ e
            in match downcast_asserts with
              | [] -> ()
              | _ ->
                  self#queue_assertion downcast_asserts
                  ;
                  self#add_to_skip_set e.eid SkipBounding
                    (* expression should be skipped w.r.t
                       signed mult/add/sub arithmetic overflow *)

          )
          ;
        DoChildren

    | StartOf _lval ->
        if self#is_DoMemAccess () then
          self#queue_assertion
            [ (Logic_const.pvalid (translate_C_expr_to_term ~cast:false exp), None) ]
        ;
        DoChildren

    | AddrOf _
    | Info _
    | UnOp _
    | Const _
    | CastE _
    | BinOp _ -> DoChildren


    | SizeOf _
    | SizeOfE _
    | SizeOfStr _
    | AlignOf _
    | AlignOfE _ -> SkipChildren