diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index 23e9a64223935754b638f38147a59a69cf90bf1c..79da27bd41da6e97700185a0d1cf6801b9f1c812 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -265,6 +265,25 @@ let mkBlock (slst: stmt list) : block = let mkBlockNonScoping l = let b = mkBlock l in b.bscoping <- false; b +let rec enforceGhostStmtCoherence ?(force_ghost=false) stmt = + let force_ghost = force_ghost || stmt.ghost in + stmt.ghost <- force_ghost ; + begin match stmt.skind with + | Break(_) | Continue(_) | Goto(_) | Throw(_) + | Instr(_) | Return(_) -> () + | UnspecifiedSequence(_) -> () + | If(_, b1, b2, _) | TryFinally(b1, b2, _) | TryExcept(b1, _, b2, _) -> + enforceGhostBlockCoherence ~force_ghost b1 ; + enforceGhostBlockCoherence ~force_ghost b2 + | Switch(_, b, _, _) | Loop(_, b, _, _, _) | Block(b) -> + enforceGhostBlockCoherence ~force_ghost b + | TryCatch(b, l, _) -> + enforceGhostBlockCoherence ~force_ghost b ; + List.iter (fun (_, b) -> enforceGhostBlockCoherence ~force_ghost b) l + end +and enforceGhostBlockCoherence ?force_ghost block = + List.iter (enforceGhostStmtCoherence ?force_ghost) block.bstmts + let mkStmt ?(ghost=false) ?(valid_sid=false) ?(sattr=[]) (sk: stmtkind) : stmt = { skind = sk; labels = []; @@ -3359,6 +3378,7 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp = let res = doVisitCil vis vis#behavior.memo_stmt vis#vstmt (childrenStmt toPrepend) s in + let ghost = res.ghost in (* Now see if we have saved some instructions *) toPrepend := !toPrepend @ vis#unqueueInstr (); (match !toPrepend with @@ -3366,8 +3386,8 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp = | _ -> let b = mkBlockNonScoping - ((List.map (fun i -> mkStmt (Instr i)) !toPrepend) - @ [mkStmt res.skind]) + ((List.map (fun i -> mkStmt ~ghost (Instr i)) !toPrepend) + @ [mkStmt ~ghost res.skind]) in b.battrs <- addAttribute (Attr (vis_tmp_attr, [])) b.battrs; (* Make our statement contain the instructions to prepend *) @@ -3494,6 +3514,7 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp = else s.skind in if skind' != s.skind then s.skind <- skind'; + enforceGhostStmtCoherence s ; (* Visit the labels *) let labels' = let fLabel = function @@ -6637,7 +6658,7 @@ let childrenFileSameGlobals vis f = in List.iter (fun s -> - match s.skind with + begin match s.skind with | Instr i -> s.skind <- stmt_of_instr_list (doInstrList [i]) | If (_e, tb, eb, _) -> peepHole1 doone tb.bstmts; @@ -6657,7 +6678,9 @@ let childrenFileSameGlobals vis f = peepHole1 doone b.bstmts; peepHole1 doone h.bstmts; s.skind <- TryExcept(b, (doInstrList il, e), h, l); - | Return _ | Goto _ | Break _ | Continue _ | Throw _ -> ()) + | Return _ | Goto _ | Break _ | Continue _ | Throw _ -> () + end ; + enforceGhostStmtCoherence s) ss (* Process two statements and possibly replace them both *) diff --git a/tests/cil/change_to_instr.i b/tests/cil/change_to_instr.i new file mode 100644 index 0000000000000000000000000000000000000000..b83b32608f67b7918cae94834696592bc19cf770 --- /dev/null +++ b/tests/cil/change_to_instr.i @@ -0,0 +1,17 @@ +/* run.config +OPT: -load-script tests/cil/change_to_instr.ml -print +*/ + + +int main(){ + int i = 0 ; + //@ ghost int j = 0 ; + + i++ ; + //@ ghost j++ ; + + { + //@ ghost int x = 0; + //@ ghost x++ ; + } +} diff --git a/tests/cil/change_to_instr.ml b/tests/cil/change_to_instr.ml new file mode 100644 index 0000000000000000000000000000000000000000..04d2679952d844a376299eb5e32449b829314e9a --- /dev/null +++ b/tests/cil/change_to_instr.ml @@ -0,0 +1,17 @@ +class add_skip = object(_) + inherit Visitor.frama_c_inplace + + method! vfunc f = + File.must_recompute_cfg f ; + Cil.DoChildren + + method! vinst i = + let open Cil_types in + Cil.ChangeTo [ Skip(Cil.CurrentLoc.get()) ; i ] +end + +let run () = + Visitor.visitFramacFileSameGlobals (new add_skip) (Ast.get()) + +let () = + Db.Main.extend run diff --git a/tests/cil/oracle/change_to_instr.res.oracle b/tests/cil/oracle/change_to_instr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..590858bb9f0d672e6dd54e6ecdeb12302be7ea8c --- /dev/null +++ b/tests/cil/oracle/change_to_instr.res.oracle @@ -0,0 +1,25 @@ +[kernel] Parsing tests/cil/change_to_instr.i (no preprocessing) +/* Generated by Frama-C */ +int main(void) +{ + int __retres; + ; + int i = 0; + /*@ ghost ; */ + /*@ ghost int j = 0; */ + ; + i ++; + /*@ ghost ; */ + /*@ ghost j ++; */ + { + /*@ ghost ; */ + /*@ ghost int x = 0; */ + /*@ ghost ; */ + /*@ ghost x ++; */ + } + ; + __retres = 0; + return __retres; +} + + diff --git a/tests/cil/oracle/queue_ghost_instr.res.oracle b/tests/cil/oracle/queue_ghost_instr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1066baea30d7eb9f0fadc390dfbc4ef28084385d --- /dev/null +++ b/tests/cil/oracle/queue_ghost_instr.res.oracle @@ -0,0 +1,29 @@ +[kernel] Parsing tests/cil/queue_ghost_instr.i (no preprocessing) +/* Generated by Frama-C */ +int main(void) +{ + int __retres; + ; + int i = 0; + /*@ ghost ; */ + /*@ ghost int j = 0; */ + ; + i ++; + /*@ ghost ; */ + /*@ ghost j ++; */ + { + /*@ ghost ; */ + /*@ ghost int x = 0; */ + /*@ ghost ; */ + /*@ ghost x ++; */ + } + ; + if (i) ; + /*@ ghost ; */ + /*@ ghost if (j) ; */ + ; + __retres = 0; + return __retres; +} + + diff --git a/tests/cil/queue_ghost_instr.i b/tests/cil/queue_ghost_instr.i new file mode 100644 index 0000000000000000000000000000000000000000..3bae2b6f40b0ef3824806fb03117f9af8f5e9610 --- /dev/null +++ b/tests/cil/queue_ghost_instr.i @@ -0,0 +1,26 @@ +/* run.config +OPT: -load-script tests/cil/queue_ghost_instr.ml -print +*/ + + +int main(){ + int i = 0 ; + //@ ghost int j = 0 ; + + i++ ; + //@ ghost j++ ; + + { + //@ ghost int x = 0; + //@ ghost x++ ; + } + + if(i){ + ; + } + + /*@ ghost if(j){ + + } + */ +} diff --git a/tests/cil/queue_ghost_instr.ml b/tests/cil/queue_ghost_instr.ml new file mode 100644 index 0000000000000000000000000000000000000000..22fcc753adaeea44ff4733b3971b4b2d53f12bce --- /dev/null +++ b/tests/cil/queue_ghost_instr.ml @@ -0,0 +1,27 @@ +class add_skip = object(this) + inherit Visitor.frama_c_inplace + + method! vfunc f = + File.must_recompute_cfg f ; + Cil.DoChildren + + method! vstmt s = + let open Cil_types in + begin match s.skind with + | If(_) -> + this#queueInstr([Skip(Cil.CurrentLoc.get())]) + | _ -> () + end ; + Cil.DoChildren + + method! vinst _ = + let open Cil_types in + this#queueInstr([Skip(Cil.CurrentLoc.get())]) ; + Cil.DoChildren +end + +let run () = + Visitor.visitFramacFileSameGlobals (new add_skip) (Ast.get()) + +let () = + Db.Main.extend run