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
    (* removed, see BTS#567: no point in asserting validity
       of first cell of an array simply because its address
       is taken as &tab[0] *)

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

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


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