From 9dc1505c01a5748cdd5cac9d978645e2fbc0773c Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Thu, 24 May 2018 16:01:30 +0200 Subject: Preserve storage class for functions declared within a block This is a follow-up to the introduction of the Storage_auto storage class in commit 760e422. For functions declared within a block, we used to set their storage class to "extern": { { int f(void); ---> extern int f(void); } } This helped enter_or_refine_ident understand that those declarations have linkage. Now that we have Storage_auto, this commit teaches enter_or_refine_ident that local declarations have no linkage if auto or static, and have linkage if extern or default. Then, there is no need to change storage class to extern for locally-declared functions. In turn, this improves the "extern-after-definition" warning recently introduced, avoiding a bizarre warning in the following case: int foo(void){return 0;} int main(void){ int foo(void); return foo(); } --- cparser/Elab.ml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cparser/Elab.ml b/cparser/Elab.ml index dd404d38..6923491a 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -211,9 +211,11 @@ let enter_or_refine_ident_base local loc env new_id sto ty = | _ -> () end; - (* For a block-scoped, non-"extern" variable, a new declaration - is entered, and it has no linkage. *) - if local && sto <> Storage_extern then begin + (* For a block-scoped, "static" or "auto" or "register" variable, + a new declaration is entered, and it has no linkage. *) + if local + && (sto = Storage_auto || sto = Storage_register || sto = Storage_static) + then begin (new_id, sto, Env.add_ident env new_id sto ty, ty, false) end else begin (* For a file-scoped or "extern" variable, we need to check against @@ -2293,11 +2295,12 @@ let enter_decdefs local loc env sto dl = (name_of_storage_class sto) | _ -> () end; - (* Local function declarations are always treated as extern *) - (* Local variable declarations with default storage are treated as 'auto' *) + (* Local variable declarations with default storage are treated as 'auto'. + Local function declarations with default storage remain with + default storage. *) let sto1 = - if local && isfun then Storage_extern - else if local && sto = Storage_default then Storage_auto + if local && sto = Storage_default && not isfun + then Storage_auto else sto in (* enter ident in environment with declared type, because initializer can refer to the ident *) -- cgit