123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* 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). *)(* *)(**************************************************************************)openPdg_typesopenPdgIndexopenLocationstypenode=PdgTypes.Node.t*Zone.tmoduleNS=structincludeHptmap.Make(PdgTypes.Node)(Locations.Zone)(Hptmap.Comp_unused)(structletv=[[]]end)(structletl=[Ast.self]end)letintersects=letname="Impact.Pdg_aux.NS.intersects"inletz_intersects_z1z2=Locations.Zone.intersectsz1z2inletmap_intersects=symmetric_binary_predicate(Hptmap_sig.PersistentCachename)ExistentialPredicate~decide_fast:decide_fast_intersection~decide_one:(fun__->false)~decide_both:z_intersectsinfuns1s2->map_intersectss1s2letinter=letdecide_z1z2=letinter=Locations.Zone.narrowz1z2inifLocations.Zone.is_bottominterthenNoneelseSomeinterininter~cache:(Hptmap_sig.PersistentCache"Pdg_aux.NS.inter")~symmetric:true~idempotent:true~decideletunion=letdecide_kz1z2=Zone.joinz1z2injoin~cache:(Hptmap_sig.PersistentCache"Pdg_aux.NS.union")~decide~symmetric:true~idempotent:trueletfind_defaultnm=tryfindnmwithNot_found->Zone.bottom(* We reimplement the following functions to get a Set semantics *)letadd'(n,z)m=letz'=find_defaultnminletz''=Zone.joinzz'inifZone.equalzz'thenmelseaddnz''mletmem'(n,z)m=letz'=find_defaultnminZone.is_includedzz'letremove'(n,z)m=letz'=find_defaultnminletz''=Zone.diffz'zin(* TODO: z is not an under-approximation *)ifZone.equalzZone.top||Zone.is_bottomz''thenremovenmelseaddnz''mletiter'fm=iter(funnz->f(n,z))mletfor_all'fm=tryiter(funnz->ifnot(f(n,z))thenraiseExit)m;truewithExit->falseletdiffm1m2=fold(funnzacc->remove'(n,z)acc)m2m1letfilter'f=map'(funnz->iff(n,z)thenSomezelseNone)letfoldf=fold(funnz->f(n,z))let()=Eva.Analysis.register_computation_hook(fun_->clear_caches())endtypecall_interface=(PdgTypes.Node.t*NS.t)listletpretty_nodefmt(n,z)=ifLocations.Zone.equalzLocations.Zone.topthenPdgTypes.Node.pretty_nodefmtnelseletopenPdgIndex.Signatureinletdefault()=Format.fprintffmt"%a/%a"PdgTypes.Node.pretty_nodenLocations.Zone.prettyzinletnarrow_by_z=function|OutOutRet|In(InCtrl|InNum_)->default()|In(InImplz')|Out(OutLocz')->ifLocations.Zone.equalzz'thenPdgTypes.Node.pretty_nodefmtnelsedefault()inmatchPdgTypes.Node.elem_keynwith|PdgIndex.Key.SigCallKey(_,key)|PdgIndex.Key.SigKeykey->narrow_by_zkey|_->default()letnode_list_to_set?(z=Zone.top)=List.fold_left(funset(n,zopt)->matchzopt,zwith|Somez,_|None,z->NS.add'(n,z)set)NS.empty(** [find_call_input_nodes pdg_caller s ?z input] find all the nodes of
[pdg_caller] that define the pdg input [input] above the call statement [s].
If [input] is an implicit input, its value is refined according to [z]. *)(* Copied from pdg/sets.ml, as it is currently not exported *)letfind_call_input_nodespdg_callercall_stmt?(z=Locations.Zone.top)in_key=matchin_keywith|PdgIndex.Signature.InCtrl|PdgIndex.Signature.InNum_->letidx=PdgTypes.Pdg.get_indexpdg_callerinlet_,call_sgn=FctIndex.find_callidxcall_stmtinletnode=PdgIndex.Signature.find_in_infocall_sgnin_keyin[node,None]|PdgIndex.Signature.InImplzone->letzone'=Locations.Zone.narrowzonezin(* skip undef zone: any result different from None is due to calldeps or
some imprecision. *)letnodes,_undef=Pdg.Api.find_location_nodes_at_stmtpdg_callercall_stmt~before:truezone'innodesletall_call_input_nodes~caller:pdg_caller~callee:(kf_callee,pdg_callee)call_stmt=letreal_inputs=letinout=!Db.Operational_inputs.get_internal_precise~stmt:call_stmtkf_calleeininout.Inout_type.over_inputs_if_terminationinlettest_inacc(in_key,in_node)=letdefault?z()=letin_nodes=find_call_input_nodespdg_callercall_stmt?zin_keyinletin_nodes=node_list_to_set?zin_nodesin(in_node,in_nodes)::accinmatchin_keywith|Signature.InCtrl|Signature.InNum_->default()|Signature.InImplz->ifLocations.Zone.intersectszreal_inputsthendefault~z:real_inputs()elseaccintryletsgn=FctIndex.sgn(PdgTypes.Pdg.get_indexpdg_callee)inPdgIndex.Signature.fold_all_inputstest_in[]sgnwithPdgTypes.Pdg.Top->Options.warning~source:(fst(Cil_datatype.Stmt.loccall_stmt))~once:true"skipping impact within imprecisely analyzed function %a"Kernel_function.prettykf_callee;[]letall_call_out_nodes~callee~callercall_stmt=trylet_,call_sgn=FctIndex.find_call(PdgTypes.Pdg.get_indexcaller)call_stmtinlettest_outacc(out_key,call_out_node)=(* skip undef: any zone found undef is due to an imprecision or a bug*)letout_nodes,_=Pdg.Api.find_output_nodescalleeout_keyinletout_nodes=node_list_to_setout_nodesin(call_out_node,out_nodes)::accinPdgIndex.Signature.fold_all_outputstest_out[]call_sgnwithPdgTypes.Pdg.Top->Options.warning~source:(fst(Cil_datatype.Stmt.loccall_stmt))~once:true"cannot propagate impact into imprecisely analyzed caller function %a"Kernel_function.pretty(Kernel_function.find_englobing_kfcall_stmt);[](*
Local Variables:
compile-command: "make -C ../../.."
End:
*)