let do_assign_abstract_value_to_loc ~with_alarms state lv loc_lv exp =
    assert (not (Cvalue_type.V.is_bottom exp));
    (* Or one may propagate bottoms uselessly for too long. *)
    let exp = (* truncate the value if the [lv] is too small: this may
                 happen when the [lv] is a bitfield. Otherwise, the
                 cast is explicit thanks to Cil and no truncation is
                 necessary. *)

      try
        (* if it is a bitfield, the size is statically known. *)
        let size = Int_Base.project loc_lv.size in
        try
          let old_ival = V.find_ival exp in
          let exp =
            V.inject_ival (* Inject on null as [find_ival] did not raise
                                       [Not_based_on_null] *)

              (Ival.cast
                 ~size
                 ~signed:(signof_typeof_lval lv)
                 (* the sign can be computed on integral types. *)
                 ~value:old_ival)
          in
          exp
        with
        | V.Not_based_on_null (* from [find_ival] *) ->
            (* The exp is a pointer: check there are enough bits in
               the bitfield to contain it. *)

            if Int.compare size (Int.of_int (sizeofpointer ())) >= 0
              || V.is_top exp
            then exp
            else begin
              Value_parameters.result "casting address to a bitfield of %s bits: this is smaller than sizeof(void*)" (Int.to_string size);
              V.topify_arith_origin exp
            end
        | Neither_Int_Nor_Enum_Nor_Pointer
            (* from [signof_typeof_lval] *) -> exp
      with
      | Int_Base.Error_Top | Int_Base.Error_Bottom ->
          (* from [project]: size is not known  *)
          exp
    in
    let pretty_org fmt org = if not (Origin.is_top org) then
      Format.fprintf fmt " because of %a" Origin.pretty org
    in
    (match loc_lv.loc with
    | Location_Bits.Top (Location_Bits.Top_Param.Top, orig) ->
        Value_parameters.result 
          "State before degeneration:@\n======%a@\n======="
          Relations_type.Model.pretty state;
        Value_parameters.warning ~once:true
          "writing at a completely unknown address@[%a@].@\nAborting."
          pretty_org orig;
        do_degenerate (Some lv)

    | Location_Bits.Top((Location_Bits.Top_Param.Set _) as param,orig) ->
        Value_parameters.result ~current:true ~once:true
          "writing somewhere in @[%a@]@[%a@]."
          Location_Bits.Top_Param.pretty param
          pretty_org orig
    | Location_Bits.Map _ -> (* everything is normal *) ());
    let exact = valid_cardinal_zero_or_one loc_lv in
    let value =
      Relations_type.Model.add_binding ~with_alarms ~exact
        state loc_lv exp
    in
   value