package frama-c
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Platform dedicated to the analysis of source code written in C
Install
dune-project
Dependency
Authors
-
MMichele Alberti
-
TThibaud Antignac
-
GGergö Barany
-
PPatrick Baudin
-
NNicolas Bellec
-
TThibaut Benjamin
-
AAllan Blanchard
-
LLionel Blatter
-
FFrançois Bobot
-
RRichard Bonichon
-
VVincent Botbol
-
QQuentin Bouillaguet
-
DDavid Bühler
-
ZZakaria Chihani
-
SSylvain Chiron
-
LLoïc Correnson
-
JJulien Crétin
-
PPascal Cuoq
-
ZZaynah Dargaye
-
BBasile Desloges
-
JJean-Christophe Filliâtre
-
PPhilippe Herrmann
-
JJordan Ischard
-
MMaxime Jacquemin
-
BBenjamin Jorge
-
FFlorent Kirchner
-
AAlexander Kogtenkov
-
RRemi Lazarini
-
TTristan Le Gall
-
KKilyan Le Gallic
-
JJean-Christophe Léchenet
-
MMatthieu Lemerre
-
DDara Ly
-
DDavid Maison
-
CClaude Marché
-
AAndré Maroneze
-
TThibault Martin
-
FFonenantsoa Maurica
-
MMelody Méaulle
-
BBenjamin Monate
-
NNicky Mouha
-
YYannick Moy
-
PPierre Nigron
-
AAnne Pacalet
-
VValentin Perrelle
-
GGuillaume Petiot
-
DDario Pinto
-
VVirgile Prevosto
-
AArmand Puccetti
-
FFélix Ridoux
-
VVirgile Robles
-
JJan Rochel
-
MMuriel Roger
-
CCécile Ruet-Cros
-
JJulien Signoles
-
FFabien Siron
-
NNicolas Stouls
-
HHugo Thievenaz
-
KKostyantyn Vorobyov
-
BBoris Yakobowski
Maintainers
Sources
frama-c-33.0-Arsenic.tar.gz
sha256=9c1cbffd28bb33c17a668107e39c96e4ae7378a3d8249f69b47afc7ee964e9b8
doc/src/frama-c-region.core/spec.ml.html
Source file spec.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251(**************************************************************************) (* *) (* SPDX-License-Identifier LGPL-2.1 *) (* Copyright (C) *) (* CEA (Commissariat à l'énergie atomique et aux énergies alternatives) *) (* *) (**************************************************************************) open Logic_ptree open Cil_types open Cil_datatype (* -------------------------------------------------------------------------- *) (* --- Region Specifications --- *) (* -------------------------------------------------------------------------- *) type path = | Alias of location * term_lval | Field of location * term_lval * fieldinfo * fieldinfo | Range of location * term * typ * term * term type region = { named : string ; paths : path list ; flags : Attr.flags ; } (* -------------------------------------------------------------------------- *) (* --- Printers --- *) (* -------------------------------------------------------------------------- *) let pp_named fmt a = if a <> "" then Format.fprintf fmt "%s: " a let pp_path fmt = function | Alias(_,lv) -> Printer.pp_term_lval fmt lv | Field(_,lv,f,g) -> let field lv f = Logic_const.addTermOffsetLval (TField(f,TNoOffset)) lv in Format.fprintf fmt "%a..%a" Printer.pp_term_lval (field lv f) Printer.pp_term_lval (field lv g) | Range(_,p,_,a,b) -> Format.fprintf fmt "%a[%a..%a]" Printer.pp_term p Printer.pp_term a Printer.pp_term b let pp_region fmt r = match r.paths with | [] -> Format.pp_print_string fmt "" | p::ps -> begin Format.fprintf fmt "@[<hov 2>" ; pp_named fmt r.named ; pp_path fmt p ; List.iter (Format.fprintf fmt ",@ %a" pp_path) ps ; Attr.iter (Format.fprintf fmt ",@ \\%a" Attr.pp_attr) r.flags ; Format.fprintf fmt "@]" ; end let pp_regions fmt = function | [] -> Format.pp_print_string fmt "" | r::rs -> begin Format.fprintf fmt "@[<hv 0>" ; pp_region fmt r ; List.iter (Format.fprintf fmt ",@ %a" pp_region) rs ; Format.fprintf fmt "@]" ; end (* -------------------------------------------------------------------------- *) (* --- Parsing Environment --- *) (* -------------------------------------------------------------------------- *) type env = { context: Logic_typing.typing_context ; mutable esource: Filepos.t ; mutable enamed: string ; mutable eflags: Attr.flags ; mutable rpaths: path list ; mutable regions: region list ; } let error (env:env) ~loc msg = env.context.error loc msg (* -------------------------------------------------------------------------- *) (* --- Syntactic Filter --- *) (* -------------------------------------------------------------------------- *) let lrange env (e: lexpr) = match e.lexpr_node with | PLrange(None,None) -> () | _ -> error env ~loc:e.lexpr_loc "Range [..] expected" let rec lpath env (e: lexpr) = let loc = e.lexpr_loc in match e.lexpr_node with | PLvar _ -> () | PLdot( p , _ ) | PLarrow( p , _ ) | PLunop( Ustar , p ) | PLunop( Uamp , p ) -> lpath env p | PLbinop( p , Badd , rg ) | PLarrget(p,rg) -> lpath env p ; lrange env rg | PLcast( _ , p ) -> lpath env p | _ -> error env ~loc "Unexpected l-value for region spec" (* -------------------------------------------------------------------------- *) (* --- Parsers --- *) (* -------------------------------------------------------------------------- *) let parse_term env t = let open Logic_typing in let g = env.context in g.type_term g g.pre_state t let parse_lval env p = let t = parse_term env p in match t.term_node with | TLval lv -> lv | _ -> error env ~loc:p.lexpr_loc "Expected l-value for region path" let parse_integer env p = let v = parse_term env p in if not @@ Ast_types.is_logic_integral v.term_type then error env ~loc:p.lexpr_loc "Expected integer term for object bounds" ; v let parse_pointer env p = let loc = p.lexpr_loc in let a = parse_term env p in let te = match Ast_types.unroll_logic a.term_type with | Ctype { tnode = TPtr te } -> te | _ -> error env ~loc "Expected pointer l-value for region object" in te,a let rec last_field = function | TNoOffset | TModel _ -> raise Not_found | TField(fd,TNoOffset) -> TNoOffset, fd | TField(f0,ofs) -> let ofs,fd = last_field ofs in TField(f0,ofs), fd | TIndex(k0,ofs) -> let ofs,fd = last_field ofs in TIndex(k0,ofs), fd let parse_field env p = try let h,ofs = parse_lval env p in let ofs,fd = last_field ofs in if not fd.fcomp.cstruct then error env ~loc:p.lexpr_loc "Expected struct field for range path" ; (h,ofs),fd with Not_found -> error env ~loc:p.lexpr_loc "Expected field l-value for range path" let garbage = Attr.(add `Garbage empty) let applies flags = function | Range _ -> true | Alias(_,(TVar { lv_origin = Some v },_)) -> flags = garbage && v.vformal && Ast_types.is_struct_or_union v.vtype | Alias _ | Field _ -> false let flush source env = if env.eflags <> Attr.empty && not @@ List.exists (applies env.eflags) env.rpaths then Options.warning ~source:env.esource "%a has no object to apply on" Attr.pretty env.eflags ; if env.rpaths <> [] then begin env.regions <- { named = env.enamed ; flags = env.eflags ; paths = List.rev env.rpaths ; } :: env.regions ; env.esource <- source ; env.rpaths <- [] ; env.eflags <- Attr.empty ; end let rec parse_region (env:env) p = match p.lexpr_node with | PLvar "\\nullable" -> env.eflags <- Attr.add `Nullable env.eflags | PLvar "\\allocated" -> env.eflags <- Attr.add `Allocated env.eflags | PLvar "\\garbage" -> env.eflags <- Attr.add `Garbage env.eflags | PLvar "\\readonly" -> env.eflags <- Attr.add `Readonly env.eflags | PLnamed( name , p ) -> flush (fst p.lexpr_loc) env ; env.enamed <- name ; parse_region env p | PLrange(Some a,Some b) -> let l1,f = parse_field env a in let l2,g = parse_field env b in if not (Term_lval.equal l1 l2) then error env ~loc:p.lexpr_loc "Field range from different region paths" ; env.rpaths <- Field(p.lexpr_loc,l1,f,g) :: env.rpaths | PLarrget(p,{ lexpr_node = PLrange(Some a,Some b) }) -> let te,q = parse_pointer env p in let a = parse_integer env a in let b = parse_integer env b in env.rpaths <- Range(p.lexpr_loc,q,te,a,b) :: env.rpaths | PLunop(Ustar,p) -> let te,q = parse_pointer env p in let zero = Logic_const.tinteger ~loc:p.lexpr_loc 0 in env.rpaths <- Range(p.lexpr_loc,q,te,zero,zero) :: env.rpaths | _ -> let lv = lpath env p ; parse_lval env p in env.rpaths <- Alias(p.lexpr_loc,lv) :: env.rpaths (* -------------------------------------------------------------------------- *) (* --- Spec Typechecking & Printing --- *) (* -------------------------------------------------------------------------- *) let kspec = ref 0 let registry = Hashtbl.create 0 let of_extid id = try Hashtbl.find registry id with Not_found -> [] let of_extension = function | { ext_name="region" ; ext_kind = Ext_id k } -> of_extid k | _ -> [] let of_code_annot = function | { annot_content = AExtended(_,_,e) } -> of_extension e | _ -> [] let of_behavior bhv = List.concat_map of_extension bhv.b_extended let typecheck typing_context loc ps = let env = { esource = fst loc ; enamed = "" ; eflags = Attr.empty ; context = typing_context ; rpaths = [] ; regions = [] ; } in List.iter (parse_region env) ps ; let id = !kspec in incr kspec ; flush (fst loc) env ; Hashtbl.add registry id @@ List.rev env.regions ; Ext_id id let printer _pp fmt = function | Ext_id k -> let rs = try Hashtbl.find registry k with Not_found -> [] in pp_regions fmt rs | _ -> () let () = begin Acsl_extension.register_behavior ~plugin:"region" "region" typecheck ~printer false ; Acsl_extension.register_code_annot ~plugin:"region" "alias" typecheck ~printer false ; end (* -------------------------------------------------------------------------- *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>