diff --git a/src/kernel_internals/typing/mergecil.ml b/src/kernel_internals/typing/mergecil.ml
index ed8914b346ec1c47a40f6f8dbb8cf3c21b932e12..ef0d0d96c0390db868e258835bb64e7d59cdf16a 100644
--- a/src/kernel_internals/typing/mergecil.ml
+++ b/src/kernel_internals/typing/mergecil.ml
@@ -1151,7 +1151,7 @@ and equalModuloPackedAlign attrs1 attrs2 =
    Raises [Failure] if the fields are not equivalent.
    If [mustCheckOffsets] is true, then there is already a difference in the
    composite type, so each field must be checked. *)
-and checkFieldsEqualModuloPackedAlign ~mustCheckOffsets typ_ci1 typ_ci2 f1 f2 =
+and checkFieldsEqualModuloPackedAlign ~mustCheckOffsets f1 f2 =
   if f1.fbitfield <> f2.fbitfield then
     raise (Failure "different bitfield info");
   if mustCheckOffsets || not (equal_attributes_for_merge f1.fattr f2.fattr) then
@@ -1160,11 +1160,8 @@ and checkFieldsEqualModuloPackedAlign ~mustCheckOffsets typ_ci1 typ_ci2 f1 f2 =
        in which case the difference may be safely ignored *)
     begin
       try
-        let offs1, width1 =
-          Cil.bitsOffset typ_ci1 (Field (f1, NoOffset))
-        in
-        let offs2, width2 =
-          Cil.bitsOffset typ_ci2 (Field (f2, NoOffset))
+        let offs1, width1 = Cil.fieldBitsOffset f1
+        and offs2, width2 = Cil.fieldBitsOffset f2
         in
         if not (equalModuloPackedAlign f1.fattr f2.fattr)
         || offs1 <> offs2 || width1 <> width2 then
@@ -1252,12 +1249,9 @@ and matchCompInfo (oldfidx: int) (oldci: compinfo)
                      [%a] vs [%a]"
                     pp_attrs attrs pp_attrs oldattrs))
         in
-        let typ_ci = TComp(ci, {scache = Not_Computed}, []) in
-        let typ_oldci = TComp(oldci, {scache = Not_Computed}, []) in
         List.iter2
           (fun oldf f ->
-             checkFieldsEqualModuloPackedAlign ~mustCheckOffsets
-               typ_ci typ_oldci f oldf;
+             checkFieldsEqualModuloPackedAlign ~mustCheckOffsets f oldf;
              (* Make sure the types are compatible *)
              (* Note: 6.2.7 §1 states that the names of the fields should be the
                 same. We do not force this for now, but could do it. *)
diff --git a/src/kernel_services/analysis/bit_utils.ml b/src/kernel_services/analysis/bit_utils.ml
index ce6b804ffac0b2a688bd0bdade62d83f9e640d84..0ed0755ee7f9f646292cc2f0ea738fcbf8f238d4 100644
--- a/src/kernel_services/analysis/bit_utils.ml
+++ b/src/kernel_services/analysis/bit_utils.ml
@@ -248,8 +248,7 @@ let rec pretty_bits_internal env bfinfo typ ~align ~start ~stop =
         try
           let full_fields_to_print = List.fold_left
             (fun acc field ->
-               let current_offset = Field (field,NoOffset) in
-               let start_o,width_o = bitsOffset typ current_offset in
+               let start_o,width_o = fieldBitsOffset field in
                let start_o,width_o =
                  Integer.of_int start_o, Integer.of_int width_o
                in
diff --git a/src/kernel_services/ast_data/cil_types.mli b/src/kernel_services/ast_data/cil_types.mli
index cc512a4d869da24ad9799974c91b3fd315a50cb0..50828024e849a3d79659f839306c2950c6aa85ac 100644
--- a/src/kernel_services/ast_data/cil_types.mli
+++ b/src/kernel_services/ast_data/cil_types.mli
@@ -433,13 +433,13 @@ and fieldinfo = {
       expression. *)
 
   mutable fsize_in_bits: int option;
-  (** (Deprecated. Use {!Cil.bitsOffset} instead.) Similar to [fbitfield] for
-      all types of fields.
+  (** (Deprecated. Use {!Cil.fieldBitsOffset} or {!Cil.bitsOffset} instead.)
+      Similar to [fbitfield] for all types of fields.
       @deprecated only Jessie uses this *)
 
   mutable foffset_in_bits: int option;
   (** Offset at which the field starts in the structure. Do not read directly,
-      but use {!Cil.bitsOffset} instead. *)
+      but use {!Cil.fieldBitsOffset} or {!Cil.bitsOffset} instead. *)
 
   mutable fpadding_in_bits: int option;
   (** (Deprecated.) Store the size of the padding that follows the field, if any.
diff --git a/src/kernel_services/ast_printing/cil_printer.ml b/src/kernel_services/ast_printing/cil_printer.ml
index 6567141ad0a51d2dbd1cff12ccae4751edb12368..30a1603c6ada298959263b39055535650a6e826c 100644
--- a/src/kernel_services/ast_printing/cil_printer.ml
+++ b/src/kernel_services/ast_printing/cil_printer.ml
@@ -1833,10 +1833,11 @@ class cil_printer () = object (self)
       self#attributes fi.fattr;
     if Kernel.(is_debug_key_enabled dkey_print_field_offsets) then
       try
-        let (offset, size) = Cil.bitsOffset fi.ftype (Field (fi, NoOffset)) in
+        let (offset, size) = Cil.fieldBitsOffset fi in
         let first = offset in
-        let last = offset + size - 1 in
-        fprintf fmt " /* bits %d .. %d */" first last
+        let last = if size > 0 then Some (offset + size - 1) else None in
+        let pp_opt fmt = Pretty_utils.pp_opt ~none:"" Format.pp_print_int fmt in
+        fprintf fmt " /* bits %d .. %a */" first pp_opt last
       with Cil.SizeOfError _ -> ()
 
   method private opt_funspec fmt funspec =
diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml
index 6f90ae11d735c7169a1ca90de6324221969f744b..f7bdda90abaa439fad1402a1d5e266322c403f1b 100644
--- a/src/kernel_services/ast_queries/cil.ml
+++ b/src/kernel_services/ast_queries/cil.ml
@@ -4419,6 +4419,29 @@ and sizeOf ~loc t =
     integer ~loc ((bitsSizeOf t) lsr 3)
   with SizeOfError _ -> new_exp ~loc (SizeOf(t))
 
+and fieldBitsOffset (f : fieldinfo) : int * int =
+  if  not f.fcomp.cstruct (* union *) then
+    0, bitsSizeOf f.ftype
+  else begin
+    if f.foffset_in_bits = None then begin
+      let aux ~last acc fi =
+        let acc' = offsetOfFieldAcc ~last ~fi ~sofar:acc in
+        fi.fsize_in_bits <- Some acc'.oaLastFieldWidth;
+        fi.foffset_in_bits <- Some acc'.oaLastFieldStart;
+        acc'
+      in
+      ignore (
+        fold_struct_fields aux
+          { oaFirstFree      = 0;
+            oaLastFieldStart = 0;
+            oaLastFieldWidth = 0;
+            oaPrevBitPack    = None }
+          f.fcomp.cfields
+      );
+    end;
+    Extlib.the f.foffset_in_bits, Extlib.the f.fsize_in_bits
+  end
+
 and bitsOffset (baset: typ) (off: offset) : int * int =
   let rec loopOff (baset: typ) (width: int) (start: int) = function
       NoOffset -> start, width
@@ -4432,38 +4455,13 @@ and bitsOffset (baset: typ) (off: offset) : int * int =
         let bitsbt = bitsSizeOf bt in
         loopOff bt bitsbt (start + ei * bitsbt) off
       end
-    | Field(f, off) when not f.fcomp.cstruct (* union *) ->
+    | Field(f, off) ->
       if check_invariants then
-        assert (match unrollType baset with
-            | TComp (ci, _, _) -> ci == f.fcomp
-            | _ -> false);
+        (match unrollType baset with
+         | TComp (ci, _, _) -> assert (ci == f.fcomp)
+         | _ -> assert false);
+      let offsbits, size = fieldBitsOffset f in
       (* All union fields start at offset 0 *)
-      loopOff f.ftype (bitsSizeOf f.ftype) start off
-
-    | Field(f, off) (* struct *) ->
-      if check_invariants then
-        assert (match unrollType baset with
-            | TComp (ci, _, _) -> ci == f.fcomp
-            | _ -> false);
-      if f.foffset_in_bits = None then begin
-        let aux ~last acc fi =
-          let acc' = offsetOfFieldAcc ~last ~fi ~sofar:acc in
-          fi.fsize_in_bits <- Some acc'.oaLastFieldWidth;
-          fi.foffset_in_bits <- Some acc'.oaLastFieldStart;
-          acc'
-        in
-        ignore (
-          fold_struct_fields aux
-            { oaFirstFree      = 0;
-              oaLastFieldStart = 0;
-              oaLastFieldWidth = 0;
-              oaPrevBitPack    = None }
-            f.fcomp.cfields
-        );
-      end;
-      let offsbits, size =
-        Extlib.the f.foffset_in_bits, Extlib.the f.fsize_in_bits
-      in
       loopOff f.ftype size (start + offsbits) off
   in
   loopOff baset (bitsSizeOf baset) 0 off
diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli
index 3bf916dcb66519cd830e6f6caaf5ab0d4d483d3f..60d2376a79df9ff31ac26fa6f68d96753423999d 100644
--- a/src/kernel_services/ast_queries/cil.mli
+++ b/src/kernel_services/ast_queries/cil.mli
@@ -2185,6 +2185,13 @@ val intOfAttrparam: attrparam -> int option
  * this after you call {!Cil.initCIL}. *)
 val bitsOffset: typ -> offset -> int * int
 
+(** Give a field, returns the number of bits from the structure or union
+ * containing the field and the width (also expressed in bits) for the subobject
+ * denoted by the field. Raises {!Cil.SizeOfError} when it cannot compute
+ * the size. This function is architecture dependent, so you should only call
+ * this after you call {!Cil.initCIL}. *)
+val fieldBitsOffset: fieldinfo -> int * int
+
 (** Like map but try not to make a copy of the list *)
 val mapNoCopy: ('a -> 'a) -> 'a list -> 'a list
 
diff --git a/src/plugins/value/domains/cvalue/builtins_memory.ml b/src/plugins/value/domains/cvalue/builtins_memory.ml
index 6d266b4f8a2cc85a28a4fffd1757128a5b45db9f..9f0e325e07c67523804413820be3da68a0b32379 100644
--- a/src/plugins/value/domains/cvalue/builtins_memory.ml
+++ b/src/plugins/value/domains/cvalue/builtins_memory.ml
@@ -470,10 +470,9 @@ let memset_typ_offsm_int full_typ i =
           (* Do not produce NaN or infinites here (unless they are accepted
              by the engine). *)
           if Fval.is_finite f = True then update size v' else update size v
-        | TComp ({ cstruct = true ; cfields = l}, _, _) as tcomp -> (* struct *)
+        | TComp ({ cstruct = true ; cfields = l}, _, _) -> (* struct *)
           let aux_field offsm fi =
-            let field = Field (fi, NoOffset) in
-            let offset_fi = Int.of_int (fst (Cil.bitsOffset tcomp field)) in
+            let offset_fi = Int.of_int (fst (Cil.fieldBitsOffset fi)) in
             aux fi.ftype (Int.add offset offset_fi) offsm
           in
           List.fold_left aux_field offsm l
diff --git a/src/plugins/value/legacy/eval_terms.ml b/src/plugins/value/legacy/eval_terms.ml
index b3893e9dc18e6b3dfc5a5623c1221f851f26176d..7844e81a2ceb93868468ff78f3e64ff7eb2d093f 100644
--- a/src/plugins/value/legacy/eval_terms.ml
+++ b/src/plugins/value/legacy/eval_terms.ml
@@ -1250,7 +1250,7 @@ and eval_toffset ~alarm_mode env typ toffset =
 
   | TField (fi, remaining) ->
     let size_current default =
-      try Ival.of_int (fst (Cil.bitsOffset typ (Field(fi, NoOffset))))
+      try Ival.of_int (fst (Cil.fieldBitsOffset fi))
       with Cil.SizeOfError _ -> default
     in
     let attrs = Cil.filter_qualifier_attributes (Cil.typeAttrs typ) in
diff --git a/src/plugins/value/values/main_locations.ml b/src/plugins/value/values/main_locations.ml
index 30069d98a9ef24037534ee12cdc43ccb1fa508d0..298f1b1698650bbc4b667439083ee6c96c211b04 100644
--- a/src/plugins/value/values/main_locations.ml
+++ b/src/plugins/value/values/main_locations.ml
@@ -20,8 +20,6 @@
 (*                                                                        *)
 (**************************************************************************)
 
-open Cil_types
-
 module PLoc = struct
 
   type value = Cvalue.V.t
@@ -70,10 +68,10 @@ module PLoc = struct
 
   let no_offset = Precise Precise_locs.offset_zero
 
-  let forward_field typ field = function
+  let forward_field _typ field = function
     | Precise offset ->
       begin try
-          let field = fst (Cil.bitsOffset typ (Field (field, NoOffset))) in
+          let field = fst (Cil.fieldBitsOffset field) in
           let field_i = Integer.of_int field in
           Precise (Precise_locs.shift_offset_by_singleton field_i offset)
         with Cil.SizeOfError _ -> Precise (Precise_locs.offset_top)
@@ -189,12 +187,12 @@ module PLoc = struct
       then `Bottom
       else `Value (new_mem, Precise new_off)
 
-  let backward_field typ field = function
+  let backward_field _typ field = function
     | Imprecise _ as x -> `Value x
     | Precise offset ->
       begin try
           let offset_ival = Precise_locs.imprecise_offset offset in
-          let field = fst (Cil.bitsOffset typ (Field (field, NoOffset))) in
+          let field = fst (Cil.fieldBitsOffset field) in
           let field_i = Integer.of_int (- field) in
           let ival = Ival.add_singleton_int field_i offset_ival in
           if Ival.is_bottom ival
diff --git a/src/plugins/wp/Layout.ml b/src/plugins/wp/Layout.ml
index d1e8b5795328c83d795393ebc8b699a997b0749b..5615d0bd561ba28da9cc730684a02a61718cb383 100644
--- a/src/plugins/wp/Layout.ml
+++ b/src/plugins/wp/Layout.ml
@@ -99,15 +99,12 @@ struct
       let typ = TComp(comp,Cil.empty_size_cache (),[]) in
       H.add cache comp typ ; typ
 
-  let field_offset cache fd =
-    let typ = typ_of_comp cache fd.fcomp in
-    let offset = Cil_types.(Field(fd,NoOffset)) in
-    Cil.bitsOffset typ offset
+  let field_offset _cache fd =
+    Cil.fieldBitsOffset fd
 
   let range_field cache fd =
     let typ = typ_of_comp cache fd.fcomp in
-    let offset = Cil_types.(Field(fd,NoOffset)) in
-    Cil.bitsOffset typ offset , Cil.bitsSizeOf typ
+    Cil.fieldBitsOffset fd, Cil.bitsSizeOf typ
 
   let range_index typ n =
     let len = Cil.bitsSizeOf typ * n in (0 , len) , len
diff --git a/src/plugins/wp/ctypes.ml b/src/plugins/wp/ctypes.ml
index 1511490737dca9c73d0586cd5b47119abeb27fab..cb2d079f01617cb9654a9320702f8fe1cab9adf9 100644
--- a/src/plugins/wp/ctypes.ml
+++ b/src/plugins/wp/ctypes.ml
@@ -489,12 +489,7 @@ let bits_sizeof_object = function
   | C_array ainfo -> bits_sizeof_array ainfo
 
 let field_offset fd =
-  if fd.fcomp.cstruct then (* C struct *)
-    let ctype = TComp(fd.fcomp,Cil.empty_size_cache(),[]) in
-    let offset = Field(fd,NoOffset) in
-    fst (Cil.bitsOffset ctype offset) / 8
-  else (* CIL invariant: all C union fields start at offset 0 *)
-    0
+  fst (Cil.fieldBitsOffset fd) / 8
 
 (* Conforms to C-ISO 6.3.1.8        *)
 (* If same sign => greater rank.    *)
diff --git a/tests/syntax/field-offsets.c b/tests/syntax/field-offsets.c
index dd972c8418ed4e042d4e2912312e7c538ea9599c..e29ff5e8e83a2e2cf667507ea5e185c214c54f8d 100644
--- a/tests/syntax/field-offsets.c
+++ b/tests/syntax/field-offsets.c
@@ -13,7 +13,7 @@ struct st {
 struct fam {
   int a;
   char b;
-  int fam[]; // check that a SizeOfError exception does not crash the printer
+  int fam[]; // check that the printer handles flexible arrays members
 };
 
 int main() {
diff --git a/tests/syntax/oracle/field-offsets.res.oracle b/tests/syntax/oracle/field-offsets.res.oracle
index 62a4b01b9fb855630e67033bd10a1a209ec595ba..f6ce77e05cea6fdf238ec7e97220c22ad40c6b87 100644
--- a/tests/syntax/oracle/field-offsets.res.oracle
+++ b/tests/syntax/oracle/field-offsets.res.oracle
@@ -9,7 +9,7 @@ struct st {
 struct fam {
    int a ; /* bits 0 .. 31 */
    char b ; /* bits 32 .. 39 */
-   int fam[] ;
+   int fam[] ; /* bits 64 ..  */
 };
 int main(void)
 {