From 2892e2caa89f927062824ca901562d085a76d619 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Sat, 25 Sep 2021 12:03:55 +0200 Subject: Ignore unnamed plain members of structs and unions E.g. `struct { int; int x; };`. The `int;` declaration provides no name, is not a bit field, and is not a C11 anonymous struct/union member. Such declarations are not allowed by the C99 grammar, even though GCC, Clang and CompCert tolerate them. The C11 grammar allows these declarations but the standard text gives them no meaning. CompCert used to warn about such declarations, yet include them in the struct or union as unnamed members, similar to an unnamed bit field. This is incorrect and inconsistent with what GCC and Clang do. With this commit, CompCert still warns, then ignores the declaration and does not create an unnamed member. This is consistent with GCC and Clang. Fixes: #411 --- cparser/Elab.ml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'cparser') diff --git a/cparser/Elab.ml b/cparser/Elab.ml index a5b87e2e..a78dc9d9 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -125,14 +125,15 @@ let rec mmap f env = function let (tl', env2) = mmap f env1 tl in (hd' :: tl', env2) -let rec mmap2 f env l1 l2 = +let rec mmap2_filter f env l1 l2 = match l1,l2 with - | [],[] -> [],env - | a1::l1,a2::l2 -> - let hd,env1 = f env a1 a2 in - let tl,env2 = mmap2 f env1 l1 l2 in - (hd::tl,env2) - | _, _ -> invalid_arg "mmap2" + | [], [] -> ([], env) + | a1 :: l1, a2 :: l2 -> + let (opt_hd, env1) = f env a1 a2 in + let (tl, env2) = mmap2_filter f env1 l1 l2 in + ((match opt_hd with Some hd -> hd :: tl | None -> tl), env2) + | _, _ -> + invalid_arg "mmap2_filter" (* To detect redefinitions within the same scope *) @@ -1034,11 +1035,15 @@ and elab_field_group env = function if is_qualified_array ty then error loc "type qualifier used in array declarator outside of function prototype"; let anon_composite = is_anonymous_composite ty in - if id = "" && not anon_composite && optbitsize = None then + if id = "" && not anon_composite && optbitsize = None then begin warning loc Missing_declarations "declaration does not declare anything"; - { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize'; fld_anonymous = id = "" && anon_composite},env' + None, env' + end else + Some { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize'; + fld_anonymous = id = "" && anon_composite}, + env' in - (mmap2 elab_bitfield env' fieldlist names) + (mmap2_filter elab_bitfield env' fieldlist names) | Field_group_static_assert(exp, loc_exp, msg, loc_msg, loc) -> elab_static_assert env exp loc_exp msg loc_msg loc; -- cgit From 6ede270e6f386a099bc898307168e75ebd819c7e Mon Sep 17 00:00:00 2001 From: Bernhard Schommer Date: Tue, 21 Sep 2021 16:30:19 +0200 Subject: Ignore unnamed bit fields for initialization of unions When a union is initialized with an initializer without designator the first named member should be initialized. This commit skips members without names during the elaboration of union initializers. Note that anonymous members (unnamed members of struct or union type) should not be skipped, and are not skipped since elaboration give names to these members. Bug 31982 --- cparser/Cutil.ml | 13 +++++++++---- cparser/Elab.ml | 10 +++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'cparser') diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml index d3a830ce..bcdea107 100644 --- a/cparser/Cutil.ml +++ b/cparser/Cutil.ml @@ -1263,11 +1263,16 @@ let rec default_init env ty = let ci = Env.find_struct env id in Init_struct(id, default_init_fields ci.ci_members) | TUnion(id, _) -> - let ci = Env.find_union env id in - begin match ci.ci_members with + let ci = Env.find_union env id in + let rec default_init_field = function | [] -> raise No_default_init - | fld :: _ -> Init_union(id, fld, default_init env fld.fld_typ) - end + | fld :: fl -> + if fld.fld_name = "" then + default_init_field fl + else + Init_union(id, fld, default_init env fld.fld_typ) + in + default_init_field ci.ci_members | _ -> raise No_default_init diff --git a/cparser/Elab.ml b/cparser/Elab.ml index a78dc9d9..c2c7f943 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -1402,14 +1402,18 @@ module I = struct | TStruct(id, _), Init_struct(id', (fld1, i1) :: flds) -> OK(Zstruct(z, id, [], fld1, flds), i1) | TUnion(id, _), Init_union(id', fld, i) -> - begin match (Env.find_union env id).Env.ci_members with + let rec first_named = function | [] -> NotFound - | fld1 :: _ -> + | fld1 :: fl -> + if fld1.fld_name = "" then + first_named fl + else begin OK(Zunion(z, id, fld1), if fld.fld_name = fld1.fld_name then i else default_init env fld1.fld_typ) - end + end in + first_named (Env.find_union env id).Env.ci_members | (TStruct _ | TUnion _), Init_single a -> (* This is a previous whole-struct initialization that we are going to overwrite. Hard to support correctly -- cgit