123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161(**************************************************************************)(* *)(* This file is part of Aorai plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* INRIA (Institut National de Recherche en Informatique et en *)(* Automatique) *)(* INSA (Institut National des Sciences Appliquees) *)(* *)(* 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_typesopenAutomaton_astletdkey=Aorai_option.register_category"check-metavar"moduleVarSet=Cil_datatype.Varinfo.Setletpretty_setfmtset=letl=VarSet.elementssetinPretty_utils.pp_list~sep:", "Cil_printer.pp_varinfofmtlletpretty_statefmtst=Format.pp_print_stringfmtst.Automaton_ast.nameletpretty_transfmttr=Format.fprintffmt"from %a to %a:@\n{ @[%a@] } %a"pretty_statetr.startpretty_statetr.stopPretty_automaton.Typed.print_conditiontr.crossPretty_automaton.Typed.print_actionltr.actionsmoduletypeInitAnalysisParam=sigvalis_metavariable:varinfo->boolendmoduleInitAnalysis(Env:InitAnalysisParam)=structtypevertex=Aorai_graph.E.vertextypeedge=Aorai_graph.E.ttypeg=Aorai_graph.ttypedata=Bottom|InitializedSetofVarSet.tlettop=InitializedSetVarSet.emptyletinitv=ifv.Automaton_ast.init=Bool3.TruethentopelseBottomletdirection=Graph.Fixpoint.Forwardletequald1d2=matchd1,d2with|Bottom,d|d,Bottom->d=Bottom|InitializedSets1,InitializedSets2->VarSet.equals1s2letjoind1d2=matchd1,d2with|Bottom,d|d,Bottom->d|InitializedSets1,InitializedSets2->InitializedSet(VarSet.inters1s2)let_pretty_datafmt=function|Bottom->Format.printf"Bottom"|InitializedSetset->pretty_setfmtsetletchecktrusedinitialized=letdiff=VarSet.diffusedinitializedinifnot(VarSet.is_emptydiff)thenAorai_option.abort"The metavariables %a may not be initialized before the transition %a"pretty_setdiffpretty_transtrletterm_mvarst=letresult=refVarSet.emptyinletv=objectinheritVisitor.frama_c_inplacemethod!vlogic_var_uselv=matchlv.lv_originwith|SomeviwhenEnv.is_metavariablevi->result:=VarSet.addvi!result;Cil.SkipChildren|_->Cil.SkipChildrenendinignore(Visitor.visitFramacTermvt);!resultletreccond_mvars=function|TAnd(c1,c2)|TOr(c1,c2)->VarSet.union(cond_mvarsc1)(cond_mvarsc2)|TNot(c)->cond_mvarsc|TRel(_,t1,t2)->VarSet.union(term_mvarst1)(term_mvarst2)|TCall_|TReturn_|TTrue|TFalse->VarSet.emptyletanalyze(_,tr,_)=function|Bottom->Bottom|InitializedSetinitialized->(* Check that the condition uses only initialized variables *)checktr(cond_mvarstr.cross)(initialized);(* Add initialized variables and check the right hand side *)letaddinitialized=function|Copy_value((TVar({lv_origin=Somevi}),_),t)->checktr(term_mvarst)initialized;VarSet.addviinitialized|_->initializedinletinitialized'=List.fold_leftaddinitializedtr.actionsinAorai_option.debug~dkey"%a {%a} -> %a {%a}"pretty_statetr.startpretty_setinitializedpretty_statetr.stoppretty_setinitialized';InitializedSetinitialized'endletcheckInitializationauto=letmoduleP=structletis_metavariablevi=letmoduleMap=Datatype.String.MapinMap.exists(fun_->Cil_datatype.Varinfo.equalvi)auto.metavariablesendinletmoduleA=InitAnalysis(P)inletmoduleFixpoint=Graph.Fixpoint.Make(Aorai_graph)(A)inletg=Aorai_graph.of_automatonautoinlet_result=Fixpoint.analyzeA.initgin()letcheckSingleAssignmentauto=letcheck_actiontrassigned=function|Copy_value((TVar({lv_origin=Somevi}),_),_)->ifVarSet.memviassignedthenAorai_option.abort"The metavariable %a is assigned several times during the \
transition %a"Cil_printer.pp_varinfovipretty_transtr;VarSet.addviassigned|_->assignedinletcheck_transtr=ignore(List.fold_left(check_actiontr)VarSet.emptytr.actions)inList.itercheck_transauto.trans