1 (* *********************************************************************)
3 (* The Compcert verified compiler *)
5 (* Xavier Leroy, INRIA Paris-Rocquencourt *)
7 (* Copyright Institut National de Recherche en Informatique et en *)
8 (* Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the GNU General Public License as published by *)
10 (* the Free Software Foundation, either version 2 of the License, or *)
11 (* (at your option) any later version. This file is also distributed *)
12 (* under the terms of the INRIA Non-Commercial License Agreement. *)
14 (* *********************************************************************)
16 (* Elaboration from Cabs parse tree to C simplified, typed syntax tree *)
27 (** * Utility functions *)
31 let fatal_error loc fmt =
32 Errors.fatal_error ("%a: Error:@ " ^^ fmt) format_cabsloc loc
35 Errors.error ("%a: Error:@ " ^^ fmt) format_cabsloc loc
38 Errors.warning ("%a: Warning:@ " ^^ fmt) format_cabsloc loc
40 (* Error reporting for Env functions *)
42 let wrap fn loc env arg =
44 with Env.Error msg -> fatal_error loc "%s" (Env.error_message msg)
46 (* Translation of locations *)
48 let elab_loc l = (l.filename, l.lineno)
50 (* Buffering of the result (a list of topdecl *)
52 let top_declarations = ref ([] : globdecl list)
54 let emit_elab loc td =
55 top_declarations := { gdesc = td; gloc = loc } :: !top_declarations
57 let reset() = top_declarations := []
59 let elaborated_program () =
60 let p = !top_declarations in
61 top_declarations := [];
62 (* Reverse it and eliminate unreferenced declarations *)
67 let loc_of_name (_, _, _, loc) = loc
69 let loc_of_namelist = function [] -> cabslu | name :: _ -> loc_of_name name
71 let loc_of_init_name_list =
72 function [] -> cabslu | (name, init) :: _ -> loc_of_name name
74 (* Monadic map for functions env -> 'a -> 'b * env *)
76 let rec mmap f env = function
79 let (hd', env1) = f env hd in
80 let (tl', env2) = mmap f env1 tl in
83 (* To detect redefinitions within the same scope *)
85 let redef fn env arg =
87 let (id, info) = fn env arg in
88 if Env.in_current_scope env id then Some(id, info) else None
92 (* Forward declarations *)
94 let elab_expr_f : (cabsloc -> Env.t -> Cabs.expression -> C.exp) ref
95 = ref (fun _ _ _ -> assert false)
97 let elab_block_f : (cabsloc -> C.typ -> Env.t -> Cabs.block -> C.stmt) ref
98 = ref (fun _ _ _ _ -> assert false)
101 (** * Elaboration of constants *)
103 let has_suffix s suff =
104 let ls = String.length s and lsuff = String.length suff in
105 ls >= lsuff && String.sub s (ls - lsuff) lsuff = suff
108 assert (String.length s >= n);
109 String.sub s 0 (String.length s - n)
111 let has_prefix s pref =
112 let ls = String.length s and lpref = String.length pref in
113 ls >= lpref && String.sub s 0 lpref = pref
116 assert (String.length s >= n);
117 String.sub s n (String.length s - n)
122 let parse_int base s =
123 let max_val = (* (2^64-1) / base, unsigned *)
125 | 8 -> 2305843009213693951L
126 | 10 -> 1844674407370955161L
127 | 16 -> 1152921504606846975L
128 | _ -> assert false in
130 for i = 0 to String.length s - 1 do
131 if !v > max_val then raise Overflow;
132 v := Int64.mul !v (Int64.of_int base);
135 if c >= '0' && c <= '9' then Char.code c - 48
136 else if c >= 'A' && c <= 'F' then Char.code c - 55
137 else raise Bad_digit in
138 if digit >= base then raise Bad_digit;
139 v := Int64.add !v (Int64.of_int digit)
143 let integer_representable v ik =
144 let bitsize = sizeof_ikind ik * 8
145 and signed = is_signed_ikind ik in
146 if bitsize >= 64 then
147 (not signed) || (v >= 0L && v <= 0x7FFF_FFFF_FFFF_FFFFL)
148 else if not signed then
149 v >= 0L && v < Int64.shift_left 1L bitsize
151 v >= 0L && v < Int64.shift_left 1L (bitsize - 1)
153 let elab_int_constant loc s0 =
154 let s = String.uppercase s0 in
155 (* Determine possible types and chop type suffix *)
156 let (s, dec_kinds, hex_kinds) =
157 if has_suffix s "ULL" || has_suffix s "LLU" then
158 (chop_last s 3, [IULongLong], [IULongLong])
159 else if has_suffix s "LL" then
160 (chop_last s 2, [ILongLong], [ILongLong; IULongLong])
161 else if has_suffix s "UL" || has_suffix s "LU" then
162 (chop_last s 2, [IULong; IULongLong], [IULong; IULongLong])
163 else if has_suffix s "L" then
164 (chop_last s 1, [ILong; ILongLong],
165 [ILong; IULong; ILongLong; IULongLong])
166 else if has_suffix s "U" then
167 (chop_last s 1, [IUInt; IULong; IULongLong],
168 [IUInt; IULong; IULongLong])
170 (s, [IInt; ILong; IULong; ILongLong],
171 [IInt; IUInt; ILong; IULong; ILongLong; IULongLong])
175 if has_prefix s "0X" then
177 else if has_prefix s "0" then
187 error loc "integer literal '%s' is too large" s0;
190 error loc "bad digit in integer literal '%s'" s0;
193 (* Find smallest allowable type that fits *)
195 try List.find (fun ty -> integer_representable v ty)
196 (if base = 10 then dec_kinds else hex_kinds)
198 error loc "integer literal '%s' cannot be represented" s0;
203 let elab_float_constant loc s0 =
204 let s = String.uppercase s0 in
205 (* Determine type and chop suffix *)
207 if has_suffix s "L" then
208 (chop_last s 1, FLongDouble)
209 else if has_suffix s "F" then
210 (chop_last s 1, FFloat)
213 (* Convert to Caml float - XXX loss of precision for long double *)
215 try float_of_string s
216 with Failure _ -> error loc "bad float literal '%s'" s0; 0.0 in
219 let elab_char_constant loc sz cl =
220 let nbits = 8 * sz in
221 (* Treat multi-char constants as a number in base 2^nbits *)
222 let max_val = Int64.shift_left 1L (64 - nbits) in
226 if acc >= max_val then begin
227 error loc "character literal overflows";
229 Int64.add (Int64.shift_left acc nbits) d)
232 if v < 256L then IInt
233 else if v < Int64.shift_left 1L (8 * sizeof_ikind IULong) then IULong
237 let elab_constant loc = function
239 let (v, ik) = elab_int_constant loc s in
242 let (v, fk) = elab_float_constant loc s in
245 let (v, ik) = elab_char_constant loc 1 cl in
248 let (v, ik) = elab_char_constant loc !config.sizeof_wchar cl in
250 | CONST_STRING s -> CStr s
251 | CONST_WSTRING s -> CWStr s
254 (** * Elaboration of type expressions, type specifiers, name declarations *)
256 (* Elaboration of attributes *)
258 let elab_attribute loc = function
259 | ("const", []) -> Some AConst
260 | ("restrict", []) -> Some ARestrict
261 | ("volatile", []) -> Some AVolatile
263 (* warning loc "ignoring '%s' attribute" name; *)
266 let rec elab_attributes loc = function
269 match elab_attribute loc a1 with
270 | None -> elab_attributes loc al
271 | Some a -> add_attributes [a] (elab_attributes loc al)
273 (* Auxiliary for typespec elaboration *)
275 let typespec_rank = function (* Don't change this *)
278 | Cabs.Tunsigned -> 2
287 | _ -> 11 (* There should be at most one of the others *)
289 let typespec_order t1 t2 = compare (typespec_rank t1) (typespec_rank t2)
291 (* Elaboration of a type specifier. Returns 4-tuple:
292 (storage class, "inline" flag, elaborated type, new env)
293 Optional argument "only" is true if this is a standalone
294 struct or union declaration, without variable names.
297 let rec elab_specifier ?(only = false) loc env specifier =
298 (* We first divide the parts of the specifier as follows:
300 - a set of attributes (const, volatile, restrict)
301 - a list of type specifiers *)
302 let sto = ref Storage_default
303 and inline = ref false
305 and tyspecs = ref [] in
307 let do_specifier = function
313 | CV_VOLATILE -> AVolatile
314 | CV_RESTRICT -> ARestrict in
315 attr := add_attributes [a] !attr
317 attr := add_attributes (elab_attributes loc [a]) !attr
319 if !sto <> Storage_default then
320 error loc "multiple storage specifiers";
324 | STATIC -> sto := Storage_static
325 | EXTERN -> sto := Storage_extern
326 | REGISTER -> sto := Storage_register
328 | SpecInline -> inline := true
329 | SpecType tys -> tyspecs := tys :: !tyspecs in
331 List.iter do_specifier specifier;
333 let simple ty = (!sto, !inline, add_attributes_type !attr ty, env) in
335 (* Now interpret the list of type specifiers. Much of this code
336 is stolen from CIL. *)
337 match List.stable_sort typespec_order (List.rev !tyspecs) with
338 | [Cabs.Tvoid] -> simple (TVoid [])
340 | [Cabs.T_Bool] -> simple (TInt(IBool, []))
341 | [Cabs.Tchar] -> simple (TInt(IChar, []))
342 | [Cabs.Tsigned; Cabs.Tchar] -> simple (TInt(ISChar, []))
343 | [Cabs.Tunsigned; Cabs.Tchar] -> simple (TInt(IUChar, []))
345 | [Cabs.Tshort] -> simple (TInt(IShort, []))
346 | [Cabs.Tsigned; Cabs.Tshort] -> simple (TInt(IShort, []))
347 | [Cabs.Tshort; Cabs.Tint] -> simple (TInt(IShort, []))
348 | [Cabs.Tsigned; Cabs.Tshort; Cabs.Tint] -> simple (TInt(IShort, []))
350 | [Cabs.Tunsigned; Cabs.Tshort] -> simple (TInt(IUShort, []))
351 | [Cabs.Tunsigned; Cabs.Tshort; Cabs.Tint] -> simple (TInt(IUShort, []))
353 | [] -> simple (TInt(IInt, []))
354 | [Cabs.Tint] -> simple (TInt(IInt, []))
355 | [Cabs.Tsigned] -> simple (TInt(IInt, []))
356 | [Cabs.Tsigned; Cabs.Tint] -> simple (TInt(IInt, []))
358 | [Cabs.Tunsigned] -> simple (TInt(IUInt, []))
359 | [Cabs.Tunsigned; Cabs.Tint] -> simple (TInt(IUInt, []))
361 | [Cabs.Tlong] -> simple (TInt(ILong, []))
362 | [Cabs.Tsigned; Cabs.Tlong] -> simple (TInt(ILong, []))
363 | [Cabs.Tlong; Cabs.Tint] -> simple (TInt(ILong, []))
364 | [Cabs.Tsigned; Cabs.Tlong; Cabs.Tint] -> simple (TInt(ILong, []))
366 | [Cabs.Tunsigned; Cabs.Tlong] -> simple (TInt(IULong, []))
367 | [Cabs.Tunsigned; Cabs.Tlong; Cabs.Tint] -> simple (TInt(IULong, []))
369 | [Cabs.Tlong; Cabs.Tlong] -> simple (TInt(ILongLong, []))
370 | [Cabs.Tsigned; Cabs.Tlong; Cabs.Tlong] -> simple (TInt(ILongLong, []))
371 | [Cabs.Tlong; Cabs.Tlong; Cabs.Tint] -> simple (TInt(ILongLong, []))
372 | [Cabs.Tsigned; Cabs.Tlong; Cabs.Tlong; Cabs.Tint] -> simple (TInt(ILongLong, []))
374 | [Cabs.Tunsigned; Cabs.Tlong; Cabs.Tlong] -> simple (TInt(IULongLong, []))
375 | [Cabs.Tunsigned; Cabs.Tlong; Cabs.Tlong; Cabs.Tint] -> simple (TInt(IULongLong, []))
377 (* int64 is a MSVC extension *)
378 | [Cabs.Tint64] -> simple (TInt(ILongLong, []))
379 | [Cabs.Tsigned; Cabs.Tint64] -> simple (TInt(ILongLong, []))
380 | [Cabs.Tunsigned; Cabs.Tint64] -> simple (TInt(IULongLong, []))
382 | [Cabs.Tfloat] -> simple (TFloat(FFloat, []))
383 | [Cabs.Tdouble] -> simple (TFloat(FDouble, []))
385 | [Cabs.Tlong; Cabs.Tdouble] -> simple (TFloat(FLongDouble, []))
387 (* Now the other type specifiers *)
389 | [Cabs.Tnamed id] ->
390 let (id', info) = wrap Env.lookup_typedef loc env id in
391 simple (TNamed(id', []))
393 | [Cabs.Tstruct(id, optmembers, a)] ->
395 elab_struct_or_union only Struct loc id optmembers env in
396 let attr' = add_attributes !attr (elab_attributes loc a) in
397 (!sto, !inline, TStruct(id', attr'), env')
399 | [Cabs.Tunion(id, optmembers, a)] ->
401 elab_struct_or_union only Union loc id optmembers env in
402 let attr' = add_attributes !attr (elab_attributes loc a) in
403 (!sto, !inline, TUnion(id', attr'), env')
405 | [Cabs.Tenum(id, optmembers, a)] ->
407 elab_enum loc id optmembers env in
408 let attr' = add_attributes !attr (elab_attributes loc a) in
409 (!sto, !inline, TInt(enum_ikind, attr'), env')
411 | [Cabs.TtypeofE _] ->
412 fatal_error loc "GCC __typeof__ not supported"
413 | [Cabs.TtypeofT _] ->
414 fatal_error loc "GCC __typeof__ not supported"
416 (* Specifier doesn't make sense *)
418 fatal_error loc "illegal combination of type specifiers"
420 (* Elaboration of a type declarator. *)
422 and elab_type_declarator loc env ty = function
425 | Cabs.PARENTYPE(attr1, d, attr2) ->
426 (* XXX ignoring the distinction between attrs after and before *)
427 let a = elab_attributes loc (attr1 @ attr2) in
428 elab_type_declarator loc env (add_attributes_type a ty) d
429 | Cabs.ARRAY(d, attr, sz) ->
430 let a = elab_attributes loc attr in
436 match Ceval.integer_expr env (!elab_expr_f loc env sz) with
438 if n < 0L then error loc "array size is negative";
441 error loc "array size is not a compile-time constant";
442 Some 1L in (* produces better error messages later *)
443 elab_type_declarator loc env (TArray(ty, sz', a)) d
444 | Cabs.PTR(attr, d) ->
445 let a = elab_attributes loc attr in
446 elab_type_declarator loc env (TPtr(ty, a)) d
447 | Cabs.PROTO(d, params, vararg) ->
448 begin match unroll env ty with
449 | TArray _ | TFun _ ->
450 error loc "illegal function return type@ %a" Cprint.typ ty
453 let params' = elab_parameters env params in
454 elab_type_declarator loc env (TFun(ty, params', vararg, [])) d
456 (* Elaboration of parameters in a prototype *)
458 and elab_parameters env params =
460 | [] -> (* old-style K&R prototype *)
463 (* Prototype introduces a new scope *)
464 let (vars, _) = mmap elab_parameter (Env.new_scope env) params in
465 (* Catch special case f(void) *)
467 | [ ( {name=""}, TVoid _) ] -> Some []
470 (* Elaboration of a function parameter *)
472 and elab_parameter env (spec, name) =
473 let (id, sto, inl, ty, env1) = elab_name env spec name in
474 if sto <> Storage_default && sto <> Storage_register then
475 error (loc_of_name name)
476 "'extern' or 'static' storage not supported for function parameter";
477 (* replace array and function types by pointer types *)
478 let ty1 = argument_conversion env1 ty in
479 let (id', env2) = Env.enter_ident env1 id sto ty1 in
480 ( (id', ty1) , env2 )
482 (* Elaboration of a (specifier, Cabs "name") pair *)
484 and elab_name env spec (id, decl, attr, loc) =
485 let (sto, inl, bty, env') = elab_specifier loc env spec in
486 let (ty, env'') = elab_type_declarator loc env' bty decl in
487 let a = elab_attributes loc attr in
488 (id, sto, inl, add_attributes_type a ty, env'')
490 (* Elaboration of a name group *)
492 and elab_name_group env (spec, namelist) =
493 let (sto, inl, bty, env') =
494 elab_specifier (loc_of_namelist namelist) env spec in
495 let elab_one_name env (id, decl, attr, loc) =
497 elab_type_declarator loc env bty decl in
498 let a = elab_attributes loc attr in
499 ((id, sto, add_attributes_type a ty), env1) in
500 mmap elab_one_name env' namelist
502 (* Elaboration of an init-name group *)
504 and elab_init_name_group env (spec, namelist) =
505 let (sto, inl, bty, env') =
506 elab_specifier (loc_of_init_name_list namelist) env spec in
507 let elab_one_name env ((id, decl, attr, loc), init) =
509 elab_type_declarator loc env bty decl in
510 let a = elab_attributes loc attr in
511 ((id, sto, add_attributes_type a ty, init), env1) in
512 mmap elab_one_name env' namelist
514 (* Elaboration of a field group *)
516 and elab_field_group env (spec, fieldlist) =
518 elab_name_group env (spec, List.map fst fieldlist) in
520 let elab_bitfield ((_, _, _, loc), optbitsize) (id, sto, ty) =
521 if sto <> Storage_default then
522 error loc "member '%s' has non-default storage" id;
524 match optbitsize with
528 match unroll env' ty with
530 | _ -> ILongLong (* trigger next error message *) in
531 if integer_rank ik > integer_rank IInt then
533 "the type of a bit field must be an integer type \
534 no bigger than 'int'";
535 match Ceval.integer_expr env' (!elab_expr_f loc env sz) with
538 error loc "bit size of member (%Ld) is negative" n;
541 if n > Int64.of_int(sizeof_ikind ik * 8) then begin
542 error loc "bit size of member (%Ld) is too large" n;
547 error loc "bit size of member is not a compile-time constant";
549 { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize' }
551 (List.map2 elab_bitfield fieldlist names, env')
553 (* Elaboration of a struct or union *)
555 and elab_struct_or_union_info kind loc env members =
556 let (m, env') = mmap elab_field_group env members in
557 let m = List.flatten m in
558 (* Check for incomplete types *)
559 let rec check_incomplete = function
561 | [ { fld_typ = TArray(ty_elt, None, _) } ] when kind = Struct -> ()
562 (* C99: ty[] allowed as last field of a struct *)
564 if incomplete_type env' fld.fld_typ then
565 error loc "member '%s' has incomplete type" fld.fld_name;
566 check_incomplete rem in
568 (composite_info_def env' kind m, env')
570 (* Elaboration of a struct or union *)
572 and elab_struct_or_union only kind loc tag optmembers env =
574 if tag = "" then None else Env.lookup_composite env tag in
575 match optbinding, optmembers with
576 | Some(tag', ci), None
577 when (not only) || Env.in_current_scope env tag' ->
578 (* Reference to an already declared struct or union.
579 Special case: if this is an "only" declaration (without variable names)
580 and the composite was bound in another scope,
581 create a new incomplete composite instead via the case
584 | Some(tag', ({ci_sizeof = None} as ci)), Some members
585 when Env.in_current_scope env tag' ->
586 if ci.ci_kind <> kind then
587 error loc "struct/union mismatch on tag '%s'" tag;
588 (* finishing the definition of an incomplete struct or union *)
589 let (ci', env') = elab_struct_or_union_info kind loc env members in
590 (* Emit a global definition for it *)
591 emit_elab (elab_loc loc)
592 (Gcompositedef(kind, tag', ci'.ci_members));
593 (* Replace infos but keep same ident *)
594 (tag', Env.add_composite env' tag' ci')
595 | Some(tag', {ci_sizeof = Some _}), Some _
596 when Env.in_current_scope env tag' ->
597 error loc "redefinition of struct or union '%s'" tag;
600 (* declaration of an incomplete struct or union *)
602 error loc "anonymous, incomplete struct or union";
603 let ci = composite_info_decl env kind in
604 (* enter it with a new name *)
605 let (tag', env') = Env.enter_composite env tag ci in
607 emit_elab (elab_loc loc)
608 (Gcompositedecl(kind, tag'));
611 (* definition of a complete struct or union *)
612 let ci1 = composite_info_decl env kind in
613 (* enter it, incomplete, with a new name *)
614 let (tag', env') = Env.enter_composite env tag ci1 in
615 (* emit a declaration so that inner structs and unions can refer to it *)
616 emit_elab (elab_loc loc)
617 (Gcompositedecl(kind, tag'));
618 (* elaborate the members *)
619 let (ci2, env'') = elab_struct_or_union_info kind loc env' members in
620 (* emit a definition *)
621 emit_elab (elab_loc loc)
622 (Gcompositedef(kind, tag', ci2.ci_members));
623 (* Replace infos but keep same ident *)
624 (tag', Env.add_composite env'' tag' ci2)
626 (* Elaboration of an enum item *)
628 and elab_enum_item env (s, exp, loc) nextval =
634 let exp' = !elab_expr_f loc env exp in
635 match Ceval.integer_expr env exp' with
636 | Some n -> (n, Some exp')
639 "value of enumerator '%s' is not a compile-time constant" s;
640 (nextval, Some exp') in
641 if redef Env.lookup_ident env s <> None then
642 error loc "redefinition of enumerator '%s'" s;
643 let (id, env') = Env.enter_enum_item env s v in
644 ((id, exp'), Int64.succ v, env')
646 (* Elaboration of an enumeration declaration *)
648 and elab_enum loc tag optmembers env =
649 match optmembers with
652 let rec elab_members env nextval = function
655 let (dcl1, nextval1, env1) = elab_enum_item env hd nextval in
656 let (dcl2, env2) = elab_members env1 nextval1 tl in
657 (dcl1 :: dcl2, env2) in
658 let (dcls, env') = elab_members env 0L members in
659 let tag' = Env.fresh_ident tag in
660 emit_elab (elab_loc loc) (Genumdef(tag', dcls));
663 (* Elaboration of a naked type, e.g. in a cast *)
665 let elab_type loc env spec decl =
666 let (sto, inl, bty, env') = elab_specifier loc env spec in
667 let (ty, env'') = elab_type_declarator loc env' bty decl in
668 if sto <> Storage_default || inl then
669 error loc "'extern', 'static', 'register' and 'inline' are meaningless in cast";
673 (* Elaboration of expressions *)
675 let elab_expr loc env a =
677 let err fmt = error loc fmt in (* non-fatal error *)
678 let error fmt = fatal_error loc fmt in
679 let warning fmt = warning loc fmt in
681 let rec elab = function
684 error "empty expression"
686 (* 7.3 Primary expressions *)
689 begin match wrap Env.lookup_ident loc env s with
690 | (id, II_ident(sto, ty)) ->
691 { edesc = EVar id; etyp = ty }
693 { edesc = EConst(CEnum(id, v)); etyp = TInt(enum_ikind, []) }
697 let cst' = elab_constant loc cst in
698 { edesc = EConst cst'; etyp = type_of_constant cst' }
703 (* 7.4 Postfix expressions *)
705 | INDEX(a1, a2) -> (* e1[e2] *)
706 let b1 = elab a1 in let b2 = elab a2 in
708 match (unroll env b1.etyp, unroll env b2.etyp) with
709 | (TPtr(t, _) | TArray(t, _, _)), TInt _ -> t
710 | TInt _, (TPtr(t, _) | TArray(t, _, _)) -> t
711 | t1, t2 -> error "incorrect types for array subscripting" in
712 { edesc = EBinop(Oindex, b1, b2, TPtr(tres, [])); etyp = tres }
714 | MEMBEROF(a1, fieldname) ->
717 match unroll env b1.etyp with
718 | TStruct(id, attrs) ->
719 (wrap Env.find_struct_member loc env (id, fieldname), attrs)
720 | TUnion(id, attrs) ->
721 (wrap Env.find_union_member loc env (id, fieldname), attrs)
723 error "left-hand side of '.' is not a struct or union" in
724 (* A field of a const/volatile struct or union is itself const/volatile *)
725 { edesc = EUnop(Odot fieldname, b1);
726 etyp = add_attributes_type attrs fld.fld_typ }
728 | MEMBEROFPTR(a1, fieldname) ->
731 match unroll env b1.etyp with
733 begin match unroll env t with
734 | TStruct(id, attrs) ->
735 (wrap Env.find_struct_member loc env (id, fieldname), attrs)
736 | TUnion(id, attrs) ->
737 (wrap Env.find_union_member loc env (id, fieldname), attrs)
739 error "left-hand side of '->' is not a pointer to a struct or union"
742 error "left-hand side of '->' is not a pointer " in
743 { edesc = EUnop(Oarrow fieldname, b1);
744 etyp = add_attributes_type attrs fld.fld_typ }
746 (* Hack to treat vararg.h functions the GCC way. Helps with testing.
748 (preprocessing) --> __builtin_va_start(ap, arg)
749 (elaboration) --> __builtin_va_start(ap, &arg)
751 (preprocessing) --> __builtin_va_arg(ap, ty)
752 (parsing) --> __builtin_va_arg(ap, sizeof(ty))
754 | CALL((VARIABLE "__builtin_va_start" as a1), [a2; a3]) ->
755 let b1 = elab a1 and b2 = elab a2 and b3 = elab a3 in
756 { edesc = ECall(b1, [b2; {edesc = EUnop(Oaddrof, b3);
757 etyp = TPtr(b3.etyp, [])}]);
759 | CALL((VARIABLE "__builtin_va_arg" as a1),
760 [a2; (TYPE_SIZEOF _) as a3]) ->
761 let b1 = elab a1 and b2 = elab a2 and b3 = elab a3 in
762 let ty = match b3.edesc with ESizeof ty -> ty | _ -> assert false in
763 { edesc = ECall(b1, [b2; b3]); etyp = ty }
767 (* Catch the old-style usage of calling a function without
768 having declared it *)
770 | VARIABLE n when not (Env.ident_is_bound env n) ->
771 let ty = TFun(TInt(IInt, []), None, false, []) in
772 (* Emit an extern declaration for it *)
773 let id = Env.fresh_ident n in
774 emit_elab (elab_loc loc) (Gdecl(Storage_extern, id, ty, None));
775 { edesc = EVar id; etyp = ty }
777 let bl = List.map elab al in
778 (* Extract type information *)
779 let (res, args, vararg) =
780 match unroll env b1.etyp with
781 | TFun(res, args, vararg, a) -> (res, args, vararg)
783 begin match unroll env ty with
784 | TFun(res, args, vararg, a) -> (res, args, vararg)
785 | _ -> error "the function part of a call does not have a function type"
787 | _ -> error "the function part of a call does not have a function type"
789 (* Type-check the arguments against the prototype *)
793 | Some proto -> elab_arguments 1 bl proto vararg in
794 { edesc = ECall(b1, bl'); etyp = res }
796 | UNARY(POSINCR, a1) ->
797 elab_pre_post_incr_decr Opostincr "postfix '++'" a1
798 | UNARY(POSDECR, a1) ->
799 elab_pre_post_incr_decr Opostdecr "postfix '--'" a1
801 (* 7.5 Unary expressions *)
803 | CAST ((spec, dcl), SINGLE_INIT a1) ->
804 let ty = elab_type loc env spec dcl in
806 if not (valid_cast env b1.etyp ty) then
807 err "illegal cast from %a@ to %a" Cprint.typ b1.etyp Cprint.typ ty;
808 { edesc = ECast(ty, b1); etyp = ty }
810 | CAST ((spec, dcl), _) ->
811 error "cast of initializer expression is not supported"
813 | EXPR_SIZEOF(CONSTANT(CONST_STRING s)) ->
814 let cst = CInt(Int64.of_int (String.length s), size_t_ikind, "") in
815 { edesc = EConst cst; etyp = type_of_constant cst }
819 if sizeof env b1.etyp = None then
820 err "incomplete type %a" Cprint.typ b1.etyp;
821 { edesc = ESizeof b1.etyp; etyp = TInt(size_t_ikind, []) }
823 | TYPE_SIZEOF (spec, dcl) ->
824 let ty = elab_type loc env spec dcl in
825 if sizeof env ty = None then
826 err "incomplete type %a" Cprint.typ ty;
827 { edesc = ESizeof ty; etyp = TInt(size_t_ikind, []) }
831 if not (is_arith_type env b1.etyp) then
832 error "argument of unary '+' is not an arithmetic type";
833 { edesc = EUnop(Oplus, b1); etyp = unary_conversion env b1.etyp }
835 | UNARY(MINUS, a1) ->
837 if not (is_arith_type env b1.etyp) then
838 error "argument of unary '-' is not an arithmetic type";
839 { edesc = EUnop(Ominus, b1); etyp = unary_conversion env b1.etyp }
843 if not (is_integer_type env b1.etyp) then
844 error "argument of '~' is not an integer type";
845 { edesc = EUnop(Onot, b1); etyp = unary_conversion env b1.etyp }
849 if not (is_scalar_type env b1.etyp) then
850 error "argument of '!' is not a scalar type";
851 { edesc = EUnop(Olognot, b1); etyp = TInt(IInt, []) }
853 | UNARY(ADDROF, a1) ->
855 begin match unroll env b1.etyp with
856 | TArray _ | TFun _ -> ()
858 if not (is_lvalue env b1) then err "argument of '&' is not a l-value"
860 { edesc = EUnop(Oaddrof, b1); etyp = TPtr(b1.etyp, []) }
862 | UNARY(MEMOF, a1) ->
864 begin match unroll env b1.etyp with
865 (* '*' applied to a function type has no effect *)
867 | TPtr(ty, _) | TArray(ty, _, _) ->
868 { edesc = EUnop(Oderef, b1); etyp = ty }
870 error "argument of unary '*' is not a pointer"
873 | UNARY(PREINCR, a1) ->
874 elab_pre_post_incr_decr Opreincr "prefix '++'" a1
875 | UNARY(PREDECR, a1) ->
876 elab_pre_post_incr_decr Opredecr "prefix '--'" a1
878 (* 7.6 Binary operator expressions *)
880 | BINARY(MUL, a1, a2) ->
881 elab_binary_arithmetic "*" Omul a1 a2
883 | BINARY(DIV, a1, a2) ->
884 elab_binary_arithmetic "/" Odiv a1 a2
886 | BINARY(MOD, a1, a2) ->
887 elab_binary_integer "/" Omod a1 a2
889 | BINARY(ADD, a1, a2) ->
893 if is_arith_type env b1.etyp && is_arith_type env b2.etyp then
894 binary_conversion env b1.etyp b2.etyp
897 match unroll env b1.etyp, unroll env b2.etyp with
898 | (TPtr(ty, a) | TArray(ty, _, a)), TInt _ -> (ty, a)
899 | TInt _, (TPtr(ty, a) | TArray(ty, _, a)) -> (ty, a)
900 | _, _ -> error "type error in binary '+'" in
901 if not (pointer_arithmetic_ok env ty) then
902 err "illegal pointer arithmetic in binary '+'";
905 { edesc = EBinop(Oadd, b1, b2, tyres); etyp = tyres }
907 | BINARY(SUB, a1, a2) ->
911 if is_arith_type env b1.etyp && is_arith_type env b2.etyp then begin
912 let tyres = binary_conversion env b1.etyp b2.etyp in
915 match unroll env b1.etyp, unroll env b2.etyp with
916 | (TPtr(ty, a) | TArray(ty, _, a)), TInt _ ->
917 if not (pointer_arithmetic_ok env ty) then
918 err "illegal pointer arithmetic in binary '-'";
919 (TPtr(ty, a), TPtr(ty, a))
920 | TInt _, (TPtr(ty, a) | TArray(ty, _, a)) ->
921 if not (pointer_arithmetic_ok env ty) then
922 err "illegal pointer arithmetic in binary '-'";
923 (TPtr(ty, a), TPtr(ty, a))
924 | (TPtr(ty1, a1) | TArray(ty1, _, a1)),
925 (TPtr(ty2, a2) | TArray(ty2, _, a2)) ->
926 if not (compatible_types ~noattrs:true env ty1 ty2) then
927 err "mismatch between pointer types in binary '-'";
928 if not (pointer_arithmetic_ok env ty1) then
929 err "illegal pointer arithmetic in binary '-'";
930 (TPtr(ty1, []), TInt(ptrdiff_t_ikind, []))
931 | _, _ -> error "type error in binary '-'"
933 { edesc = EBinop(Osub, b1, b2, tyop); etyp = tyres }
935 | BINARY(SHL, a1, a2) ->
936 elab_shift "<<" Oshl a1 a2
938 | BINARY(SHR, a1, a2) ->
939 elab_shift ">>" Oshr a1 a2
941 | BINARY(EQ, a1, a2) ->
942 elab_comparison Oeq a1 a2
943 | BINARY(NE, a1, a2) ->
944 elab_comparison One a1 a2
945 | BINARY(LT, a1, a2) ->
946 elab_comparison Olt a1 a2
947 | BINARY(GT, a1, a2) ->
948 elab_comparison Ogt a1 a2
949 | BINARY(LE, a1, a2) ->
950 elab_comparison Ole a1 a2
951 | BINARY(GE, a1, a2) ->
952 elab_comparison Oge a1 a2
954 | BINARY(BAND, a1, a2) ->
955 elab_binary_integer "&" Oand a1 a2
956 | BINARY(BOR, a1, a2) ->
957 elab_binary_integer "|" Oor a1 a2
958 | BINARY(XOR, a1, a2) ->
959 elab_binary_integer "^" Oxor a1 a2
961 (* 7.7 Logical operator expressions *)
963 | BINARY(AND, a1, a2) ->
964 elab_logical_operator "&&" Ologand a1 a2
965 | BINARY(OR, a1, a2) ->
966 elab_logical_operator "||" Ologor a1 a2
968 (* 7.8 Conditional expressions *)
969 | QUESTION(a1, a2, a3) ->
973 if not (is_scalar_type env b1.etyp) then
974 err ("the first argument of '? :' is not a scalar type");
975 begin match pointer_decay env b2.etyp, pointer_decay env b3.etyp with
976 | (TInt _ | TFloat _), (TInt _ | TFloat _) ->
977 { edesc = EConditional(b1, b2, b3);
978 etyp = binary_conversion env b2.etyp b3.etyp }
979 | TPtr(ty1, a1), TPtr(ty2, a2) ->
981 if is_void_type env ty1 || is_void_type env ty2 then
982 TPtr(TVoid [], add_attributes a1 a2)
984 match combine_types ~noattrs:true env
985 (TPtr(ty1, a1)) (TPtr(ty2, a2)) with
987 error "the second and third arguments of '? :' \
988 have incompatible pointer types"
991 { edesc = EConditional(b1, b2, b3); etyp = tyres }
992 | TPtr(ty1, a1), TInt _ when is_literal_0 b3 ->
993 { edesc = EConditional(b1, b2, nullconst); etyp = TPtr(ty1, a1) }
994 | TInt _, TPtr(ty2, a2) when is_literal_0 b2 ->
995 { edesc = EConditional(b1, nullconst, b3); etyp = TPtr(ty2, a2) }
997 match combine_types env ty1 ty2 with
999 error ("the second and third arguments of '? :' have incompatible types")
1001 { edesc = EConditional(b1, b2, b3); etyp = tyres }
1004 (* 7.9 Assignment expressions *)
1006 | BINARY(ASSIGN, a1, a2) ->
1009 if not (is_lvalue env b1) then
1010 err "left-hand side of assignment is not a l-value";
1011 if List.mem AConst (attributes_of_type env b1.etyp) then
1012 err "left-hand side of assignment has 'const' type";
1013 if not (valid_assignment env b2 b1.etyp) then begin
1014 if valid_cast env b2.etyp b1.etyp then
1015 warning "assigning a value of type@ %a@ to a lvalue of type@ %a"
1016 Cprint.typ b2.etyp Cprint.typ b1.etyp
1018 err "assigning a value of type@ %a@ to a lvalue of type@ %a"
1019 Cprint.typ b2.etyp Cprint.typ b1.etyp;
1021 { edesc = EBinop(Oassign, b1, b2, b1.etyp); etyp = b1.etyp }
1023 | BINARY((ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN | DIV_ASSIGN | MOD_ASSIGN
1024 | BAND_ASSIGN | BOR_ASSIGN | XOR_ASSIGN | SHL_ASSIGN | SHR_ASSIGN
1028 | ADD_ASSIGN -> (ADD, Oadd_assign)
1029 | SUB_ASSIGN -> (SUB, Osub_assign)
1030 | MUL_ASSIGN -> (MUL, Omul_assign)
1031 | DIV_ASSIGN -> (DIV, Odiv_assign)
1032 | MOD_ASSIGN -> (MOD, Omod_assign)
1033 | BAND_ASSIGN -> (BAND, Oand_assign)
1034 | BOR_ASSIGN -> (BOR, Oor_assign)
1035 | XOR_ASSIGN -> (XOR, Oxor_assign)
1036 | SHL_ASSIGN -> (SHL, Oshl_assign)
1037 | SHR_ASSIGN -> (SHR, Oshr_assign)
1038 | _ -> assert false in
1039 begin match elab (BINARY(sop, a1, a2)) with
1040 | { edesc = EBinop(_, b1, b2, _); etyp = ty } as b ->
1041 if not (is_lvalue env b1) then
1042 err ("left-hand side of assignment is not a l-value");
1043 if List.mem AConst (attributes_of_type env b1.etyp) then
1044 err "left-hand side of assignment has 'const' type";
1045 if not (valid_assignment env b b1.etyp) then begin
1046 if valid_cast env ty b1.etyp then
1047 warning "assigning a value of type@ %a@ to a lvalue of type@ %a"
1048 Cprint.typ ty Cprint.typ b1.etyp
1050 err "assigning a value of type@ %a@ to a lvalue of type@ %a"
1051 Cprint.typ ty Cprint.typ b1.etyp;
1053 { edesc = EBinop(top, b1, b2, ty); etyp = b1.etyp }
1057 (* 7.10 Sequential expressions *)
1060 error "empty sequential expression"
1061 | COMMA (a1 :: al) -> (* watch for left associativity *)
1062 let rec elab_comma accu = function
1066 elab_comma { edesc = EBinop(Ocomma, accu, b, b.etyp); etyp = b.etyp } l
1067 in elab_comma (elab a1) al
1069 (* Extensions that we do not handle *)
1072 error "GCC's &&label construct is not supported"
1074 error "GCC's statements within expressions are not supported"
1075 | EXPR_ALIGNOF _ | TYPE_ALIGNOF _ ->
1076 error "GCC's __alignof__ construct is not supported"
1079 | EXPR_ALIGNOF a1 ->
1080 warning "nonstandard `alignof' expression, turned into a constant";
1082 begin match alignof env b1.etyp with
1083 | None -> error "incomplete type %a" Cprint.typ b1.etyp
1084 | Some al -> intconst (Int64.of_int al) size_t_ikind
1086 | TYPE_ALIGNOF (spec, dcl) ->
1087 warning "nonstandard `alignof' expression, turned into a constant";
1088 let ty = elab_type loc env spec dcl in
1089 begin match alignof env ty with
1090 | None -> error "incomplete type %a" Cprint.typ ty
1091 | Some al -> intconst (Int64.of_int al) size_t_ikind
1095 (* Elaboration of pre- or post- increment/decrement *)
1096 and elab_pre_post_incr_decr op msg a1 =
1098 if not (is_lvalue env b1) then
1099 err "the argument of %s is not a l-value" msg;
1100 if not (is_scalar_type env b1.etyp) then
1101 err "the argument of %s must be an arithmetic or pointer type" msg;
1102 { edesc = EUnop(op, b1); etyp = b1.etyp }
1104 (* Elaboration of binary operators over integers *)
1105 and elab_binary_integer msg op a1 a2 =
1107 if not (is_integer_type env b1.etyp) then
1108 error "the first argument of '%s' is not an integer type" msg;
1110 if not (is_integer_type env b2.etyp) then
1111 error "the second argument of '%s' is not an integer type" msg;
1112 let tyres = binary_conversion env b1.etyp b2.etyp in
1113 { edesc = EBinop(op, b1, b2, tyres); etyp = tyres }
1115 (* Elaboration of binary operators over arithmetic types *)
1116 and elab_binary_arithmetic msg op a1 a2 =
1118 if not (is_arith_type env b1.etyp) then
1119 error "the first argument of '%s' is not an arithmetic type" msg;
1121 if not (is_arith_type env b2.etyp) then
1122 error "the second argument of '%s' is not an arithmetic type" msg;
1123 let tyres = binary_conversion env b1.etyp b2.etyp in
1124 { edesc = EBinop(op, b1, b2, tyres); etyp = tyres }
1126 (* Elaboration of shift operators *)
1127 and elab_shift msg op a1 a2 =
1129 if not (is_integer_type env b1.etyp) then
1130 error "the first argument of '%s' is not an integer type" msg;
1132 if not (is_integer_type env b2.etyp) then
1133 error "the second argument of '%s' is not an integer type" msg;
1134 let tyres = unary_conversion env b1.etyp in
1135 { edesc = EBinop(op, b1, b2, tyres); etyp = tyres }
1137 (* Elaboration of comparisons *)
1138 and elab_comparison op a1 a2 =
1142 match pointer_decay env b1.etyp, pointer_decay env b2.etyp with
1143 | (TInt _ | TFloat _), (TInt _ | TFloat _) ->
1144 EBinop(op, b1, b2, binary_conversion env b1.etyp b2.etyp)
1145 | TInt _, TPtr(ty, _) when is_literal_0 b1 ->
1146 EBinop(op, nullconst, b2, TPtr(ty, []))
1147 | TPtr(ty, _), TInt _ when is_literal_0 b2 ->
1148 EBinop(op, b1, nullconst, TPtr(ty, []))
1149 | TPtr(ty1, _), TPtr(ty2, _)
1150 when is_void_type env ty1 ->
1151 EBinop(op, b1, b2, TPtr(ty2, []))
1152 | TPtr(ty1, _), TPtr(ty2, _)
1153 when is_void_type env ty2 ->
1154 EBinop(op, b1, b2, TPtr(ty1, []))
1155 | TPtr(ty1, _), TPtr(ty2, _) ->
1156 if not (compatible_types ~noattrs:true env ty1 ty2) then
1157 warning "comparison between incompatible pointer types";
1158 EBinop(op, b1, b2, TPtr(ty1, []))
1161 warning "comparison between integer and pointer";
1162 EBinop(op, b1, b2, TPtr(TVoid [], []))
1164 error "illegal comparison between types@ %a@ and %a"
1165 Cprint.typ b1.etyp Cprint.typ b2.etyp in
1166 { edesc = resdesc; etyp = TInt(IInt, []) }
1168 (* Elaboration of && and || *)
1169 and elab_logical_operator msg op a1 a2 =
1171 if not (is_scalar_type env b1.etyp) then
1172 err "the first argument of '%s' is not a scalar type" msg;
1174 if not (is_scalar_type env b2.etyp) then
1175 err "the second argument of '%s' is not a scalar type" msg;
1176 { edesc = EBinop(op, b1, b2, TInt(IInt, [])); etyp = TInt(IInt, []) }
1178 (* Type-checking of function arguments *)
1179 and elab_arguments argno args params vararg =
1180 match args, params with
1182 | [], _::_ -> err "not enough arguments in function call"; []
1186 else (err "too many arguments in function call"; args)
1187 | arg1 :: argl, (_, ty_p) :: paraml ->
1188 let ty_a = argument_conversion env arg1.etyp in
1189 if not (valid_assignment env {arg1 with etyp = ty_a} ty_p) then begin
1190 if valid_cast env ty_a ty_p then
1192 "argument #%d of function call has type@ %a@ \
1193 instead of the expected type@ %a"
1194 argno Cprint.typ ty_a Cprint.typ ty_p
1197 "argument #%d of function call has type@ %a@ \
1198 instead of the expected type@ %a"
1199 argno Cprint.typ ty_a Cprint.typ ty_p
1201 arg1 :: elab_arguments (argno + 1) argl paraml vararg
1205 (* Filling in forward declaration *)
1206 let _ = elab_expr_f := elab_expr
1208 let elab_opt_expr loc env = function
1210 | a -> Some (elab_expr loc env a)
1212 let elab_for_expr loc env = function
1213 | NOTHING -> { sdesc = Sskip; sloc = elab_loc loc }
1214 | a -> { sdesc = Sdo (elab_expr loc env a); sloc = elab_loc loc }
1217 (* Elaboration of initializers *)
1219 (* Initializers are first elaborated to the following type: *)
1221 let project_init loc il =
1224 if what <> NEXT_INIT then
1225 error loc "C99 initializers are not supported";
1229 let below_optsize n opt_sz =
1230 match opt_sz with None -> true | Some sz -> n < sz
1232 let init_char_array_string opt_size s =
1236 if below_optsize !len opt_size then begin
1237 init := Init_single (intconst x IChar) :: !init;
1238 len := Int64.succ !len
1240 for i = 0 to String.length s - 1 do
1241 enter (Int64.of_int (Char.code s.[i]))
1244 Init_array (List.rev !init)
1246 let init_int_array_wstring opt_size s =
1250 if below_optsize !len opt_size then begin
1251 init := Init_single (intconst x IInt) :: !init;
1252 len := Int64.succ !len
1256 Init_array (List.rev !init)
1258 let check_init_type loc env a ty =
1259 if valid_assignment env a ty then ()
1260 else if valid_cast env a.etyp ty then
1262 "initializer has type@ %a@ instead of the expected type @ %a"
1263 Cprint.typ a.etyp Cprint.typ ty
1266 "initializer has type@ %a@ instead of the expected type @ %a"
1267 Cprint.typ a.etyp Cprint.typ ty
1269 (* Build an initializer for type [ty], consuming initialization items
1270 from the list [ile]. Return a pair (initializer, items not consumed). *)
1272 let rec elab_init loc env ty ile =
1273 match unroll env ty with
1274 | TArray(ty_elt, opt_sz, _) ->
1275 let rec elab_init_array n accu rem =
1276 match opt_sz, rem with
1277 | Some sz, _ when n >= sz ->
1278 (Init_array(List.rev accu), rem)
1280 (Init_array(List.rev accu), rem)
1282 let (i, rem') = elab_init loc env ty_elt rem in
1283 elab_init_array (Int64.succ n) (i :: accu) rem' in
1284 begin match ile with
1285 (* char array = "string literal" *)
1286 | (SINGLE_INIT (CONSTANT (CONST_STRING s))
1287 | COMPOUND_INIT [_, SINGLE_INIT(CONSTANT (CONST_STRING s))]) :: ile1
1288 when (match unroll env ty_elt with
1289 | TInt((IChar|IUChar|ISChar), _) -> true
1291 (init_char_array_string opt_sz s, ile1)
1292 (* wchar array = L"wide string literal" *)
1293 | (SINGLE_INIT (CONSTANT (CONST_WSTRING s))
1294 | COMPOUND_INIT [_, SINGLE_INIT(CONSTANT (CONST_WSTRING s))]) :: ile1
1295 when (match unroll env ty_elt with
1298 (init_int_array_wstring opt_sz s, ile1)
1299 (* array = { elt, ..., elt } *)
1300 | COMPOUND_INIT ile1 :: ile2 ->
1301 let (ie, rem) = elab_init_array 0L [] (project_init loc ile1) in
1303 warning loc "excess elements at end of array initializer";
1305 (* array = elt, ..., elt (within a bigger compound initializer) *)
1307 elab_init_array 0L [] ile
1310 let ci = wrap Env.find_struct loc env id in
1311 let rec elab_init_fields fld accu rem =
1314 (Init_struct(id, List.rev accu), rem)
1316 let (i, rem') = elab_init loc env fld1.fld_typ rem in
1317 elab_init_fields fld' ((fld1, i) :: accu) rem' in
1318 begin match ile with
1319 (* struct = { elt, ..., elt } *)
1320 | COMPOUND_INIT ile1 :: ile2 ->
1322 elab_init_fields ci.ci_members [] (project_init loc ile1) in
1324 warning loc "excess elements at end of struct initializer";
1326 (* struct = elt, ..., elt (within a bigger compound initializer) *)
1328 elab_init_fields ci.ci_members [] ile
1331 let ci = wrap Env.find_union loc env id in
1333 match ci.ci_members with [] -> assert false | hd :: tl -> hd in
1334 begin match ile with
1335 (* union = { elt } *)
1336 | COMPOUND_INIT ile1 :: ile2 ->
1338 elab_init loc env fld1.fld_typ (project_init loc ile1) in
1340 warning loc "excess elements at end of union initializer";
1341 (Init_union(id, fld1, i), ile2)
1342 (* union = elt (within a bigger compound initializer) *)
1344 let (i, rem) = elab_init loc env fld1.fld_typ ile in
1345 (Init_union(id, fld1, i), rem)
1347 | TInt _ | TFloat _ | TPtr _ ->
1348 begin match ile with
1350 | SINGLE_INIT a :: ile1 ->
1351 let a' = elab_expr loc env a in
1352 check_init_type loc env a' ty;
1353 (Init_single a', ile1)
1354 (* scalar = nothing (within a bigger compound initializer) *)
1355 | (NO_INIT :: ile1) | ([] as ile1) ->
1356 begin match unroll env ty with
1357 | TInt _ -> (Init_single (intconst 0L IInt), ile1)
1358 | TFloat _ -> (Init_single (floatconst 0.0 FDouble), ile1)
1359 | TPtr _ -> (Init_single nullconst, ile1)
1362 | COMPOUND_INIT _ :: ile1 ->
1363 fatal_error loc "compound initializer for type@ %a" Cprint.typ ty
1366 fatal_error loc "impossible to initialize at type@ %a" Cprint.typ ty
1368 let elab_initial loc env ty ie =
1369 match unroll env ty, ie with
1370 | _, NO_INIT -> None
1371 (* scalar or composite = expr *)
1372 | (TInt _ | TFloat _ | TPtr _ | TStruct _ | TUnion _), SINGLE_INIT a ->
1373 let a' = elab_expr loc env a in
1374 check_init_type loc env a' ty;
1375 Some (Init_single a')
1377 array or struct or union = { elt, ..., elt } *)
1378 | (TArray _, SINGLE_INIT _)
1379 | ((TArray _ | TStruct _ | TUnion _), COMPOUND_INIT _) ->
1380 let (i, rem) = elab_init loc env ty [ie] in
1382 warning loc "excess elements at end of compound initializer";
1385 error loc "ill-formed initializer for type@ %a" Cprint.typ ty;
1388 (* Complete an array type with the size obtained from the initializer:
1389 "int x[] = { 1, 2, 3 }" becomes "int x[3] = ..." *)
1391 let fixup_typ env ty init =
1392 match unroll env ty, init with
1393 | TArray(ty_elt, None, attr), Init_array il ->
1394 TArray(ty_elt, Some(Int64.of_int(List.length il)), attr)
1399 let elab_initializer loc env ty ie =
1400 match elab_initial loc env ty ie with
1404 (fixup_typ env ty init, Some init)
1407 (* Elaboration of top-level and local definitions *)
1409 let enter_typedef loc env (s, sto, ty) =
1410 if sto <> Storage_default then
1411 error loc "Non-default storage on 'typedef' definition";
1412 if redef Env.lookup_typedef env s <> None then
1413 error loc "Redefinition of typedef '%s'" s;
1415 Env.enter_typedef env s ty in
1416 emit_elab (elab_loc loc) (Gtypedef(id, ty));
1419 let enter_or_refine_ident local loc env s sto ty =
1420 match redef Env.lookup_ident env s with
1421 | Some(id, II_ident(old_sto, old_ty)) ->
1424 error loc "redefinition of local variable '%s'" s;
1427 match combine_types env old_ty ty with
1431 warning loc "redefinition of '%s' with incompatible type" s; ty
1434 if old_sto = Storage_extern then sto else
1435 if sto = Storage_extern then old_sto else
1436 if old_sto = sto then sto else begin
1437 warning loc "redefinition of '%s' with incompatible storage class" s;
1440 (id, Env.add_ident env id new_sto new_ty)
1441 | Some(id, II_enum v) ->
1442 error loc "illegal redefinition of enumerator '%s'" s;
1443 (id, Env.add_ident env id sto ty)
1445 Env.enter_ident env s sto ty
1447 let rec enter_decdefs local loc env = function
1450 | (s, sto, ty, init) :: rem ->
1451 (* Sanity checks on storage class *)
1452 begin match sto with
1454 if init <> NO_INIT then error loc
1455 "'extern' declaration cannot have an initializer"
1456 | Storage_register ->
1457 if not local then error loc "'register' on global declaration"
1460 (* function declarations are always extern *)
1462 match unroll env ty with TFun _ -> Storage_extern | _ -> sto in
1463 (* enter ident in environment with declared type, because
1464 initializer can refer to the ident *)
1465 let (id, env1) = enter_or_refine_ident local loc env s sto' ty in
1466 (* process the initializer *)
1467 let (ty', init') = elab_initializer loc env1 ty init in
1468 (* update environment with refined type *)
1469 let env2 = Env.add_ident env1 id sto' ty' in
1470 (* check for incomplete type *)
1471 if sto' <> Storage_extern && incomplete_type env ty' then
1472 warning loc "'%s' has incomplete type" s;
1473 if local && sto <> Storage_extern && sto <> Storage_static then begin
1474 (* Local definition *)
1475 let (decls, env3) = enter_decdefs local loc env2 rem in
1476 ((sto', id, ty', init') :: decls, env3)
1478 (* Global definition *)
1479 emit_elab (elab_loc loc) (Gdecl(sto, id, ty', init'));
1480 enter_decdefs local loc env2 rem
1483 let elab_fundef env (spec, name) body loc1 loc2 =
1484 let (s, sto, inline, ty, env1) = elab_name env spec name in
1485 if sto = Storage_register then
1486 error loc1 "a function definition cannot have 'register' storage class";
1487 (* Fix up the type. We can have params = None but only for an
1488 old-style parameterless function "int f() {...}" *)
1491 | TFun(ty_ret, None, vararg, attr) -> TFun(ty_ret, Some [], vararg, attr)
1493 (* Extract info from type *)
1494 let (ty_ret, params, vararg) =
1496 | TFun(ty_ret, Some params, vararg, attr) -> (ty_ret, params, vararg)
1497 | _ -> fatal_error loc1 "wrong type for function definition" in
1498 (* Enter function in the environment, for recursive references *)
1499 let (fun_id, env1) = enter_or_refine_ident false loc1 env s sto ty in
1500 (* Enter parameters in the environment *)
1502 List.fold_left (fun e (id, ty) -> Env.add_ident e id Storage_default ty)
1503 (Env.new_scope env1) params in
1504 (* Elaborate function body *)
1505 let body' = !elab_block_f loc2 ty_ret env2 body in
1506 (* Build and emit function definition *)
1515 fd_body = body' } in
1516 emit_elab (elab_loc loc1) (Gfundef fn);
1519 let rec elab_definition (local: bool) (env: Env.t) (def: Cabs.definition)
1520 : decl list * Env.t =
1522 (* "int f(int x) { ... }" *)
1523 | FUNDEF(spec_name, body, loc1, loc2) ->
1524 if local then error loc1 "local definition of a function";
1525 let env1 = elab_fundef env spec_name body loc1 loc2 in
1528 (* "int x = 12, y[10], *z" *)
1529 | DECDEF(init_name_group, loc) ->
1530 let (dl, env1) = elab_init_name_group env init_name_group in
1531 enter_decdefs local loc env1 dl
1533 (* "typedef int * x, y[10]; " *)
1534 | TYPEDEF(namegroup, loc) ->
1535 let (dl, env1) = elab_name_group env namegroup in
1536 let env2 = List.fold_left (enter_typedef loc) env1 dl in
1539 (* "struct s { ...};" or "union u;" *)
1540 | ONLYTYPEDEF(spec, loc) ->
1541 let (sto, inl, ty, env') = elab_specifier ~only:true loc env spec in
1542 if sto <> Storage_default || inl then
1543 error loc "Non-default storage or 'inline' on 'struct' or 'union' declaration";
1546 (* global asm statement *)
1547 | GLOBASM(_, loc) ->
1548 error loc "Top-level 'asm' statement is not supported";
1553 emit_elab (elab_loc loc) (Gpragma s);
1556 (* extern "C" { ... } *)
1557 | LINKAGE(_, loc, defs) ->
1558 elab_definitions local env defs
1560 and elab_definitions local env = function
1563 let (decl1, env1) = elab_definition local env d1 in
1564 let (decl2, env2) = elab_definitions local env1 dl in
1565 (decl1 @ decl2, env2)
1568 (* Elaboration of statements *)
1570 (* Extract list of Cabs statements from a Cabs block *)
1572 let block_body loc b =
1573 if b.blabels <> [] then
1574 error loc "GCC's '__label__' declaration is not supported";
1575 if b.battrs <> [] then
1576 warning loc "ignoring attributes on this block";
1579 (* Elaboration of a block. Return the corresponding C statement. *)
1581 let elab_block loc return_typ env b =
1583 let rec elab_stmt env s =
1587 (* 8.2 Expression statements *)
1589 | COMPUTATION(a, loc) ->
1590 { sdesc = Sdo (elab_expr loc env a); sloc = elab_loc loc }
1592 (* 8.3 Labeled statements *)
1594 | LABEL(lbl, s1, loc) ->
1595 { sdesc = Slabeled(Slabel lbl, elab_stmt env s1); sloc = elab_loc loc }
1597 | CASE(a, s1, loc) ->
1598 let a' = elab_expr loc env a in
1599 begin match Ceval.integer_expr env a' with
1601 error loc "argument of 'case' must be an integer compile-time constant"
1604 { sdesc = Slabeled(Scase a', elab_stmt env s1); sloc = elab_loc loc }
1606 | CASERANGE(_, _, _, loc) ->
1607 error loc "GCC's 'case' with range of values is not supported";
1610 | DEFAULT(s1, loc) ->
1611 { sdesc = Slabeled(Sdefault, elab_stmt env s1); sloc = elab_loc loc }
1613 (* 8.4 Compound statements *)
1618 (* 8.5 Conditional statements *)
1620 | IF(a, s1, s2, loc) ->
1621 let a' = elab_expr loc env a in
1622 if not (is_scalar_type env a'.etyp) then
1623 error loc "the condition of 'if' does not have scalar type";
1624 let s1' = elab_stmt env s1 in
1625 let s2' = elab_stmt env s2 in
1626 { sdesc = Sif(a', s1', s2'); sloc = elab_loc loc }
1628 (* 8.6 Iterative statements *)
1630 | WHILE(a, s1, loc) ->
1631 let a' = elab_expr loc env a in
1632 if not (is_scalar_type env a'.etyp) then
1633 error loc "the condition of 'while' does not have scalar type";
1634 let s1' = elab_stmt env s1 in
1635 { sdesc = Swhile(a', s1'); sloc = elab_loc loc }
1637 | DOWHILE(a, s1, loc) ->
1638 let s1' = elab_stmt env s1 in
1639 let a' = elab_expr loc env a in
1640 if not (is_scalar_type env a'.etyp) then
1641 error loc "the condition of 'while' does not have scalar type";
1642 { sdesc = Sdowhile(s1', a'); sloc = elab_loc loc }
1644 | FOR(fc, a2, a3, s1, loc) ->
1648 elab_for_expr loc env a1
1650 error loc "C99 declaration within `for' not supported";
1654 then intconst 1L IInt
1655 else elab_expr loc env a2 in
1656 if not (is_scalar_type env a2'.etyp) then
1657 error loc "the condition of 'for' does not have scalar type";
1658 let a3' = elab_for_expr loc env a3 in
1659 let s1' = elab_stmt env s1 in
1660 { sdesc = Sfor(a1', a2', a3', s1'); sloc = elab_loc loc }
1662 (* 8.7 Switch statement *)
1663 | SWITCH(a, s1, loc) ->
1664 let a' = elab_expr loc env a in
1665 if not (is_arith_type env a'.etyp) then
1666 error loc "the argument of 'switch' does not have arithmetic type";
1667 let s1' = elab_stmt env s1 in
1668 { sdesc = Sswitch(a', s1'); sloc = elab_loc loc }
1670 (* 8,8 Break and continue statements *)
1672 { sdesc = Sbreak; sloc = elab_loc loc }
1674 { sdesc = Scontinue; sloc = elab_loc loc }
1676 (* 8.9 Return statements *)
1678 let a' = elab_opt_expr loc env a in
1679 begin match (unroll env return_typ, a') with
1680 | TVoid _, None -> ()
1681 | TVoid _, Some _ ->
1683 "'return' with a value in a function of return type 'void'"
1686 "'return' without a value in a function of return type@ %a"
1687 Cprint.typ return_typ
1689 if not (valid_assignment env b return_typ) then begin
1690 if valid_cast env b.etyp return_typ then
1692 "return value has type@ %a@ \
1693 instead of the expected type@ %a"
1694 Cprint.typ b.etyp Cprint.typ return_typ
1697 "return value has type@ %a@ \
1698 instead of the expected type@ %a"
1699 Cprint.typ b.etyp Cprint.typ return_typ
1702 { sdesc = Sreturn a'; sloc = elab_loc loc }
1704 (* 8.10 Goto statements *)
1706 { sdesc = Sgoto lbl; sloc = elab_loc loc }
1708 (* 8.11 Null statements *)
1710 { sdesc = Sskip; sloc = elab_loc loc }
1714 error (get_definitionloc def) "ill-placed definition";
1716 | COMPGOTO(a, loc) ->
1717 error loc "GCC's computed 'goto' is not supported";
1719 | ASM(_, _, _, loc) ->
1720 error loc "'asm' statement is not supported";
1722 | TRY_EXCEPT(_, _, _, loc) ->
1723 error loc "'try ... except' statement is not supported";
1725 | TRY_FINALLY(_, _, loc) ->
1726 error loc "'try ... finally' statement is not supported";
1729 and elab_blk loc env b =
1730 let b' = elab_blk_body (Env.new_scope env) (block_body loc b) in
1731 { sdesc = Sblock b'; sloc = elab_loc loc }
1733 and elab_blk_body env sl =
1737 | DEFINITION def :: sl1 ->
1738 let (dcl, env') = elab_definition true env def in
1739 let loc = elab_loc (get_definitionloc def) in
1740 List.map (fun d -> {sdesc = Sdecl d; sloc = loc}) dcl
1741 @ elab_blk_body env' sl1
1743 let s' = elab_stmt env s in
1744 s' :: elab_blk_body env sl1
1746 in elab_blk loc env b
1748 (* Filling in forward declaration *)
1749 let _ = elab_block_f := elab_block
1752 (** * Entry point *)
1754 let elab_preprocessed_file name ic =
1755 let lb = Lexer.init name ic in
1757 ignore (elab_definitions false (Builtins.environment())
1758 (Parser.file Lexer.initial lb));
1760 elaborated_program()