aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2018-04-21 18:57:51 +0300
committerXavier Leroy <xavierleroy@users.noreply.github.com>2018-04-25 14:27:31 +0200
commit92c8be3a36dff49f92e6cf94719a1750e4961538 (patch)
tree535a8dd1af2fad409abb00a6a356e3d5f0c02cef
parent7be3e73fa8a46b6b813c1be98da54a1a471378b9 (diff)
downloadcompcert-92c8be3a36dff49f92e6cf94719a1750e4961538.tar.gz
compcert-92c8be3a36dff49f92e6cf94719a1750e4961538.zip
Initialization of anonymous bit-fields in structs
For anonymous bit-fields in structs, carrier fields may be introduced which are not initialized since no default initializer are generated earlier. This cause the translation in C2C to throw an error since too few initializers are available. Example: struct s2 { int : 10; int a; int : 10; char b; int : 10; short c; int : 10; } s2 = { 42, 'a', 43 }; To work around this issue we need to generate a default inializer for every new member that does not have a translated member. Based on P#80, with more efficient algorithms. Bug 23362
-rw-r--r--cparser/Bitfields.ml21
-rw-r--r--test/regression/bitfields9.c1
2 files changed, 21 insertions, 1 deletions
diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml
index 71226ec6..696a9a8d 100644
--- a/cparser/Bitfields.ml
+++ b/cparser/Bitfields.ml
@@ -359,6 +359,20 @@ let rec transf_struct_init id fld_init_list =
etyp = bf.bf_carrier_typ})
:: transf_struct_init id rem'
+(* Add default initialization for carrier fields that are not listed in the output of
+ [transf_struct_init]. This happens with carrier fields that contain no named
+ bitfields, only anonymous bitfields. *)
+
+let rec completed_struct_init env actual expected =
+ match actual, expected with
+ | [], [] -> []
+ | (f_a, i) :: actual', f_e :: expected' when f_a.fld_name = f_e.fld_name ->
+ (f_a, i) :: completed_struct_init env actual' expected'
+ | _, f_e :: expected' ->
+ (f_e, default_init env f_e.fld_typ) :: completed_struct_init env actual expected'
+ | _, [] ->
+ assert false
+
(* Check whether a field access (e.f or e->f) is a bitfield access.
If so, return carrier expression (e and *e, respectively)
and bitfield_info *)
@@ -520,7 +534,12 @@ and transf_init env i =
| Init_struct(id, fld_init_list) ->
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')
+ begin match Hashtbl.find composite_transformed_members id with
+ | exception Not_found ->
+ Init_struct(id, fld_init_list')
+ | ml ->
+ Init_struct(id, completed_struct_init env (transf_struct_init id fld_init_list') ml)
+ end
| Init_union(id, fld, i) ->
let i' = transf_init env i in
match is_bitfield id fld.fld_name with
diff --git a/test/regression/bitfields9.c b/test/regression/bitfields9.c
index 54cc34ab..eef20168 100644
--- a/test/regression/bitfields9.c
+++ b/test/regression/bitfields9.c
@@ -11,6 +11,7 @@ struct t {
unsigned int c: 16;
_Bool d: 1;
short e: 8;
+ int : 10;
};
union u {