aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2018-05-24 16:01:30 +0200
committerXavier Leroy <xavierleroy@users.noreply.github.com>2018-05-26 11:05:13 +0200
commit9dc1505c01a5748cdd5cac9d978645e2fbc0773c (patch)
tree6a75c4cb0b096b5744603e37dc4491ac324da8db
parent2b2585f39000f7000f296bc5b35c14e70f0c31fe (diff)
downloadcompcert-kvx-9dc1505c01a5748cdd5cac9d978645e2fbc0773c.tar.gz
compcert-kvx-9dc1505c01a5748cdd5cac9d978645e2fbc0773c.zip
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(); }
-rw-r--r--cparser/Elab.ml17
1 files 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 *)