Skip to content

Commit ec033c3

Browse files
committed
Fix elaboration of function definitions with nested function types
Since commit ea3a41b, `elab_type_declarator` has a special case for function definitions, causing it to include the function parameters in the returned updated typing environment. However, this special case was wrong for nested function types such as ``` int (*f(int y))(int x) { ... } ``` `f` is a function taking an `y` parameter and returning a function `(x: int) -> int`. The special case causes both `x` and `y` to be included in the returned environment, while only `y` should be. This commit makes sure that the special case for function definitions applies only to the outermost function type, i.e. the innermost `Cabs.PROTO` declarator. A similar issue was handled correctly in the `Cabs.PROTO_OLD` case, so this commit tries to use the same code structure in the `PROTO` and `PROTO_OLD` cases.
1 parent 3f217e3 commit ec033c3

File tree

3 files changed

+25
-18
lines changed

3 files changed

+25
-18
lines changed

Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Code generation and optimization:
2020
Bug fixes:
2121
- More robust determination of symbols that may be defined in a shared object. (#538)
2222
- Escape `$NNN` identifiers in generated x86 and ARM assembly code (#541).
23+
- Wrong parameter scoping in function definitions such as `int (*f(int y))(int x) { ... }` (a function returning a pointer to a prototyped function).
2324

2425
Usability:
2526
- Mark stack as non-executable in binaries produced by `ccomp`.

cparser/Elab.ml

+23-17
Original file line numberDiff line numberDiff line change
@@ -924,28 +924,34 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
924924
elab_return_type loc env ty;
925925
let (ty, a) = get_nontype_attrs env ty in
926926
let (params', env') = elab_parameters loc env params in
927-
(* For a function declaration (fundef = false), the scope introduced
928-
to treat parameters ends here, so we discard the extended
929-
environment env' returned by elab_parameters.
930-
For a function definition (fundef = true) we return the
931-
extended environment env' so that it can serve as the basis
932-
to elaborating the function body. *)
933-
let env'' = if fundef then env' else env in
934-
elab_type_declarator ~fundef loc env'' (TFun(ty, Some params', vararg, a)) d
927+
let funty = TFun(ty, Some params', vararg, a) in
928+
(* For a function declaration (fundef = false or d <> JUSTBASE),
929+
the scope introduced to treat parameters ends here, so we
930+
discard the extended environment env' returned by
931+
elab_parameters.
932+
For a function definition (fundef = true and d = JUSTBASE),
933+
we return the extended environment env' so that it can serve
934+
as the basis to elaborating the function body. *)
935+
if fundef && d = Cabs.JUSTBASE then
936+
((funty, None), env')
937+
else
938+
elab_type_declarator ~fundef loc env funty d
935939
| Cabs.PROTO_OLD(d, params) ->
936940
elab_return_type loc env ty;
937941
let (ty, a) = get_nontype_attrs env ty in
942+
let funty = TFun(ty, None, false, a) in
938943
(* For consistency with the PROTO case above, for a function definition
939-
(fundef = true) we open a new scope, even though we do not
940-
add any bindings for the parameters. *)
941-
let env'' = if fundef then Env.new_scope env else env in
942-
match params with
943-
| [] ->
944-
elab_type_declarator ~fundef loc env'' (TFun(ty, None, false, a)) d
945-
| _ ->
946-
if not fundef || d <> Cabs.JUSTBASE then
944+
(fundef = true and d = JUSTBASE) we open a new scope, even
945+
though we do not add any bindings for the parameters. *)
946+
if fundef && d = Cabs.JUSTBASE then begin
947+
let env' = Env.new_scope env in
948+
let opt_params = if params = [] then None else Some params in
949+
((funty, opt_params), env')
950+
end else begin
951+
if params <> [] then
947952
fatal_error loc "illegal old-style K&R function definition";
948-
((TFun(ty, None, false, a), Some params), env'')
953+
elab_type_declarator ~fundef loc env funty d
954+
end
949955

950956
(* Elaboration of parameters in a prototype *)
951957

0 commit comments

Comments
 (0)