2222open C
2323open Cutil
2424
25- (* Convert an initializer to a list of assignment expressions. *)
25+ (* Convert an initializer to a list of assignment expressions.
26+ Used for compound literals, where initialization is embedded in an
27+ expression at the appropriate sequence point. *)
2628
27- let rec local_initializer env path init k =
29+ let rec local_initializer_expr env path init k =
2830 match init with
2931 | Init_single e ->
3032 { edesc = EBinop (Oassign , path, e, path.etyp); etyp = path.etyp } :: k
@@ -42,7 +44,7 @@ let rec local_initializer env path init k =
4244 match il with
4345 | [] -> (default_init env ty_elt, [] )
4446 | i1 :: il' -> (i1, il') in
45- local_initializer env
47+ local_initializer_expr env
4648 { edesc = EBinop (Oindex , path, intconst pos IInt , TPtr (ty_elt, [] ));
4749 etyp = ty_elt }
4850 i1
@@ -51,27 +53,92 @@ let rec local_initializer env path init k =
5153 array_init 0L il
5254 | Init_struct (id , fil ) ->
5355 let field_init (fld , i ) k =
54- local_initializer env
56+ local_initializer_expr env
5557 { edesc = EUnop (Odot fld.fld_name, path); etyp = fld.fld_typ }
5658 i k in
5759 List. fold_right field_init fil k
5860 | Init_union (id , fld , i ) ->
59- local_initializer env
61+ local_initializer_expr env
6062 { edesc = EUnop (Odot fld.fld_name, path); etyp = fld.fld_typ }
6163 i k
6264
63- (* Prepend assignments to the given statement. *)
64-
65- let add_inits_stmt loc inits s =
66- List. fold_right
67- (fun e s -> sseq loc {sdesc = Sdo e; sloc = loc} s)
68- inits s
69-
7065(* Record new variables to be locally or globally defined *)
7166
7267let local_variables = ref ([] : decl list )
7368let global_variables = ref ([] : decl list )
7469
70+ let new_local name ty =
71+ let id = Env. fresh_ident name in
72+ local_variables :=
73+ (Storage_default , id, ty, None ) :: ! local_variables;
74+ { edesc = EVar id; etyp = ty }
75+
76+ (* Convert a declaration initializer to assignment statements. The explicitly
77+ supplied outer array prefix is traversed directly. A nonempty implicit
78+ array tail is initialized by a typed counted loop, so the generated AST
79+ does not grow with the number of omitted elements. *)
80+
81+ let rec local_initializer_stmt env loc path init k =
82+ match init with
83+ | Init_single e ->
84+ sseq loc (sassign loc path e) k
85+ | Init_array il ->
86+ let (ty_elt, sz) =
87+ match unroll env path.etyp with
88+ | TArray (ty_elt , Some sz , _ ) -> (ty_elt, sz)
89+ (* We accept empty array initializer for flexible array members, which
90+ has size zero *)
91+ | TArray (ty_elt , None, _ ) when il = [] -> (ty_elt, 0L )
92+ | _ ->
93+ Diagnostics. fatal_error Diagnostics. no_loc
94+ " wrong type for array initializer" in
95+ let array_elt index =
96+ { edesc = EBinop (Oindex , path, index, TPtr (ty_elt, [] ));
97+ etyp = ty_elt } in
98+ let array_default_init pos =
99+ let index_kind = size_t_ikind () in
100+ let index_type = TInt (index_kind, [] ) in
101+ let index = new_local " __init_index" index_type in
102+ let init_index = sassign loc index (intconst pos index_kind) in
103+ let test_index =
104+ { edesc = EBinop (Olt , index, intconst sz index_kind, index_type);
105+ etyp = TInt (IInt , [] ) } in
106+ let incr_index =
107+ { sdesc = Sdo { edesc = EUnop (Opreincr , index);
108+ etyp = index_type };
109+ sloc = loc } in
110+ let body =
111+ local_initializer_stmt env loc
112+ (array_elt index)
113+ (default_init env ty_elt)
114+ sskip in
115+ let loop =
116+ { sdesc = Sfor (init_index, test_index, incr_index, body);
117+ sloc = loc } in
118+ sseq loc loop k in
119+ let rec array_init pos il =
120+ if pos > = sz then k else begin
121+ match il with
122+ | i1 :: il' ->
123+ local_initializer_stmt env loc
124+ (array_elt (intconst pos IInt ))
125+ i1
126+ (array_init (Int64. succ pos) il')
127+ | [] ->
128+ array_default_init pos
129+ end in
130+ array_init 0L il
131+ | Init_struct (id , fil ) ->
132+ let field_init (fld , i ) k =
133+ local_initializer_stmt env loc
134+ { edesc = EUnop (Odot fld.fld_name, path); etyp = fld.fld_typ }
135+ i k in
136+ List. fold_right field_init fil k
137+ | Init_union (id , fld , i ) ->
138+ local_initializer_stmt env loc
139+ { edesc = EUnop (Odot fld.fld_name, path); etyp = fld.fld_typ }
140+ i k
141+
75142(* Note: "const int x = y - 1;" is legal, but we turn it into
76143 "const int x; x = y - 1;", which is not. Therefore, remove
77144 top-level 'const' attribute. Also remove it on element type of
@@ -94,7 +161,7 @@ let process_compound_literal islocal env ty init =
94161 let e = {edesc = EVar id; etyp = ty'} in
95162 local_variables :=
96163 (Storage_default , id, ty', None ) :: ! local_variables;
97- (local_initializer env e init [] , e)
164+ (local_initializer_expr env e init [] , e)
98165 end else begin
99166 global_variables :=
100167 (Storage_static , id, ty, Some init) :: ! global_variables;
@@ -253,8 +320,8 @@ let process_decl loc env ctx (sto, id, ty, optinit) k =
253320 k
254321 | Some init ->
255322 let init' = expand_init true env init in
256- let l = local_initializer env { edesc = EVar id; etyp = ty' } init' [] in
257- add_inits_stmt loc l k
323+ local_initializer_stmt env loc
324+ { edesc = EVar id; etyp = ty' } init' k
258325
259326(* Simplification of blocks within a statement *)
260327
0 commit comments