123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* 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 licenses/LGPLv2.1). *)(* *)(**************************************************************************)openCil_typestypelabel_mapping=Cil_types.logic_label->Clabels.c_label(** push the Tat down to the 'data' operations.
* This can be useful in cases like \at (x + \at(y, Ly), Lx) because
* it gives \at(x, Lx) + \at(y, Ly) so there is no more \at imbrications.
* Also try to "normalize" label :
* - remove Here because its meaning change when propagating,
* - remove Old because its meaning depend on where it comes from.
* *)classnorm_at(mapping:label_mapping)=object(self)inheritVisitor.generic_frama_c_visitor(Visitor_behavior.copy(Project.current()))valmutablecurrent_label=Nonemethodprivatechange_labellabel=letlabel=mappinglabelinletold_label=current_labelincurrent_label<-Somelabel;old_labelmethodprivaterestore_termold_labelx=current_label<-old_label;letx=matchx.term_nodewith|Ttypeofx->(* Ttypeof is used as a dummy unary construct *)x|_->assertfalseinxmethodprivaterestore_predold_labelx=current_label<-old_label;letx=matchx.pred_contentwith|Pnotx->(* Pnot is used as a dummy unary construct *)x|_->assertfalseinxmethod!vtermt=matcht.term_nodewith|Tat(t,l)->letold_label=self#change_labellinletnew_t={twithterm_node=Ttypeoft}inCil.ChangeDoChildrenPost(new_t,self#restore_termold_label)|TAddrOf(h,_)|TLval(h,_)|TStartOf(h,_)->letold_label=current_labelinletat_label=matchhwith|TResult_|TVar{lv_name="\\exit_status"}->SomeClabels.post|_->old_labelincurrent_label<-None;letpostt=current_label<-old_label;matchat_labelwith|Somelabel->{twithterm_node=Tat(t,Clabels.to_logiclabel)}|None->tinCil.ChangeDoChildrenPost(t,post)|Tapp_->letpost=function|{term_node=Tapp(predicate,labels,args)}ast->letnormalizel=mappingl|>Clabels.to_logicinletnew_labels=List.mapnormalizelabelsin{twithterm_node=Tapp(predicate,new_labels,args)}|_->assertfalseinCil.ChangeDoChildrenPost(t,post)|_->Cil.DoChildrenmethod!vpredicatep=matchp.pred_contentwith|Pat(p,l)->letold_label=self#change_labellinletnew_p={pwithpred_content=Pnotp}inCil.ChangeDoChildrenPost(new_p,self#restore_predold_label)|Papp_->letpost=function|{pred_content=Papp(predicate,labels,args)}asp->letnormalizel=mappingl|>Clabels.to_logicinletnew_labels=List.mapnormalizelabelsin{pwithpred_content=Papp(predicate,new_labels,args)}|_->assertfalseinCil.ChangeDoChildrenPost(p,post)|_->Cil.DoChildrenendexceptionLabelErroroflogic_labelletoptionl=functionSomel->l|None->raise(LabelErrorl)letlabels_emptyl=raise(LabelErrorl)letenclosing_loop?kf?atl=matchkf,atwith|Somekf,Somestmt->Kernel_function.find_enclosing_loopkfstmt|_->raise(LabelErrorl)letlabels_fct?kf?atl=matchlwith|BuiltinLabelInit->Clabels.init|BuiltinLabelPre->Clabels.pre|StmtLabelat->Clabels.stmt!at|BuiltinLabelLoopEntry->Clabels.loop_entry(enclosing_loop?kf?atl)(* Labels fct is not used to label invariant establishment/preservation,
thus, contrary to what is done in [labels_loop], Current is not Here. *)|BuiltinLabelLoopCurrent->Clabels.loop_current(enclosing_loop?kf?atl)|_->raise(LabelErrorl)(* -------------------------------------------------------------------------- *)(* --- Function Contracts --- *)(* -------------------------------------------------------------------------- *)letlabels_fct_pre=function|BuiltinLabelInit->Clabels.init|BuiltinLabel(Pre|Here)->Clabels.pre|l->raise(LabelErrorl)letlabels_fct_post~exit=function|BuiltinLabelInit->Clabels.init|BuiltinLabel(Pre|Old)->Clabels.pre|BuiltinLabel(Post|Here)->ifexitthenClabels.exitelseClabels.post|l->raise(LabelErrorl)letlabels_fct_assigns~exit=function|BuiltinLabelInit->Clabels.init|BuiltinLabel(Here|Pre|Old)->Clabels.pre|BuiltinLabelPost->ifexitthenClabels.exitelseClabels.post|l->raise(LabelErrorl)(* -------------------------------------------------------------------------- *)(* --- Statements Contracts --- *)(* -------------------------------------------------------------------------- *)letlabels_stmt_pre~kfs=function|BuiltinLabelHere->Clabels.stmts|l->labels_fct~kf~at:slletlabels_stmt_post~kfs=function|BuiltinLabelOld->Clabels.stmts|BuiltinLabel(Here|Post)->Clabels.stmt_posts|l->labels_fct~kf~at:slletlabels_stmt_assigns~kfs=function|BuiltinLabel(Here|Old)->Clabels.stmts|BuiltinLabelPost->Clabels.stmt_posts|l->labels_fct~kf~at:sl(* LEGACY *)letlabels_stmt_post_l~kfsl_post=function|BuiltinLabelOld->Clabels.stmts|BuiltinLabel(Here|Post)asl->optionll_post|l->labels_fct~kf~at:sl(* LEGACY *)letlabels_stmt_assigns_l~kfsl_post=function|BuiltinLabel(Here|Old)->Clabels.stmts|BuiltinLabelPostasl->optionll_post|l->labels_fct~kf~at:sl(* -------------------------------------------------------------------------- *)(* --- User Assertions in Functions Code --- *)(* -------------------------------------------------------------------------- *)letlabels_assert~kfs=function|BuiltinLabelHere->Clabels.stmts|l->labels_fct~kf~at:slletlabels_loops=function(* In invariant preservation/establishment, LoopCurrent is Here. *)|BuiltinLabel(Here|LoopCurrent)->Clabels.here|BuiltinLabelLoopEntry->Clabels.loop_entrys|FormalLabelwplabel->Clabels.formalwplabel|l->labels_fct?kf:None?at:Nonel(* current loop is handled above *)(* -------------------------------------------------------------------------- *)(* --- User Defined Predicates --- *)(* -------------------------------------------------------------------------- *)letlabels_predicatelab_pairsl=tryList.assocllab_pairs|>Clabels.of_logicwithNot_found->Clabels.of_logiclletlabels_axiom=function|FormalLabela->Clabels.formala|l->raise(LabelErrorl)(* -------------------------------------------------------------------------- *)(* --- Apply Normalization --- *)(* -------------------------------------------------------------------------- *)(** @raise LabelError if there is a label in [p] that is incompatible
* with the [labels] translation *)letpreproc_annotlabelsp=letvisitor=newnorm_atlabelsinVisitor.visitFramacPredicatevisitorpletpreproc_termlabelst=letvisitor=newnorm_atlabelsinVisitor.visitFramacTermvisitort(** @raise LabelError if there is a label in [p] that is incompatible
* with the [labels] translation *)letpreproc_assignslabelsasgns=letvisitor=newnorm_atlabelsinList.map(Visitor.visitFramacFromvisitor)asgnslethas_postassigns=function|WritesAny->false|Writesfroms->letexceptionHAS_POSTinletvisitor=newnorm_at(funl->ifClabels.is_postlthenraiseHAS_POSTelseClabels.of_logicl)intryList.iter(funfr->ignore@@Visitor.visitFramacFromvisitorfr)froms;falsewithHAS_POST->trueletcatch_label_errorextxt1txt2=matchexwith|LabelErrorlab->Wp_parameters.warning"Unexpected label %a in %s : ignored %s"Wp_error.pp_logic_labellabtxt1txt2|_->raiseex(* -------------------------------------------------------------------------- *)