aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cparser/Bitfields.ml32
-rw-r--r--cparser/Cutil.ml22
-rw-r--r--test/regression/Makefile2
-rw-r--r--test/regression/Results/bitfields71
-rw-r--r--test/regression/bitfields7.c20
5 files changed, 53 insertions, 24 deletions
diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml
index a345d975..9452a4f6 100644
--- a/cparser/Bitfields.ml
+++ b/cparser/Bitfields.ml
@@ -88,19 +88,25 @@ let rec transf_members env id count = function
m :: transf_members env id count ms
else begin
let (nbits, bitfields, ml') = pack_bitfields env id ml in
- let carrier = sprintf "__bf%d" count in
- let carrier_typ = TInt(unsigned_ikind_for_carrier nbits, []) in
- List.iter
- (fun (name, pos, sz, signed, signed2) ->
- if name <> "" then
- Hashtbl.add bitfield_table
- (id, name)
- {bf_carrier = carrier; bf_carrier_typ = carrier_typ;
- bf_pos = pos; bf_size = sz;
- bf_signed = signed; bf_signed_res = signed2})
- bitfields;
- { fld_name = carrier; fld_typ = carrier_typ; fld_bitfield = None}
- :: transf_members env id (count + 1) ml'
+ if nbits = 0 then
+ (* Lone zero-size bitfield: just ignore *)
+ transf_members env id count ml'
+ else begin
+ (* Create integer field of sufficient size for this bitfield group *)
+ let carrier = sprintf "__bf%d" count in
+ let carrier_typ = TInt(unsigned_ikind_for_carrier nbits, []) in
+ List.iter
+ (fun (name, pos, sz, signed, signed2) ->
+ if name <> "" then
+ Hashtbl.add bitfield_table
+ (id, name)
+ {bf_carrier = carrier; bf_carrier_typ = carrier_typ;
+ bf_pos = pos; bf_size = sz;
+ bf_signed = signed; bf_signed_res = signed2})
+ bitfields;
+ { fld_name = carrier; fld_typ = carrier_typ; fld_bitfield = None}
+ :: transf_members env id (count + 1) ml'
+ end
end
let transf_composite env su id ml =
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index cb241e5c..bb540c70 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -216,12 +216,14 @@ let pack_bitfields ml =
pack (nbits + n) ms (* add to current word *)
in
let (nbits, ml') = pack 0 ml in
- let sz =
- if nbits <= 8 then 1 else
- if nbits <= 16 then 2 else
- if nbits <= 32 then 4 else
- if nbits <= 64 then 8 else assert false in
- (sz, ml')
+ let (sz, al) =
+ (* A lone bitfield of width 0 consumes no space and aligns to 1 *)
+ if nbits = 0 then (0, 1) else
+ if nbits <= 8 then (1, 1) else
+ if nbits <= 16 then (2, 2) else
+ if nbits <= 32 then (4, 4) else
+ if nbits <= 64 then (8, 8) else assert false in
+ (sz, al, ml')
(* Natural alignment, in bytes *)
@@ -264,8 +266,8 @@ let alignof_struct_union env members =
| None -> None
| Some a -> align_rec (max a al) rem
end else begin
- let (sz, ml') = pack_bitfields ml in
- align_rec (max sz al) ml'
+ let (s, a, ml') = pack_bitfields ml in
+ align_rec (max a al) ml'
end
in align_rec 1 members
@@ -355,8 +357,8 @@ let sizeof_struct env members =
| Some a, Some s -> sizeof_rec (align ofs a + s) rem
| _, _ -> None
end else begin
- let (sz, ml') = pack_bitfields ml in
- sizeof_rec (align ofs sz + sz) ml'
+ let (s, a, ml') = pack_bitfields ml in
+ sizeof_rec (align ofs a + s) ml'
end
in sizeof_rec 0 members
diff --git a/test/regression/Makefile b/test/regression/Makefile
index 7d456df5..c1925c79 100644
--- a/test/regression/Makefile
+++ b/test/regression/Makefile
@@ -9,7 +9,7 @@ LIBS=$(LIBMATH)
# Can run and have reference output in Results
TESTS=bitfields1 bitfields2 bitfields3 bitfields4 \
- bitfields5 bitfields6 \
+ bitfields5 bitfields6 bitfields7 \
expr1 initializers volatile2 \
funct3 expr5 struct7 struct8 casts1 casts2
diff --git a/test/regression/Results/bitfields7 b/test/regression/Results/bitfields7
new file mode 100644
index 00000000..cf2b3f34
--- /dev/null
+++ b/test/regression/Results/bitfields7
@@ -0,0 +1 @@
+g_22.f2 = 1
diff --git a/test/regression/bitfields7.c b/test/regression/bitfields7.c
new file mode 100644
index 00000000..33e20a12
--- /dev/null
+++ b/test/regression/bitfields7.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+struct S0 {
+ signed f0 : 12;
+ unsigned f1 : 28;
+};
+
+struct S5 {
+ struct S0 f1;
+ unsigned : 0;
+ signed f2 : 26;
+};
+
+struct S5 g_22 = {{0,0},1};
+
+int main(int argc, char* argv[])
+{
+ printf("g_22.f2 = %d\n", g_22.f2);
+ return 0;
+}