From a14c61e8f2f41c74df1e2c8666119e60a8188cc9 Mon Sep 17 00:00:00 2001 From: Allan Blanchard <allan.blanchard@cea.fr> Date: Tue, 5 Jan 2021 10:01:51 +0100 Subject: [PATCH] [kernel] Robustify some fields treatments --- src/kernel_internals/typing/cabs2cil.ml | 13 ++-- src/kernel_internals/typing/mergecil.ml | 82 ++++++++++--------------- 2 files changed, 39 insertions(+), 56 deletions(-) diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index b91f906f540..711d6633ecf 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -3744,7 +3744,7 @@ let find_field_offset cond (fidlist: fieldinfo list) : offset = | fid :: rest when prefix anonCompFieldName fid.fname -> begin match unrollType fid.ftype with | TComp (ci, _, _) -> - (try let off = search (Extlib.the ci.cfields) in Field(fid,off) + (try let off = search (Extlib.opt_conv [] ci.cfields) in Field(fid,off) with Not_found -> search rest (* Continue searching *)) | _ -> abort_context "unnamed field type is not a struct/union" @@ -3755,7 +3755,7 @@ let find_field_offset cond (fidlist: fieldinfo list) : offset = let findField n comp = try - find_field_offset (fun x -> x.fname = n) (Extlib.the comp.cfields) + find_field_offset (fun x -> x.fname = n) (Extlib.opt_conv [] comp.cfields) with Not_found -> abort_context "Cannot find field %s in type %s" n (Cil.compFullName comp) @@ -5549,16 +5549,17 @@ and makeCompType ghost (isstruct: bool) "Empty %s is allowed only in GCC or MSVC mode" (if comp.cstruct then "struct" else "union"); List.iter check flds; - if comp.cfields <> Some [] && comp.cfields <> None then begin + if comp.cfields <> None then begin + let old_fields = Extlib.the comp.cfields in (* This appears to be a multiply defined structure. This can happen from * a construct like "typedef struct foo { ... } A, B;". This is dangerous * because at the time B is processed some forward references in { ... } * appear as backward references, which could lead to circularity in * the type structure. We do a thorough check and then we reuse the type * for A *) - if List.length (Extlib.opt_conv [] comp.cfields) <> List.length flds + if List.length old_fields <> List.length flds || (List.exists2 (fun f1 f2 -> not (Cil_datatype.Typ.equal f1.ftype f2.ftype)) - (Extlib.opt_conv [] comp.cfields) flds) + old_fields flds) then Kernel.error ~once:true ~current:true "%s seems to be multiply defined" (compFullName comp) @@ -8327,7 +8328,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl = [(A.NEXT_INIT, A.SINGLE_INIT oneinit)] else (* If this is a GNU extension with field-to-union cast find the field *) - let fi = findField (Extlib.the ci.cfields) in + let fi = findField (Extlib.opt_conv [] ci.cfields) in (* Change the designator and redo *) doInit local_env asconst add_implicit_ensures preinit so acc diff --git a/src/kernel_internals/typing/mergecil.ml b/src/kernel_internals/typing/mergecil.ml index 2dc0f65e999..ead5136f1f6 100644 --- a/src/kernel_internals/typing/mergecil.ml +++ b/src/kernel_internals/typing/mergecil.ml @@ -2164,64 +2164,46 @@ class renameVisitorClass = }) | _ -> DoChildren + method private update_field f = + (* See if the compinfo was changed *) + if f.fcomp.creferenced then None + else begin + match + PlainMerging.findReplacement true sEq !currentFidx f.fcomp.cname + with + None -> None (* We did not replace it *) + | Some (ci', _oldfidx) -> begin + (* First, find out the index of the original field *) + let rec indexOf (i: int) = function + | [] -> Kernel.fatal "Cannot find field %s in %s" + f.fname (compFullName f.fcomp) + | f' :: _ when f' == f -> i + | _ :: rest -> indexOf (i + 1) rest + in + let index = indexOf 0 (Extlib.opt_conv [] f.fcomp.cfields) in + let ci'_fields = Extlib.opt_conv [] ci'.cfields in + if List.length ci'_fields <= index then + Kernel.fatal "Too few fields in replacement %s for %s" + (compFullName ci') + (compFullName f.fcomp); + Some (List.nth ci'_fields index) + end + end + (* The Field offset might need to be changed to use new compinfo *) method! voffs = function Field (f, o) -> begin - (* See if the compinfo was changed *) - if f.fcomp.creferenced then - DoChildren - else begin - match - PlainMerging.findReplacement true sEq !currentFidx f.fcomp.cname - with - None -> DoChildren (* We did not replace it *) - | Some (ci', _oldfidx) -> begin - (* First, find out the index of the original field *) - let rec indexOf (i: int) = function - [] -> Kernel.fatal "Cannot find field %s in %s" - f.fname (compFullName f.fcomp) - | f' :: _ when f' == f -> i - | _ :: rest -> indexOf (i + 1) rest - in - let index = indexOf 0 (Extlib.the f.fcomp.cfields) in - if List.length (Extlib.the ci'.cfields) <= index then - Kernel.fatal "Too few fields in replacement %s for %s" - (compFullName ci') - (compFullName f.fcomp); - let f' = List.nth (Extlib.the ci'.cfields) index in - ChangeDoChildrenPost (Field (f', o), fun x -> x) - end - end + match self#update_field f with + | None -> DoChildren + | Some f' -> ChangeDoChildrenPost (Field (f', o), fun x -> x) end | _ -> DoChildren method! vterm_offset = function TField (f, o) -> begin - (* See if the compinfo was changed *) - if f.fcomp.creferenced then - DoChildren - else begin - match - PlainMerging.findReplacement true sEq !currentFidx f.fcomp.cname - with - None -> DoChildren (* We did not replace it *) - | Some (ci', _oldfidx) -> begin - (* First, find out the index of the original field *) - let rec indexOf (i: int) = function - [] -> Kernel.fatal "Cannot find field %s in %s" - f.fname (compFullName f.fcomp) - | f' :: _ when f' == f -> i - | _ :: rest -> indexOf (i + 1) rest - in - let index = indexOf 0 (Extlib.the f.fcomp.cfields) in - if List.length (Extlib.the ci'.cfields) <= index then - Kernel.fatal "Too few fields in replacement %s for %s" - (compFullName ci') - (compFullName f.fcomp); - let f' = List.nth (Extlib.the ci'.cfields) index in - ChangeDoChildrenPost (TField (f', o), fun x -> x) - end - end + match self#update_field f with + | None -> DoChildren + | Some f' -> ChangeDoChildrenPost (TField (f', o), fun x -> x) end | TModel(f,o) -> (match -- GitLab