123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2024 *)(* 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 licenses/LGPLv2.1). *)(* *)(**************************************************************************)(** Find the statements that reads a given zone, using Inout. (Thus,
only operational reads are found.) *)openCil_typesopenLocationstypet=|DirectofCil_types.stmt|IndirectofCil_types.stmtclassfind_readzlval=objectinheritVisitor.frama_c_inplacevalmutableres:tlist=[]method!vstmt_auxstmt=letaux_calllvopt_kfargs_loc=letz=Inout.stmt_inputsstmtinifZone.intersectszzlvalthenbegin(* Computes what is read to evaluate [args] and [lvopt] *)letdeps=List.map(Inout.expr_inputsstmt)argsinletdeps=List.fold_leftZone.joinZone.bottomdepsinletdeps=matchlvoptwith|None->deps|Somelv->letdlv=Eva.Results.(beforestmt|>address_depslv)inZone.joindlvdepsinletdirect=Zone.intersectsdepszlvalin(* now determine if the functions called at [stmt] read directly or
indirectly [zlval] *)letaux_kf(direct,indirect)kf=letinputs=Inout.kf_inputskfin(* TODO: change to this once we can get "full" inputs through Inout.
Currently, non operational inputs disappear, and this function
is not suitable.
let inout = !Db.Operational_inputs.get_internal_precise ~stmt kf in
let inputs = inout.Inout_type.over_inputs in *)ifZone.intersectsinputszlvalthenifEva.Analysis.use_spec_instead_of_definitionkfthen(* Direct, as there is no body for this function. *)(true,indirect)else(direct,true)(* Indirect effect *)else(direct,indirect)(* this function pointer does not read [zlval] *)inletkfs=Eva.Results.calleestmtinletdirect,indirect=List.fold_leftaux_kf(direct,false)kfsinifdirectthenres<-Directstmt::res;ifindirectthenres<-Indirectstmt::res;endinmatchstmt.skindwith|Instr(Call(lvopt,f,args,loc))->aux_calllvoptfargsloc;Cil.SkipChildren|Instr(Local_init(v,ConsInit(f,args,k),l))->Cil.treat_constructor_as_funcaux_callvfargskl;Cil.SkipChildren|Instr_->letz=Inout.stmt_inputsstmtinifZone.intersectszzlvalthenbeginres<-Directstmt::resend;Cil.SkipChildren|If(e,_,_,_)|Switch(e,_,_,_)|Return(Somee,_)->letz=Inout.expr_inputsstmteinifZone.intersectszzlvalthenbeginres<-Directstmt::resend;Cil.DoChildren|_->Cil.DoChildrenmethodresult=resendletcomputez=letvis=newfind_readzinletaux_kf_fundeckf=letall_in=Inout.kf_inputskfinifZone.intersectsall_inzthenbeginletfundec=Kernel_function.get_definitionkfinignore(Visitor.visitFramacFunction(vis:>Visitor.frama_c_visitor)fundec;)endinletaux_kfkf=ifKernel_function.is_definitionkfthenaux_kf_fundeckfinGlobals.Functions.iteraux_kf;vis#result