From 6c71eee16ed2814039d0e959ba9190a2d855469e Mon Sep 17 00:00:00 2001 From: Pierre Nigron <pierre.nigron@cea.fr> Date: Fri, 25 Aug 2023 10:05:35 +0200 Subject: [PATCH] [kernel] Refactoring cabs2cil --- src/kernel_internals/typing/cabs2cil.ml | 118 +++++++++++++----------- src/kernel_services/ast_queries/cil.ml | 14 ++- src/kernel_services/ast_queries/cil.mli | 11 ++- 3 files changed, 84 insertions(+), 59 deletions(-) diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index 0f97b8993b2..682cbb32b78 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -658,11 +658,11 @@ let process_pragmas_pack_align_field_attributes fi fattrs cattr = if Cil.hasAttribute "packed" cattr then (dropAttribute "aligned" fattrs) else begin let sizeof_type = - match Cil.unrollType fi.ftype with - | TArray (_, None, _) -> + if Cil.isUnsizedArrayType fi.ftype + then (* flexible array member: use size of pointer *) Cil.bitsSizeOf theMachine.upointType - | _ -> + else Cil.bytesSizeOf fi.ftype in let align = Integer.(min n (of_int sizeof_type)) in @@ -3305,25 +3305,30 @@ let rec collectInitializer in let newtype = (* detect flexible array member initialization *) - match thistype, Cil.unrollType parenttype with - | TArray (_, None, _), TComp (comp, _) - when comp.cstruct && len > 0 -> - (* incomplete array type inside a struct => FAM, with - a non-empty initializer (len > 0) - *) - Kernel.debug ~dkey - "Detected initialization of a flexible array member \ - (length %d, parenttype %a)" len Cil_datatype.Typ.pretty parenttype; - Kernel.error ~once:true ~current:true - "static initialization of flexible array members is an \ - unsupported GNU extension"; - TArray (typ, None, at) - | _ -> (* not a flexible array member *) - if len = 0 && not (Cil.gccMode() || Cil.msvcMode ()) then + if Cil.isUnsizedArrayType thistype && + Cil.isStructType parenttype && + len > 0 + then + begin + (* incomplete array type inside a struct => FAM, with + a non-empty initializer (len > 0) *) + Kernel.debug ~dkey + "Detected initialization of a flexible array member \ + (length %d, parenttype %a)" len Cil_datatype.Typ.pretty parenttype; Kernel.error ~once:true ~current:true - "arrays of size zero not supported in C99@ \ - (only allowed as compiler extensions)"; - TArray (typ, Some (integer ~loc len), at) + "static initialization of flexible array members is an \ + unsupported GNU extension"; + TArray (typ, None, at) + end + else + begin + (* not a flexible array member *) + if len = 0 && not (Cil.gccMode() || Cil.msvcMode ()) then + Kernel.error ~once:true ~current:true + "arrays of size zero not supported in C99@ \ + (only allowed as compiler extensions)"; + TArray (typ, Some (integer ~loc len), at) + end in CompoundInit (newtype, (* collect [] endAt*)init), (* If the sizes of the initializers have not been used anywhere, @@ -5287,19 +5292,17 @@ and makeCompType ghost (isstruct: bool) end else if not (Cil.isCompleteType ~allowZeroSizeArrays ftype) then begin - match Cil.unrollType ftype with - | TArray(_,None,_) when last_group && last_field -> - begin - (* possible flexible array member; check if struct contains at least + if Cil.isUnsizedArrayType ftype && last_group && last_field + then + (* possible flexible array member; check if struct contains at least one other field *) - if flds = [] then (* struct is empty *) - Kernel.error ~source - "flexible array member '%s' (type %a) \ - not allowed in otherwise empty struct" - n Cil_datatype.Typ.pretty ftype - else (* valid flexible array member *) () - end - | _ -> + if flds = [] then (* struct is empty *) + Kernel.error ~source + "flexible array member '%s' (type %a) \ + not allowed in otherwise empty struct" + n Cil_datatype.Typ.pretty ftype + else (* valid flexible array member *) () + else Kernel.error ~source "field `%s' is declared with incomplete type %a" n Cil_datatype.Typ.pretty ftype @@ -5349,21 +5352,23 @@ and makeCompType ghost (isstruct: bool) (* If the field is unnamed and its type is a structure of union type * then give it a distinguished name *) let fname = - if n = missingFieldName then begin - match unrollType ftype with - | TComp _ -> begin + if n = missingFieldName then + if isStructOrUnionType ftype then + begin Kernel.warning ~wkey:Kernel.wkey_c11 ~once:true ~current:true "unnamed fields are a C11 extension"; incr anonCompFieldNameId; anonCompFieldName ^ (string_of_int !anonCompFieldNameId) end - | _ -> n - end else begin - if fbitfield = Some 0 then - Kernel.error ~source:(fst cloc) - "named bitfield (%s) with zero width" n; - n - end + else + n + else + begin + if fbitfield = Some 0 then + Kernel.error ~source:(fst cloc) + "named bitfield (%s) with zero width" n; + n + end in let rec is_circular t = match Cil.unrollType t with @@ -9039,19 +9044,20 @@ and createLocal ghost ((_, sto, _, _) as specs) let se4, ie', et, r = doInitializer (ghost_local_env ghost) vi inite in let se4 = cleanup_autoreference vi se4 in (* Fix the length *) - (match vi.vtype, ie', et with - (* We have a length now *) - | TArray(_,None, _), _, TArray(_, Some _, _) -> - Cil.update_var_type vi et - (* Initializing a local array *) - | TArray(TInt((IChar|IUChar|ISChar), _) as bt, None, a), - SingleInit({enode = Const(CStr s);eloc=loc}), _ -> - Cil.update_var_type vi - (TArray(bt, - Some (integer ~loc (String.length s + 1)), - a)) - | _, _, _ -> ()); - + if Cil.isUnsizedArrayType vi.vtype && Cil.isSizedArrayType et + then + (* We have a length now *) + Cil.update_var_type vi et + else + (match vi.vtype, ie', et with + (* Initializing a local array *) + | TArray(TInt((IChar|IUChar|ISChar), _) as bt, None, a), + SingleInit({enode = Const(CStr s);eloc=loc}), _ -> + Cil.update_var_type vi + (TArray(bt, + Some (integer ~loc (String.length s + 1)), + a)) + | _, _, _ -> ()); (* Now create assignments instead of the initialization *) (se1 @@@ (se4, ghost)) @@@ diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index 2cdff0fe8dc..00322c52341 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -5791,6 +5791,10 @@ let isUnsizedArrayType t = match unrollTypeSkel t with | TArray (_, None, _) -> true | _ -> false +let isSizedArrayType t = match unrollTypeSkel t with + | TArray (_, Some _, _) -> true + | _ -> false + let isAnyCharArrayType t = match unrollTypeSkel t with | TArray(tau,_,_) when isAnyCharType tau -> true | _ -> false @@ -5799,10 +5803,16 @@ let isCharArrayType t = match unrollTypeSkel t with | TArray(tau,_,_) when isCharType tau -> true | _ -> false -let isStructOrUnionType t = match unrollTypeSkel t with - | TComp _ -> true +let isStructType t = match unrollTypeSkel t with + | TComp (comp, _) -> comp.cstruct | _ -> false +let isUnionType t = match unrollTypeSkel t with + | TComp (comp, _) -> not comp.cstruct + | _ -> false + +let isStructOrUnionType t = isStructType t || isUnionType t + let isVariadicListType t = match unrollTypeSkel t with | TBuiltin_va_list _ -> true | _ -> false diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli index feb0fa4c8bc..9f1c971c1a2 100644 --- a/src/kernel_services/ast_queries/cil.mli +++ b/src/kernel_services/ast_queries/cil.mli @@ -611,7 +611,16 @@ val isArrayType: typ -> bool (** True if the argument is an unsized array type *) val isUnsizedArrayType: typ -> bool -(** True if the argument is a struct of union type *) +(** True if the argument is a sized array type *) +val isSizedArrayType: typ -> bool + +(** True if the argument is a struct *) +val isStructType: typ -> bool + +(** True if the argument is a union type *) +val isUnionType: typ -> bool + +(** True if the argument is a struct or union type *) val isStructOrUnionType: typ -> bool (** possible causes for raising {!Cil.LenOfArray} *) -- GitLab