summaryrefslogtreecommitdiff
path: root/cparser/Elab.ml
diff options
context:
space:
mode:
authorGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2014-05-05 08:27:22 +0000
committerGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2014-05-05 08:27:22 +0000
commitdba806ca25b5bc53b744e2c1c2d72fa3d6cd8e05 (patch)
treeefdded5c1b088beb82043d0bb2a7003726205ab2 /cparser/Elab.ml
parentf3a4e6b8796f8358ff85a7a50d1a14fe0e5642b1 (diff)
Support for old-style K&R function definitions.
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@2478 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'cparser/Elab.ml')
-rw-r--r--cparser/Elab.ml46
1 files changed, 46 insertions, 0 deletions
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 780cf09..d19b988 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -1874,6 +1874,46 @@ let elab_fundef env spec name body loc =
emit_elab loc (Gfundef fn);
env1
+let elab_kr_fundef env spec name params defs body loc =
+ (* Check that the declarations only declare parameters *)
+ let check_one_decl (Init_name(Name(s, dty, attrs, loc'), ie)) =
+ if not (List.mem s params) then
+ error loc' "Declaration of '%s' which is not a function parameter" s;
+ if ie <> NO_INIT then
+ error loc' "Illegal initialization of function parameter '%s'" s in
+ let check_decl = function
+ | DECDEF((spec', name_init_list), loc') ->
+ List.iter check_one_decl name_init_list
+ | d ->
+ (* Should never be produced by the parser *)
+ fatal_error (get_definitionloc d)
+ "Illegal declaration of function parameter" in
+ List.iter check_decl defs;
+ (* Convert old-style K&R function definition to modern prototyped form *)
+ let rec convert_param param = function
+ | [] ->
+ (* Parameter is not declared, defaults to "int" in ISO C90,
+ is an error in ISO C99. Just emit a warning. *)
+ warning loc "Type of '%s' defaults to 'int'" param;
+ PARAM([SpecType Tint], Some param, JUSTBASE, [], loc)
+ | DECDEF((spec', name_init_list), loc') :: defs ->
+ let rec convert = function
+ | [] -> convert_param param defs
+ | Init_name(Name(s, dty, attrs, loc''), ie) :: l ->
+ if s = param
+ then PARAM(spec', Some param, dty, attrs, loc'')
+ else convert l
+ in convert name_init_list
+ | _ ->
+ assert false (* checked earlier *) in
+ let params' =
+ List.map (fun p -> convert_param p defs) params in
+ let name' =
+ let (Name(s, dty, attr, loc')) = name in
+ Name(s, PROTO(dty, (params', false)), attr, loc') in
+ (* Elaborate the prototyped form *)
+ elab_fundef env spec name' body loc
+
let rec elab_definition (local: bool) (env: Env.t) (def: Cabs.definition)
: decl list * Env.t =
match def with
@@ -1883,6 +1923,12 @@ let rec elab_definition (local: bool) (env: Env.t) (def: Cabs.definition)
let env1 = elab_fundef env spec name body loc in
([], env1)
+ (* "int f(x, y) double y; { ... }" *)
+ | KRFUNDEF(spec, name, params, defs, body, loc) ->
+ if local then error loc "local definition of a function";
+ let env1 = elab_kr_fundef env spec name params defs body loc in
+ ([], env1)
+
(* "int x = 12, y[10], *z" *)
| DECDEF(init_name_group, loc) ->
let ((dl, env1), sto, tydef) =