Skip to content

Commit

Permalink
Perform basic checks over [static expr] array declarators
Browse files Browse the repository at this point in the history
Check that they occur only in function prototypes and only in
outermost position.

The error messages are those used by clang.
  • Loading branch information
xavierleroy committed Jan 17, 2025
1 parent fa44750 commit 8a89973
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions cparser/Elab.ml
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,6 @@ and elab_cvspec env = function
and elab_cvspecs env cv_specs =
List.fold_left add_attributes [] (List.map (elab_cvspec env) cv_specs)

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

(* Elaboration of a type declarator. C99 section 6.7.5. *)

(* The [?fundef] parameter is true if we're elaborating a function definition
and false otherwise. When [fundef = true], K&R function declarators
are allowed, and the returned environment includes bindings for the
function parameters and the struct/unions they may define.
When [fundef = false], K&R function declarators are rejected
and declarations in parameters are not returned. *)

and elab_type_declarator ?(fundef = false) loc env ty = function
(* The [?param] parameter is true if we're elaborating a parameter
of a function prototype, and false otherwise.
This is used for checking 'static' array declarators. *)

and elab_type_declarator ?(fundef = false) ?(param = false) loc env ty = function
| Cabs.JUSTBASE ->
((ty, None), env)
| Cabs.ARRAY(d, cv_specs, static, sz) ->
Expand All @@ -897,6 +902,13 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
error loc "array type has incomplete element type %a" (print_typ env) ty;
if wrap contains_flex_array_mem loc env ty then
warning loc Flexible_array_extensions "%a may not be used as an array element due to flexible array member" (print_typ env) ty;
if static then begin
assert (sz <> None); (* guaranteed by the parser *)
if not param then
error loc "'static' used in array declarator outside of function prototype"
else if d <> Cabs.JUSTBASE then
error loc "'static' used in non-outermost array type derivation"
end;
let sz' =
match sz with
| None ->
Expand All @@ -913,13 +925,13 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
| None ->
error loc "size of array is not a compile-time constant";
Some 1L in (* produces better error messages later *)
elab_type_declarator ~fundef loc env (TArray(ty, sz', a)) d
elab_type_declarator ~fundef ~param loc env (TArray(ty, sz', a)) d
| Cabs.PTR(cv_specs, d) ->
let (ty, a) = get_nontype_attrs env ty in
let a = add_attributes a (elab_cvspecs env cv_specs) in
if is_function_type env ty && incl_attributes [ARestrict] a then
error loc "pointer to function type %a may not be 'restrict' qualified" (print_typ env) ty;
elab_type_declarator ~fundef loc env (TPtr(ty, a)) d
elab_type_declarator ~fundef ~param loc env (TPtr(ty, a)) d
| Cabs.PROTO(d, (params, vararg)) ->
elab_return_type loc env ty;
let (ty, a) = get_nontype_attrs env ty in
Expand All @@ -935,7 +947,7 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
if fundef && d = Cabs.JUSTBASE then
((funty, None), env')
else
elab_type_declarator ~fundef loc env funty d
elab_type_declarator ~fundef ~param loc env funty d
| Cabs.PROTO_OLD(d, params) ->
elab_return_type loc env ty;
let (ty, a) = get_nontype_attrs env ty in
Expand All @@ -950,7 +962,7 @@ and elab_type_declarator ?(fundef = false) loc env ty = function
end else begin
if params <> [] then
fatal_error loc "illegal old-style K&R function definition";
elab_type_declarator ~fundef loc env funty d
elab_type_declarator ~fundef ~param loc env funty d
end

(* Elaboration of parameters in a prototype *)
Expand All @@ -971,7 +983,7 @@ and elab_parameter env (PARAM (spec, id, decl, attr, loc)) =
let (sto, inl, noret, tydef, bty, env1) = elab_specifier loc env spec in
if tydef then
error loc "'typedef' used in function parameter";
let ((ty, _), _) = elab_type_declarator loc env1 bty decl in
let ((ty, _), _) = elab_type_declarator ~param:true loc env1 bty decl in
let ty = add_attributes_type (elab_attributes env attr) ty in
if sto <> Storage_default && sto <> Storage_register then
error loc (* NB: 'auto' not allowed *)
Expand Down Expand Up @@ -1014,7 +1026,7 @@ and elab_fundef_name env spec (Name (s, decl, attr, loc)) =
error loc "'typedef' is forbidden here";
let id = Env.fresh_ident s in
let ((ty, kr_params), env'') =
elab_type_declarator ~fundef:true loc env' bty decl in
elab_type_declarator ~fundef:true ~param:true loc env' bty decl in
let a = elab_attributes env attr in
(id, sto, inl, noret, add_attributes_type a ty, kr_params, env', env'')

Expand Down

0 comments on commit 8a89973

Please sign in to comment.