let do_assign_abstract_value_to_loc ~with_alarms state lv loc_lv exp =
    assert (not (Cvalue.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 bit-field. Otherwise, the
                 cast is explicit thanks to Cil and no truncation is
                 necessary. *)

      try
        (* if it is a bit-field, the size is statically known. *)
        let size = Int_Base.project loc_lv.size in
        try
          ignore (V.project_ival exp);
          cast_lval_bitfield lv size exp
        with
        | V.Not_based_on_null (* from [project_ival] *) ->
            (* The exp is a pointer: check there are enough bits in
               the bit-field to contain it. *)

            if Int.compare size (Int.of_int (sizeofpointer ())) >= 0
              || V.is_imprecise exp
            then exp
            else begin
              Value_parameters.result 
                "casting address to a bit-field 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======="
          Cvalue.Model.pretty state;
        warning_once_current
          "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 ~for_writing:true loc_lv in
    let value =
      Cvalue.Model.add_binding ~with_alarms ~exact
        state loc_lv exp
    in
   value