From 2b1c0aa69adafac185dd6c4e460d83517bcc8884 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Wed, 8 Jul 2015 10:16:53 +0200 Subject: Fix issue with bit fields of type _Bool cparser/Bitfields.ml: when assigning to a bit field of type _Bool, the right-hand side must be normalized to 0 or 1 via a cast to _Bool. test/regression/bitfields{1,9}.c: add corresponding test cases. --- cparser/Bitfields.ml | 28 ++++++++++++++++++++++------ test/regression/Results/bitfields9 | 6 +++--- test/regression/bitfields1.c | 4 ++-- test/regression/bitfields9.c | 14 +++++++------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml index 570572fa..6569bb4c 100644 --- a/cparser/Bitfields.ml +++ b/cparser/Bitfields.ml @@ -31,7 +31,8 @@ type bitfield_info = bf_pos: int; (* start bit *) bf_size: int; (* size in bit *) bf_signed: bool; (* is field signed or unsigned? *) - bf_signed_res: bool (* is result of extracting field signed or unsigned? *) + bf_signed_res: bool; (* is result of extracting field signed or unsigned? *) + bf_bool: bool (* does field have type _Bool? *) } (* invariants: @@ -100,7 +101,13 @@ let pack_bitfields env sid ml = match unroll env (type_of_member env m) with | TInt(ik, _) -> is_signed_ikind ik | _ -> assert false (* should never happen, checked in Elab *) in - pack ((m.fld_name, pos, n, signed, signed2) :: accu) (pos + n) ms + let is_bool = + match unroll env m.fld_typ with + | TInt(IBool, _) -> true + | _ -> false in + + pack ((m.fld_name, pos, n, signed, signed2, is_bool) :: accu) + (pos + n) ms end in pack [] 0 ml @@ -121,7 +128,7 @@ let rec transf_members env id count = function let carrier_typ = TInt(carrier_ikind, []) in (* Enter each field with its bit position, size, signedness *) List.iter - (fun (name, pos, sz, signed, signed2) -> + (fun (name, pos, sz, signed, signed2, is_bool) -> if name <> "" then begin let pos' = if !config.bitfields_msb_first @@ -131,7 +138,8 @@ let rec transf_members env id count = function (id, name) {bf_carrier = carrier; bf_carrier_typ = carrier_typ; bf_pos = pos'; bf_size = sz; - bf_signed = signed; bf_signed_res = signed2} + bf_signed = signed; bf_signed_res = signed2; + bf_bool = is_bool} end) bitfields; { fld_name = carrier; fld_typ = carrier_typ; fld_bitfield = None} @@ -208,13 +216,16 @@ unsigned int bitfield_insert(unsigned int x, int ofs, int sz, unsigned int y) return (x & ~mask) | ((y << ofs) & mask); } +If the bitfield is of type _Bool, the new value (y above) must be converted +to _Bool to normalize it to 0 or 1. *) let bitfield_assign env bf carrier newval = let msk = insertion_mask bf in let notmsk = {edesc = EUnop(Onot, msk); etyp = msk.etyp} in let newval_casted = - ecast (TInt(IUInt,[])) newval in + ecast (TInt(IUInt,[])) + (if bf.bf_bool then ecast (TInt(IBool,[])) newval else newval) in let newval_shifted = eshift env Oshl newval_casted (intconst (Int64.of_int bf.bf_pos) IUInt) in let newval_masked = ebinint env Oand newval_shifted msk @@ -230,17 +241,22 @@ unsigned int bitfield_init(int ofs, int sz, unsigned int y) unsigned int mask = (1U << sz) - 1; return (y & mask) << ofs; } + +If the bitfield is of type _Bool, the new value (y above) must be converted +to _Bool to normalize it to 0 or 1. *) let bitfield_initializer bf i = match i with | Init_single e -> let m = Int64.pred (Int64.shift_left 1L bf.bf_size) in + let e_cast = + if bf.bf_bool then ecast (TInt(IBool,[])) e else e in let e_mask = {edesc = EConst(CInt(m, IUInt, sprintf "0x%LXU" m)); etyp = TInt(IUInt, [])} in let e_and = - {edesc = EBinop(Oand, e, e_mask, TInt(IUInt,[])); + {edesc = EBinop(Oand, e_cast, e_mask, TInt(IUInt,[])); etyp = TInt(IUInt,[])} in {edesc = EBinop(Oshl, e_and, intconst (Int64.of_int bf.bf_pos) IInt, TInt(IUInt, [])); diff --git a/test/regression/Results/bitfields9 b/test/regression/Results/bitfields9 index ca74f1f4..a1d0e9fd 100644 --- a/test/regression/Results/bitfields9 +++ b/test/regression/Results/bitfields9 @@ -1,10 +1,10 @@ glob_s = { a = -12, b = 1 } -glob_t = { c = 123, d = 0, e = -45 } +glob_t = { c = 123, d = 1, e = -45 } loc_s = { a = 11, b = 2 } loc_t = { c = 11, d = 1, e = 2 } compound_s = { a = 2, b = 3 } -compound_t = { c = 2, d = 0, e = -11 } +compound_t = { c = 2, d = 1, e = -11 } loc_s = { a = 7, b = 2 } loc_t = { c = 7, d = 1, e = 50 } compound_s = { a = -14, b = 3 } -compound_t = { c = 50, d = 0, e = -7 } +compound_t = { c = 50, d = 1, e = -7 } diff --git a/test/regression/bitfields1.c b/test/regression/bitfields1.c index c6022dd1..5f6dfdd1 100644 --- a/test/regression/bitfields1.c +++ b/test/regression/bitfields1.c @@ -7,7 +7,7 @@ struct s { struct t { unsigned int c: 16; - unsigned int d: 1; + _Bool d: 1; short e: 8; }; @@ -29,7 +29,7 @@ int main() y.c = 12345; y.d = 0; y.e = 89; - res = f(&x, &y, 1); + res = f(&x, &y, 2); printf("x = {a = %d, b = %d }\n", x.a, x.b); printf("y = {c = %d, d = %d, e = %d }\n", y.c, y.d, y.e); diff --git a/test/regression/bitfields9.c b/test/regression/bitfields9.c index b33c4064..be87057b 100644 --- a/test/regression/bitfields9.c +++ b/test/regression/bitfields9.c @@ -9,7 +9,7 @@ struct s { struct t { unsigned int c: 16; - unsigned int d: 1; + _Bool d: 1; short e: 8; }; @@ -25,25 +25,25 @@ void print_t(char * msg, struct t p) /* Global initialization */ struct s glob_s = { -12, 1 }; -struct t glob_t = { 123, 0, -45 }; +struct t glob_t = { 123, 2, -45 }; /* Local initialization */ -void f(int x, int y) +void f(int x, int y, int z) { struct s loc_s = { x, y }; - struct t loc_t = { x, 1, y }; + struct t loc_t = { x, z, y }; print_s("loc_s", loc_s); print_t("loc_t", loc_t); print_s("compound_s", (struct s) { y, x }); - print_t("compound_t", (struct t) { y, 0, -x }); + print_t("compound_t", (struct t) { y, ~z, -x }); } int main() { print_s("glob_s", glob_s); print_t("glob_t", glob_t); - f(11, 2); - f(7, 50); + f(11, 2, 3); + f(7, 50, 2); return 0; } -- cgit