diff options
author | Xavier Leroy <xavier.leroy@inria.fr> | 2018-04-21 18:16:38 +0300 |
---|---|---|
committer | Xavier Leroy <xavierleroy@users.noreply.github.com> | 2018-04-25 14:27:31 +0200 |
commit | f016c51503ceff5354e12b27f22ae33172b8fb0e (patch) | |
tree | f17716f0fc9910bb7c80bd1371a22e490e3e2566 | |
parent | 0a15edfb0c49242fcc8f772ed39f167a40e3b25e (diff) | |
download | compcert-f016c51503ceff5354e12b27f22ae33172b8fb0e.tar.gz compcert-f016c51503ceff5354e12b27f22ae33172b8fb0e.zip |
Initialization of union bit fields
Bit fields in unions were initialized like normal fields,
causing mismatch on the name of the field.
Also: added function Bitfields.carrier_field and refactored.
Patch by Bernhard Schommer.
Bug 23362
-rw-r--r-- | cparser/Bitfields.ml | 15 | ||||
-rw-r--r-- | test/regression/Results/bitfields9 | 8 | ||||
-rw-r--r-- | test/regression/bitfields9.c | 25 |
3 files changed, 45 insertions, 3 deletions
diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml index baf2b0ec..9ac9b61f 100644 --- a/cparser/Bitfields.ml +++ b/cparser/Bitfields.ml @@ -40,6 +40,10 @@ type bitfield_info = 0 < pos + sz <= bitsizeof(int) *) +let carrier_field bf = + { fld_name = bf.bf_carrier; fld_typ = bf.bf_carrier_typ; + fld_bitfield = None; fld_anonymous = false } + (* Mapping (struct identifier, bitfield name) -> bitfield info *) let bitfield_table = @@ -336,8 +340,7 @@ let rec transf_struct_init id fld_init_list = | Some bf -> let (el, rem') = pack_bitfield_init id bf.bf_carrier fld_init_list in - ({fld_name = bf.bf_carrier; fld_typ = bf.bf_carrier_typ; - fld_bitfield = None; fld_anonymous = false}, + (carrier_field bf, Init_single {edesc = ECast(bf.bf_carrier_typ, or_expr_list el); etyp = bf.bf_carrier_typ}) :: transf_struct_init id rem' @@ -504,7 +507,13 @@ and transf_init env i = let fld_init_list' = List.map (fun (f, i) -> (f, transf_init env i)) fld_init_list in Init_struct(id, transf_struct_init id fld_init_list') - | Init_union(id, fld, i) -> Init_union(id, fld, transf_init env i) + | Init_union(id, fld, i) -> + let i' = transf_init env i in + match is_bitfield id fld.fld_name with + | None -> + Init_union(id, fld, i') + | Some bf -> + Init_union(id, carrier_field bf, Init_single (bitfield_initializer bf i')) (* Declarations *) diff --git a/test/regression/Results/bitfields9 b/test/regression/Results/bitfields9 index a1d0e9fd..e35c2414 100644 --- a/test/regression/Results/bitfields9 +++ b/test/regression/Results/bitfields9 @@ -1,10 +1,18 @@ glob_s = { a = -12, b = 1 } glob_t = { c = 123, d = 1, e = -45 } +glob_u_u = { u = -3 } +glob_u_v = { v = 6 } loc_s = { a = 11, b = 2 } loc_t = { c = 11, d = 1, e = 2 } +loc_u_u = { u = -5 } +loc_u_v = { v = 3 } compound_s = { a = 2, b = 3 } compound_t = { c = 2, d = 1, e = -11 } +compound_u = { u = 2 } loc_s = { a = 7, b = 2 } loc_t = { c = 7, d = 1, e = 50 } +loc_u_u = { u = 7 } +loc_u_v = { v = 2 } compound_s = { a = -14, b = 3 } compound_t = { c = 50, d = 1, e = -7 } +compound_u = { u = 2 } diff --git a/test/regression/bitfields9.c b/test/regression/bitfields9.c index be87057b..54cc34ab 100644 --- a/test/regression/bitfields9.c +++ b/test/regression/bitfields9.c @@ -13,6 +13,11 @@ struct t { short e: 8; }; +union u { + int u: 4; + unsigned int v: 3; +}; + void print_s(char * msg, struct s p) { printf("%s = { a = %d, b = %d }\n", msg, p.a, p.b); @@ -23,25 +28,45 @@ void print_t(char * msg, struct t p) printf("%s = { c = %d, d = %d, e = %d }\n", msg, p.c, p.d, p.e); } +void print_u_u(char * msg, union u p) +{ + printf("%s = { u = %d }\n", msg, p.u); +} + +void print_u_v(char * msg, union u p) +{ + printf("%s = { v = %u }\n", msg, p.v); +} + + /* Global initialization */ struct s glob_s = { -12, 1 }; struct t glob_t = { 123, 2, -45 }; +union u glob_u_u = { -3 }; +union u glob_u_v = { .v = 6 }; /* Local initialization */ void f(int x, int y, int z) { struct s loc_s = { x, y }; struct t loc_t = { x, z, y }; + union u loc_u_u = { .u = x }; + union u loc_u_v = { .v = z }; print_s("loc_s", loc_s); print_t("loc_t", loc_t); + print_u_u("loc_u_u", loc_u_u); + print_u_v("loc_u_v", loc_u_v); print_s("compound_s", (struct s) { y, x }); print_t("compound_t", (struct t) { y, ~z, -x }); + print_u_u("compound_u", (union u) { y }); } int main() { print_s("glob_s", glob_s); print_t("glob_t", glob_t); + print_u_u("glob_u_u", glob_u_u); + print_u_v("glob_u_v", glob_u_v); f(11, 2, 3); f(7, 50, 2); return 0; |