Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file instrument_binding.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287(**************************************************************************)(* *)(* This file is part of the Frama-C's Luncov plug-in. *)(* *)(* Copyright (C) 2012-2025 *)(* 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_typesopenInstrumentletget_bindingid=letvalue=getidinmatchvaluewith|Bindingbinfo->binfo|_->assertfalseletextractidbind_id=letbinds=get_bindingidinList.find(funb->b.bi_id=bind_id)bindsletget_locidbind=(extractidbind).bi_locletget_tagidbind=(extractidbind).bi_tagletget_bindsidbind=(extractidbind).bi_bindingsletget_kf_ididbind=(extractidbind).bi_kf_idletget_annotable_stmtidbind=(extractidbind).bi_annotableletget_predicateidbind=(extractidbind).bi_predicateletis_current_bindidbind=letbinds=get_bindingidinList.exists(funb->b.bi_id=bind)bindsletis_last_bindidbind=letbinds=get_bindingidinletlast=List.hd(List.revbinds)inlast.bi_id=bindletget_idsid=letbinds=get_bindingidinList.map(funb->b.bi_id)bindsletget_ids_stringid=letbinds=get_bindingidinletbinds=List.map(funb->"#"^string_of_intb.bi_id)bindsinString.concat"·"bindsletat=refReq(** Visitor that removes all but a binding pair (given its id),
add a single assertion whose validity implies the uncoverability of a binding,
and provides information to get a Property.t
*)classbinding_selectoridlbl_infobinding_infoprj=object(self)inheritVisitor.frama_c_copyprjvalmutableto_remove_part=[]valmutableto_remove=[]valmutableremoved=[]valmutableprevious=[]methodprivatefusion_blocksstmt=matchstmt.skindwith|Blockblast->letbstmts'=ref[]inletblocals'=ref[]inletbstatics'=ref[]inletfstmt'=matchstmt'.skindwith|Blockb'->bstmts':=b'.bstmts@!bstmts';blocals':=b'.blocals@!blocals';bstatics':=b'.bstatics@!bstatics';|_->assertfalseinList.iterfprevious;blast.bstmts<-!bstmts'@blast.bstmts;blast.blocals<-!blocals'@blast.blocals;blast.bstatics<-!bstatics'@blast.bstatics;|_->assertfalsemethodprivateclean_slocalsslocals=List.filter(funvi->not(List.exists(funstmt->matchstmt.skindwith|Blockb->Ast_info.is_block_localvib|_->assertfalse)removed))slocalsmethodprivateclean_labelsstmtl=List.filter(funstmt->if(List.exists(funsid->sid=stmt.sid)to_remove)then(removed<-stmt::removed;false)elsenot(List.exists(funsid->sid=stmt.sid)to_remove_part))stmtlmethod!vfunc_=Cil.DoChildrenPost(funf->f.slocals<-self#clean_slocalsf.slocals;File.must_recompute_cfgf;to_remove_part<-[];to_remove<-[];removed<-[];f)method!vblock_=Cil.DoChildrenPost(funb->b.bstmts<-self#clean_labelsb.bstmts;b)method!vstmt_auxstmt=matchis_stmt_by_sidstmt.sidwith|[]->Cil.DoChildren|[lblid']whenis_current_bindidlblid'->Cil.DoChildrenPost(funnew_stmt->ifnot(is_last_bindidlblid')thenbeginto_remove_part<-new_stmt.sid::to_remove;previous<-new_stmt::previous;endelsebeginself#fusion_blocksnew_stmt;previous<-[];self#add_annot();end;new_stmt)|_->to_remove<-stmt.sid::to_remove;Cil.JustCopymethodprivatemk_check_capred=lettop_pred=Logic_const.toplevel_predicate~kind:CheckpredinLogic_const.new_code_annotation(AAssert([],top_pred))methodprivateget_new_kf()=letold_kf=Option.getself#current_kfinVisitor_behavior.Get.kernel_functionself#behaviorold_kfmethodprivatemk_label_annotexp=letcond=Visitor.visitFramacExpr(self:>Visitor.frama_c_visitor)expinletcond=Logic_utils.expr_to_term~coerce:truecondinletassertion=Logic_const.prel(!at,cond,Cil.lzero())inself#mk_check_caassertionmethodprivatemk_ipcakfstmt=Annotations.add_code_annot~kfwp_emitterstmtca;Property.ip_of_code_annot_singlekfstmtcamethodprivatemk_bind_impbi_condvar_pred=letcond=Visitor.visitFramacExpr(self:>Visitor.frama_c_visitor)bi_condinletpred=Visitor.visitFramacExpr(self:>Visitor.frama_c_visitor)var_predinletcond=Logic_utils.expr_to_predicatecondinletpred=Logic_utils.expr_to_predicatepredinletimplies=Logic_const.pimplies(cond,pred)inletimplies_not=Logic_const.pimplies(cond,Logic_const.pnotpred)inimplies,implies_notmethodprivateadd_labels_annot()=letbinfos=get_bindingidinletnew_kf=self#get_new_kf()inletcas=List.map(funb->self#mk_label_annotb.bi_predicate)binfosinletqueued_action()=letips=List.map2(funcab->b.bi_id,self#mk_ipcanew_kfb.bi_annotable)casbinfosinlbl_info:=ipsinQueue.addqueued_actionself#get_filling_actionsmethodprivateadd_binding_CACC_annot()=letnew_kf=self#get_new_kf()inletbinfos=get_bindingidinmatchbinfoswith|[b1;b2]->ifList.lengthb1.bi_bindings=1&&List.lengthb2.bi_bindings=1thenbeginlet_,var_p_1=List.hdb1.bi_bindingsinlet_,var_p_2=List.hdb2.bi_bindingsinletimp_1,imp_not_1=self#mk_bind_impb1.bi_predicatevar_p_1inletimp_2,imp_not_2=self#mk_bind_impb2.bi_predicatevar_p_2inletimp=Logic_const.pand(imp_1,imp_2)inletimp_not=Logic_const.pand(imp_not_1,imp_not_2)inletca_imp=self#mk_check_caimpinletca_imp_not=self#mk_check_caimp_notinletqueued_action()=letip_1=self#mk_ipca_impnew_kfb2.bi_annotableinletip_2=self#mk_ipca_imp_notnew_kfb2.bi_annotableinbinding_info:=ip_1::ip_2::!binding_infoinQueue.addqueued_actionself#get_filling_actionsendelseOptions.warning"Skip binding annot for %s : Too many bindings [CACC]"(get_ids_stringb1.bi_id)|_->Options.warning"Skip binding annot : Wrong number of bindings [CACC]"methodprivateadd_binding_RACC_annot()=letnew_kf=self#get_new_kf()inletbinfos=get_bindingidinmatchbinfoswith|[b1;b2]->ifList.lengthb1.bi_bindings=List.lengthb2.bi_bindingsthenbeginletmake_ca(_,var1)(_,var2)=letimp_1,imp_not_1=self#mk_bind_impb1.bi_predicatevar1inletimp_2,imp_not_2=self#mk_bind_impb2.bi_predicatevar2inletimp_1=Logic_const.pand(imp_1,imp_not_2)inletimp_2=Logic_const.pand(imp_not_1,imp_2)inself#mk_check_caimp_1,self#mk_check_caimp_2inletall_ca=List.map2make_cab1.bi_bindingsb2.bi_bindingsinletqueued_action()=letcreate_ips(ca_imp_1,ca_imp_2)=letip_1=self#mk_ipca_imp_1new_kfb2.bi_annotableinletip_2=self#mk_ipca_imp_2new_kfb2.bi_annotableinbinding_info:=ip_1::ip_2::!binding_infoinList.itercreate_ipsall_cainQueue.addqueued_actionself#get_filling_actionsendelseOptions.warning"Skip binding annot for %s : Wrong number of bindings [RACC]"(get_ids_stringb1.bi_id)|_->Options.warning"Skip binding annot : Wrong number of bindings [RACC]"methodprivateadd_binding_annot()=lettag=get_tagididinmatchtagwith|"CACC"->self#add_binding_CACC_annot()|"RACC"->self#add_binding_RACC_annot()|_->Options.warning"Skip : Criteria %s not supported yet"tagmethodprivateadd_annot()=self#add_labels_annot();self#add_binding_annot()endletcreate_project_for_binding?nameid=letname=matchnamewith|None->"binding_"^get_ids_stringid|Somename->nameinletlbl_info=ref[]inletbinding_info=ref[]inletprj=File.create_project_from_visitorname(newbinding_selectoridlbl_infobinding_info)inletselection=Parameter_state.get_selection_context()inProject.copy~selectionprj;prj,!lbl_info,List.rev!binding_info