Skip to content

Commit 8a89973

Browse files
committed
Perform basic checks over [static expr] array declarators
Check that they occur only in function prototypes and only in outermost position. The error messages are those used by clang.
1 parent fa44750 commit 8a89973

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

cparser/Elab.ml

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,6 @@ and elab_cvspec env = function
871871
and elab_cvspecs env cv_specs =
872872
List.fold_left add_attributes [] (List.map (elab_cvspec env) cv_specs)
873873

874-
(* Elaboration of a type declarator. C99 section 6.7.5. *)
875874
and elab_return_type loc env ty =
876875
match unroll env ty with
877876
| TArray _ ->
@@ -880,14 +879,20 @@ and elab_return_type loc env ty =
880879
error loc "function cannot return function type %a" (print_typ env) ty
881880
| _ -> ()
882881

882+
(* Elaboration of a type declarator. C99 section 6.7.5. *)
883+
883884
(* The [?fundef] parameter is true if we're elaborating a function definition
884885
and false otherwise. When [fundef = true], K&R function declarators
885886
are allowed, and the returned environment includes bindings for the
886887
function parameters and the struct/unions they may define.
887888
When [fundef = false], K&R function declarators are rejected
888889
and declarations in parameters are not returned. *)
889890

890-
and elab_type_declarator ?(fundef = false) loc env ty = function
891+
(* The [?param] parameter is true if we're elaborating a parameter
892+
of a function prototype, and false otherwise.
893+
This is used for checking 'static' array declarators. *)
894+
895+
and elab_type_declarator ?(fundef = false) ?(param = false) loc env ty = function
891896
| Cabs.JUSTBASE ->
892897
((ty, None), env)
893898
| Cabs.ARRAY(d, cv_specs, static, sz) ->
@@ -897,6 +902,13 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
897902
error loc "array type has incomplete element type %a" (print_typ env) ty;
898903
if wrap contains_flex_array_mem loc env ty then
899904
warning loc Flexible_array_extensions "%a may not be used as an array element due to flexible array member" (print_typ env) ty;
905+
if static then begin
906+
assert (sz <> None); (* guaranteed by the parser *)
907+
if not param then
908+
error loc "'static' used in array declarator outside of function prototype"
909+
else if d <> Cabs.JUSTBASE then
910+
error loc "'static' used in non-outermost array type derivation"
911+
end;
900912
let sz' =
901913
match sz with
902914
| None ->
@@ -913,13 +925,13 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
913925
| None ->
914926
error loc "size of array is not a compile-time constant";
915927
Some 1L in (* produces better error messages later *)
916-
elab_type_declarator ~fundef loc env (TArray(ty, sz', a)) d
928+
elab_type_declarator ~fundef ~param loc env (TArray(ty, sz', a)) d
917929
| Cabs.PTR(cv_specs, d) ->
918930
let (ty, a) = get_nontype_attrs env ty in
919931
let a = add_attributes a (elab_cvspecs env cv_specs) in
920932
if is_function_type env ty && incl_attributes [ARestrict] a then
921933
error loc "pointer to function type %a may not be 'restrict' qualified" (print_typ env) ty;
922-
elab_type_declarator ~fundef loc env (TPtr(ty, a)) d
934+
elab_type_declarator ~fundef ~param loc env (TPtr(ty, a)) d
923935
| Cabs.PROTO(d, (params, vararg)) ->
924936
elab_return_type loc env ty;
925937
let (ty, a) = get_nontype_attrs env ty in
@@ -935,7 +947,7 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
935947
if fundef && d = Cabs.JUSTBASE then
936948
((funty, None), env')
937949
else
938-
elab_type_declarator ~fundef loc env funty d
950+
elab_type_declarator ~fundef ~param loc env funty d
939951
| Cabs.PROTO_OLD(d, params) ->
940952
elab_return_type loc env ty;
941953
let (ty, a) = get_nontype_attrs env ty in
@@ -950,7 +962,7 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
950962
end else begin
951963
if params <> [] then
952964
fatal_error loc "illegal old-style K&R function definition";
953-
elab_type_declarator ~fundef loc env funty d
965+
elab_type_declarator ~fundef ~param loc env funty d
954966
end
955967

956968
(* Elaboration of parameters in a prototype *)
@@ -971,7 +983,7 @@ and elab_parameter env (PARAM (spec, id, decl, attr, loc)) =
971983
let (sto, inl, noret, tydef, bty, env1) = elab_specifier loc env spec in
972984
if tydef then
973985
error loc "'typedef' used in function parameter";
974-
let ((ty, _), _) = elab_type_declarator loc env1 bty decl in
986+
let ((ty, _), _) = elab_type_declarator ~param:true loc env1 bty decl in
975987
let ty = add_attributes_type (elab_attributes env attr) ty in
976988
if sto <> Storage_default && sto <> Storage_register then
977989
error loc (* NB: 'auto' not allowed *)
@@ -1014,7 +1026,7 @@ and elab_fundef_name env spec (Name (s, decl, attr, loc)) =
10141026
error loc "'typedef' is forbidden here";
10151027
let id = Env.fresh_ident s in
10161028
let ((ty, kr_params), env'') =
1017-
elab_type_declarator ~fundef:true loc env' bty decl in
1029+
elab_type_declarator ~fundef:true ~param:true loc env' bty decl in
10181030
let a = elab_attributes env attr in
10191031
(id, sto, inl, noret, add_attributes_type a ty, kr_params, env', env'')
10201032

0 commit comments

Comments
 (0)