Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file l_loop.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178(**************************************************************************)(* *)(* This file is part of the Frama-C's Lannotate plug-in. *)(* *)(* Copyright (C) 2012-2022 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file LICENSE) *)(* *)(**************************************************************************)openCil_typesopenAst_const(** Return True if the stmt list only contain 1 statement which is a Break *)letis_break_onlybstmts=List.lengthbstmts=1&&match(List.hdbstmts).skindwith|Break_->true|_->false(** Add a label in each loop, to see if we enter in it *)letinnermk_label=object(_)inheritVisitor.frama_c_inplace(** Pile qui stock le status des boucles *)valinLoopId=Stack.create()method!vfuncdec=ifAnnotators.shouldInstrumentFundec.svarthenCil.DoChildrenelseCil.SkipChildrenmethod!vstmt_auxstmt=matchstmt.skindwith|Loop(_,_,l,_,_)->letlabel=mk_label(Exp_builder.one())[]linCil.DoChildrenPost(funstmt->beginmatchstmt.skindwith|Loop(_,b,_,_,_)->letfound=reffalsein(* Cf. doc/loops.markdown for more info *)letlen=List.lengthb.bstmtsinletfids=matchs.skindwith|If(e,th,el,l)->(* If not found already && then is empty && else contains only break &&
(isn't the last stmt in the body, or we don't want to handle do..while..) *)ifnot!found&&th.bstmts=[]&&is_break_onlyel.bstmts&&(id+1<>len||not(Options.HandleDoWhile.get()))thenbegins.skind<-(If(e,{thwithbstmts=[label]},el,l));found:=trueend;s|_->sinletnb=List.mapifb.bstmtsinif!foundthenb.bstmts<-nbelseb.bstmts<-label::b.bstmts;stmt|_->assertfalseend)|_->Cil.DoChildrenend(** Add a label in each loop, to see if we enter in it *)letouttermk_label=object(self)inheritVisitor.frama_c_inplace(** Pile qui stock le status des boucles *)valinLoopId=Stack.create()methodprivatemk_comp?(loc=Cil_datatype.Location.unknown)vivalue=letnew_exp=Exp_builder.mk~loc(Lval(Varvi,NoOffset))inExp_builder.binopEqnew_expvaluemethodprivatemkSeqloc=letid_seq=Annotators.getCurrentLabelId()+1in(* sequence id *)letvInfo=Cil.makeVarinfofalsefalse("__SEQ_STATUS_"^string_of_intid_seq)Cil.intTypeinletuse=self#mk_compvInfo(Exp_builder.one())inletlbl_use=mk_labeluse[]locinletdef=Local_init(vInfo,AssignInit(SingleInit(Exp_builder.one())),loc)|>Stmt_builder.instrinletcond=Ast_info.mkassign(VarvInfo,NoOffset)(Exp_builder.zero())loc|>Stmt_builder.instrindef,lbl_use,condmethod!vfuncdec=ifAnnotators.shouldInstrumentFundec.svarthenCil.DoChildrenelseCil.SkipChildrenmethod!vstmt_auxstmt=matchstmt.skindwith|Loop_->letdef,use,cond=self#mkSeq(Cil_datatype.Stmt.locstmt)inCil.DoChildrenPost(funstmt->letnewLoop=matchstmt.skindwith|Loop(_,b,_,_,_)->letfound=reffalsein(* Cf. doc/loops.markdown for more info *)letlen=List.lengthb.bstmtsinletfids=matchs.skindwith|If(e,th,el,l)->(* If not found already && then is empty && else contains only break &&
(isn't the last stmt in the body, or we don't want to handle do..while..) *)ifnot!found&&th.bstmts=[]&&is_break_onlyel.bstmts&&(id+1<>len||not(Options.HandleDoWhile.get()))thenbegins.skind<-(If(e,{thwithbstmts=[cond]},el,l));found:=trueend;s|_->sinletnb=List.mapifb.bstmtsinif!foundthenb.bstmts<-nbelseb.bstmts<-cond::b.bstmts;stmt|_->assertfalseinStmt_builder.block[def;newLoop;use])|_->Cil.DoChildrenendletwarning()=ifOptions.HandleDoWhile.get()thenOptions.warning"Handle Do While enabled : Empty loops will be considered as Do..While"elseOptions.warning"Handle Do While disabled : Do..While will be considered as Empty loops";includeAnnotators.Register(structletname="ELO"lethelp="Enter in Loop at least once Coverage"letapplymk_labelast=warning();Visitor.visitFramacFileSameGlobals(innermk_label)astend)includeAnnotators.Register(structletname="SLO"lethelp="Skip Loop at least Once Coverage"letapplymk_labelast=warning();Visitor.visitFramacFileSameGlobals(outtermk_label)astend)