123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697(**************************************************************************)(* *)(* 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). *)(* *)(**************************************************************************)(** Those functions were previously outside the slicing module to show how to
* use the slicing API. So, they are supposed to use the slicing module through
* Db.Slicing only. There are mainly high level functions which make easier
* to achieve simple tasks. *)openCil_typestypeset=SlicingTypes.Fct_user_crit.tCil_datatype.Varinfo.Map.tletapply_all_actions()=SlicingParameters.debug~level:1"[Api.apply_all_internal]";SlicingParameters.feedback~level:1"applying all slicing requests...";SlicingParameters.debug~level:2"pending requests:@\n %t@\n"SlicingProject.print_proj_worklist;letr=SlicingProject.apply_all_actions()inSlicingParameters.feedback~level:2"done (applying all slicing requests).";rletapply_next_action()=SlicingParameters.debug~level:1"[Api.apply_next_internal]";SlicingProject.apply_next_action()letapply_all~propagate_to_callers=SlicingParameters.debug~level:1"[Api.apply_all]";assert(notpropagate_to_callers);trywhile(true)do(* Format.printf "@\napply_next_internal@."; *)apply_next_action()donewithNot_found->()letget_select_kf(fvar,_select)=Globals.Functions.getfvarletget_lval_zone?(for_writing=false)stmtlval=letopenEva.Resultsinbeforestmt|>eval_address~for_writinglval|>as_zone(** Utilities for [kinstr]. *)moduleKinstr:sigvaliter_from_func:(stmt->unit)->kernel_function->unitvalis_rw_zone:(Locations.Zone.toption*Locations.Zone.toption)->stmt->Locations.Zone.toption*Locations.Zone.toptionend=struct(** Iter on statements of a kernel function *)letiter_from_funcfkf=letdefinition=Kernel_function.get_definitionkfinList.iterfdefinition.sallstmts(** Get directly read/written [Zone.t] by the statement.
* i.e. directly means when [ki] is a call,
it doesn't don't look at the assigns clause of the called function. *)letget_rw_zonestmt=(* returns [Zone.t read],[Zone.t written] *)assert(Eva.Analysis.is_computed());letlval_processread_zonestmtlv=(* returns [read_zone] joined to [Zone.t read] by [lv], [Zone.t written] by [lv] *)(* The modified locations are [looking_for], those address are
function of [deps]. *)letzloc=get_lval_zone~for_writing:truestmtlvinletdeps=Eva.Results.(beforestmt|>address_depslv)inLocations.Zone.joinread_zonedeps,zlocinletcall_processlvfargs_loc=(* returns [Zone.t read] by [lv, f, args], [Zone.t written] by [lv] *)letread_zone=Eva.Results.(beforestmt|>expr_depsf)inletadd_argsarginputs=Locations.Zone.joininputsEva.Results.(beforestmt|>expr_depsarg)inletread_zone=List.fold_rightadd_argsargsread_zoneinletread_zone,write_zone=matchlvwith|None->read_zone,Locations.Zone.bottom|Somelv->lval_processread_zonestmtlvinread_zone,write_zoneinmatchstmt.skindwith|Switch(exp,_,_,_)|If(exp,_,_,_)->(* returns [Zone.t read] by condition [exp], [Zone.bottom] *)Eva.Results.(beforestmt|>expr_depsexp),Locations.Zone.bottom|Instr(Set(lv,exp,_))->(* returns [Zone.t read] by [exp, lv], [Zone.t written] by [lv] *)letread_zone=Eva.Results.(beforestmt|>expr_depsexp)inlval_processread_zonestmtlv|Instr(Local_init(v,AssignIniti,_))->letreccollectzonei=matchiwith|SingleInite->Locations.Zone.joinzoneEva.Results.(beforestmt|>expr_depse)|CompoundInit(_,l)->List.fold_left(funacc(_,i)->collectacci)zonelinletread_zone=collectLocations.Zone.bottomiinlval_processread_zonestmt(Cil.varv)|Instr(Call(lvaloption,funcexp,argl,l))->call_processlvaloptionfuncexpargll|Instr(Local_init(v,ConsInit(f,args,k),l))->Cil.treat_constructor_as_funccall_processvfargskl|_->Locations.Zone.bottom,Locations.Zone.bottom(** Look at intersection of [rd_zone_opt]/[wr_zone_opt] with the
directly read/written [Zone.t] by the statement.
* i.e. directly means when [ki] is a call,
it doesn't don't look at the assigns clause of the called function. *)letis_rw_zone(rd_zone_opt,wr_zone_opt)stmt=letrd_zone,wr_zone=get_rw_zonestmtinletinter_zonezone_optzone=matchzone_optwith|None->zone_opt|Somezone_requested->ifLocations.Zone.intersectszone_requestedzonethenletinter=Locations.Zone.narrowzone_requestedzoneinSomeinterelseNoneininter_zonerd_zone_optrd_zone,inter_zonewr_zone_optwr_zoneend(** Topologically propagate user marks to callers in whole project *)lettopologic_propagationproject=apply_all_actionsproject;Callgraph.Uses.iter_in_rev_order(funkf->SlicingParameters.debug~level:3"doing topologic propagation for function: %a"Kernel_function.prettykf;apply_all_actionsproject)letadd_to_selectionsetselection=SlicingSelect.Selections.add_to_selectsselectionset(** Registered as a slicing selection function:
Add a selection of the pdg nodes. *)letselect_pdg_nodessetmarknodeskf=letselection=SlicingSelect.select_pdg_nodeskfnodesmarkinadd_to_selectionsetselection(** Registered as a slicing selection function:
Add a selection of the statement. *)letselect_stmtset~sparestmtkf=letstmt_mark=SlicingMarks.mk_user_mark~data:(notspare)~addr:(notspare)~ctrl:(notspare)inletselection=SlicingSelect.select_stmt_computationkfstmtstmt_markinadd_to_selectionsetselection(** Add a selection to the entrance of the function [kf]
and add a selection to its return if [~return] is true
and add a selection to [~inputs] parts of its inputs
and add a selection to [~outputs] parts of its outputs*)letselect_entry_point_and_some_inputs_outputsset~markkf~return~outputs~inputs=SlicingParameters.debug~level:3"select_entry_point_and_some_inputs_outputs %a"Kernel_function.prettykf;letset=letselection=SlicingSelect.select_entry_pointkfmarkinadd_to_selectionsetselectioninletset=if(Locations.Zone.equalLocations.Zone.bottominputs)thensetelseletselection=SlicingSelect.select_zone_at_entrykfinputsmarkinadd_to_selectionsetselectioninif((Locations.Zone.equalLocations.Zone.bottomoutputs)&¬return)||(tryletstmt=Kernel_function.find_returnkfinifEva.Results.is_reachablestmtthenfalseelsebeginSlicingParameters.feedback"@[Nothing to select for unreachable return stmt of %a@]"Kernel_function.prettykf;trueendwithKernel_function.No_Statement->false)thensetelseletset=if(Locations.Zone.equalLocations.Zone.bottomoutputs)thensetelseletselection=SlicingSelect.select_modified_output_zonekfoutputsmarkinadd_to_selectionsetselectioninifreturnthenletselection=SlicingSelect.select_returnkfmarkinadd_to_selectionsetselectionelseset(* apply [select ~spare] on each callsite of [kf] and add the returned selection
to [set]. *)letgeneric_select_func_callsselect_stmtset~sparekf=assert(Eva.Analysis.is_computed());letcallers=Eva.Results.callsiteskfinletselect_callsacc(caller,stmts)=List.fold_left(funaccs->select_stmtacc~sparescaller)accstmtsinList.fold_leftselect_callssetcallers(** Registered as a slicing selection function:
Add a selection of calls to a [kf]. *)letselect_func_calls_intoset~sparekf=letadd_to_selectset~spareselect=letmark=letnspare=notspareinSlicingMarks.mk_user_mark~data:nspare~addr:nspare~ctrl:nspareinadd_to_selectionset(selectmark)inletkf_entry,_library=Globals.entry_point()inifKernel_function.equalkf_entrykfthenadd_to_selectset~spare(SlicingSelect.select_entry_pointkf)elseletselect_min_callset~sparekikf=add_to_selectset~spare(SlicingSelect.select_minimal_callkfki)ingeneric_select_func_callsselect_min_callset~sparekf(** Registered as a slicing selection function:
Add a selection of calls to a [kf]. *)letselect_func_calls_toset~sparekf=letkf_entry,_library=Globals.entry_point()inifKernel_function.equalkf_entrykfthenbeginletmark=letnspare=notspareinSlicingMarks.mk_user_mark~data:nspare~addr:nspare~ctrl:nspareinassert(Eva.Analysis.is_computed());letoutputs=!Db.Outputs.get_externalkfinselect_entry_point_and_some_inputs_outputsset~markkf~return:true~outputs~inputs:Locations.Zone.bottomendelsegeneric_select_func_callsselect_stmtset~sparekf(** Registered as a slicing selection function:
Add selection of function outputs. *)letselect_func_zonesetmarkzonekf=letselection=SlicingSelect.select_zone_at_endkfzonemarkinadd_to_selectionsetselection(** Registered as a slicing selection function:
Add a selection of the [kf] return statement. *)letselect_func_returnset~sparekf=tryletki=Kernel_function.find_returnkfinselect_stmtset~sparekikfwithKernel_function.No_Statement->letmark=SlicingMarks.mk_user_mark~data:(notspare)~addr:(notspare)~ctrl:(notspare)inselect_entry_point_and_some_inputs_outputsset~markkf~return:true~outputs:Locations.Zone.bottom~inputs:Locations.Zone.bottom(** Registered as a slicing selection function:
Add a selection of the statement reachability.
Note: add also a transparent selection on the whole statement. *)letselect_stmt_ctrlset~sparekikf=letctrl_mark=SlicingMarks.mk_user_mark~data:false~addr:false~ctrl:(notspare)inletselection=SlicingSelect.select_stmt_computationkfkictrl_markinadd_to_selectionsetselection(** Registered as a slicing selection function:
Add a selection of data relative to a statement.
Note: add also a transparent selection on the whole statement. *)letselect_stmt_zonesetmarkzone~beforekikf=letselection=SlicingSelect.select_stmt_zonekfki~beforezonemarkinletset=add_to_selectionsetselectioninselect_stmt_ctrlset~spare:truekikf(** Registered as a slicing selection function:
Add a selection of data relative to a statement.
Variables of [lval_str] string are bounded
relatively to the whole scope of the function [kf].
The interpretation of the address of the lvalues is
done just before the execution of the statement [~eval].
The selection preserve the value of these lvalues before
or after (c.f. boolean [~before]) the statement [ki].
Note: add also a transparent selection on the whole statement. *)letselect_stmt_lvalsetmarklval_str~beforeki~evalkf=assert(Eva.Analysis.is_computed());ifDatatype.String.Set.is_emptylval_strthensetelseletzone=Datatype.String.Set.fold(funlval_stracc->letlval_term=Logic_parse_string.term_lvalkflval_strinletlval=Logic_to_c.term_lval_to_lvallval_terminletzone=get_lval_zoneevallvalinLocations.Zone.joinzoneacc)lval_strLocations.Zone.bottominselect_stmt_zonesetmarkzone~beforekikf(** Add a selection of data relative to read/write accesses.
Interpret the [~rd] lvalues and the [~wr] lvalues from [~eval]
statements of [kf]:
- Variables of [lval_str] string are bounded
relatively to the whole scope of the function [kf].
- The interpretation of the address of the lvalues is
done just before the execution of the statement [~eval].
Find read/write accesses from the whole project if [ki_opt]=None.
Otherwise, restrict the research among the direct effect of [ki_opt] statement.
i.e. when [ki_opt] is a call, the selection doesn't look at the assigns clause
of a call. *)letselect_lval_rwsetmark~rd~wr~evalkfki_opt=assert(Eva.Analysis.is_computed());letzone_option~for_writinglval_str=ifDatatype.String.Set.is_emptylval_strthenNoneelseletzone=Datatype.String.Set.fold(funlval_stracc->letlval_term=Logic_parse_string.term_lvalkflval_strinletlval=Logic_to_c.term_lval_to_lvallval_terminletzone=get_lval_zone~for_writingevallvalinLocations.Zone.joinzoneacc)lval_strLocations.Zone.bottominSlicingParameters.debug~level:3"select_lval_rw %a zone=%a"Kernel_function.prettykfLocations.Zone.prettyzone;Somezoneinletzone_rd_opt=zone_option~for_writing:falserdinletzone_wr_opt=zone_option~for_writing:truewrinmatchzone_rd_opt,zone_wr_optwith|None,None->set|(_,_)aszone_option_rw->letac=refsetinletselect_rw_from_stmtkfki=letrd_zone_opt,wr_zone_opt=Kinstr.is_rw_zonezone_option_rwkiinletselect_zone~beforezone_opt=matchzone_optwith|None->!ac|Somezone->SlicingParameters.debug~level:3"select_lval_rw sid=%d before=%b zone=%a"ki.sidbeforeLocations.Zone.prettyzone;select_stmt_zone!acmarkzone~beforekikf;inac:=select_zone~before:truerd_zone_opt;ac:=select_zone~before:falsewr_zone_optin(matchki_optwith|Someki->select_rw_from_stmtkfki|None->Globals.Functions.iter(funkf->ifEva.Results.is_calledkfthenifnot(Eva.Analysis.use_spec_instead_of_definitionkf)then(* Called function with source code: just looks at its stmt *)Kinstr.iter_from_func(select_rw_from_stmtkf)kfelsebegin(* Called function without source code: looks at its effect *)letselect_inter_zonefselzone_optzone=matchzone_optwith|None->()|Somezone_requested->(* Format.printf "@\nselect_lval_rw zone_req=%a zone=%a@."
Locations.Zone.pretty zone_requested
Locations.Zone.pretty zone; *)ifLocations.Zone.intersectszone_requestedzonethenletinter=Locations.Zone.narrowzone_requestedzoneinfselinterelse()inletselect_wroutputs=ac:=select_entry_point_and_some_inputs_outputs!ac~markkf~return:false~outputs~inputs:Locations.Zone.bottomandselect_rdinputs=ac:=select_entry_point_and_some_inputs_outputs!ac~markkf~return:false~inputs~outputs:Locations.Zone.bottominassert(Eva.Results.is_calledkf);(* otherwise [!Db.Outputs.get_external kf] gives weird results *)select_inter_zoneselect_wrzone_wr_opt(!Db.Outputs.get_externalkf);select_inter_zoneselect_rdzone_rd_opt(!Db.Inputs.get_externalkf)end));!ac(** Registered as a slicing selection function:
Add a selection of rw accesses to lvalues relative to a statement.
Variables of [~rd] and [~wr] string are bounded
relatively to the whole scope of the function [kf].
The interpretation of the address of the lvalues is
done just before the execution of the statement [~eval].
The selection preserve the [~rd] and ~[wr] accesses
directly contained into the statement [ki].
i.e. when [ki] is a call, the selection doesn't look at
the assigns clause of the called function.
Note: add also a transparent selection on the whole statement.*)letselect_stmt_lval_rwsetmark~rd~wrki~evalkf=select_lval_rwsetmark~rd~wr~evalkf(Someki)(** Add a selection of the declaration of [vi]. *)letselect_decl_varsetmarkvikf=letselection=SlicingSelect.select_decl_varkfvimarkinadd_to_selectionsetselectionletselect_ZoneAnnot_pragmasset~sparepragmaskf=letset=Cil_datatype.Stmt.Set.fold(* selection related to statement assign and //@ slice pragma stmt *)(funki'acc->select_stmtacc~spareki'kf)pragmas.Logic_deps.stmtsetinCil_datatype.Stmt.Set.fold(* selection related to //@ slice pragma ctrl/expr *)(funki'acc->select_stmt_ctrlacc~spareki'kf)pragmas.Logic_deps.ctrlsetletselect_ZoneAnnot_zones_decl_varssetmark(zones,decl_vars)kf=letset=Cil_datatype.Varinfo.Set.fold(funviacc->select_decl_varaccmarkvikf)decl_vars.Logic_deps.varsetinletset=Cil_datatype.Logic_label.Set.fold(funlacc->letselection=SlicingSelect.select_labelkflmarkinadd_to_selectionaccselection)decl_vars.Logic_deps.lblsetinList.fold_right(funzacc->(* selection related to the parsing/compilation of the annotation *)select_stmt_zoneaccmarkz.Logic_deps.zone~before:z.Logic_deps.beforez.Logic_deps.kikf)zonessetletget_or_raise(info_data_opt,info_decl)=matchinfo_data_optwith|None->(* TODO: maybe we can know how to use [info_decl] ? *)SlicingParameters.not_yet_implemented"%s"!Logic_deps.not_yet_implemented|Someinfo_data->info_data,info_decl(** Registered as a slicing selection function:
Add selection of the annotations related to a statement.
Note: add also a transparent selection on the whole statement. *)letselect_stmt_predsetmarkpredkikf=letzones_decl_vars=Logic_deps.from_predpred(Logic_deps.mk_ctx_stmt_annotkfki)inselect_ZoneAnnot_zones_decl_varssetmark(get_or_raisezones_decl_vars)kf(** Registered as a slicing selection function:
Add selection of the annotations related to a statement.
Note: add also a transparent selection on the whole statement. *)letselect_stmt_termsetmarktermkikf=letzones_decl_vars=Logic_deps.from_termterm(Logic_deps.mk_ctx_stmt_annotkfki)inselect_ZoneAnnot_zones_decl_varssetmark(get_or_raisezones_decl_vars)kf(** Registered as a slicing selection function:
Add selection of the annotations related to a statement.
Note: add also a transparent selection on the whole statement. *)letselect_stmt_annotsetmark~spareannotkikf=letzones_decl_vars,pragmas=Logic_deps.from_stmt_annotannot(ki,kf)inletset=select_ZoneAnnot_pragmasset~sparepragmaskfinselect_ZoneAnnot_zones_decl_varssetmark(get_or_raisezones_decl_vars)kf(** Registered as a slicing selection function:
Add selection of the annotations related to a statement.
Note: add also a transparent selection on the whole statement. *)letselect_stmt_annotssetmark~spare~threat~user_assert~slicing_pragma~loop_inv~loop_varkikf=letzones_decl_vars,pragmas=Logic_deps.from_stmt_annots(Some(Logic_deps.code_annot_filter~threat~user_assert~slicing_pragma~loop_inv~loop_var~others:false))(ki,kf)inletset=select_ZoneAnnot_pragmasset~sparepragmaskfinselect_ZoneAnnot_zones_decl_varssetmark(get_or_raisezones_decl_vars)kf(** Registered as a slicing selection function:
Add a selection of the annotations related to a function. *)letselect_func_annotssetmark~spare~threat~user_assert~slicing_pragma~loop_inv~loop_varkf=tryletzones_decl_vars,pragmas=Logic_deps.from_func_annotsKinstr.iter_from_func(Some(Logic_deps.code_annot_filter~threat~user_assert~slicing_pragma~loop_inv~loop_var~others:false))kfinletset=select_ZoneAnnot_pragmasset~sparepragmaskfinselect_ZoneAnnot_zones_decl_varssetmark(get_or_raisezones_decl_vars)kfwithKernel_function.No_Definition->SlicingParameters.warning~wkey:SlicingParameters.wkey_cmdline"No definition for function '%a'. \
Slicing requests from the command line are ignored."Kernel_function.prettykf;Cil_datatype.Varinfo.Map.empty(** Registered as a slicing selection function:
Add selection of function outputs.
Variables of [lval_str] string are bounded
relatively to the whole scope of the function [kf].
The interpretation of the address of the lvalues is
done just before the execution of the first statement [kf].
The selection preserve the value of these lvalues before
execution of the return statement. *)letselect_func_lvalsetmarklval_strkf=ifDatatype.String.Set.is_emptylval_strthensetelseletki_scope_eval=Kernel_function.find_first_stmtkfinselect_stmt_lvalsetmarklval_str~before:false(Kernel_function.find_returnkf)~eval:ki_scope_evalkf(** Registered as a slicing selection function:
Add a selection of data relative to read/write accesses.
Interpret the [~rd] lvalues and the [~wr] lvalues from [~eval]
statements of [kf]:
- Variables of [lval_str] string are bounded
relatively to the whole scope of the function [kf].
- The interpretation of the address of the lvalues is
done just before the execution of the statement [~eval].
Find read/write accesses from the whole project if [ki_opt]=None. *)letselect_func_lval_rwsetmark~rd~wr~evalkf=ifDatatype.String.Set.is_emptyrd&&Datatype.String.Set.is_emptywrthensetelseselect_lval_rwsetmark~rd~wr~evalkfNone(** Registered as a slicing request function:
Add selections to all concerned slices, as slicing requests and apply them,
kernel function by kernel function.
Note:
- the function begins by applying the remaining internal requests.
- the requests added for the last kernel function are not applied. *)letadd_selectionset=letadd_selectionprevselection=letkf=get_select_kfselectioninletr=matchprevwithNone->apply_all_actions();Some(kf)|Someprev_kf->ifprev_kf==kfthenprevelseNoneandmake_requestslice=SlicingSelect.add_ff_selectionsliceselectionandslices=letslices=SlicingProject.get_sliceskfinifslices=[]then[SlicingProject.create_slicekf]elseslicesinList.itermake_requestslices;rinignore(SlicingSelect.Selections.fold_selects_internaladd_selectionNoneset)(** Registered as a slicing request function:
Add selections that will be applied to all the slices of the function
(already existing or created later)
Note:
- the function begins by applying the remaining internal requests.
- the requests added for the last kernel function are not applied. *)letadd_persistent_selectionset=(* Format.printf "@\nadd_persistent_selection@."; *)letadd_selectionprevselection=letkf=get_select_kfselectioninletr=matchprevwithNone->apply_all_actions();Some(kf)|Someprev_kf->ifprev_kf==kfthenprevelseNoneinSlicingSelect.add_fi_selectionselection;rinignore(SlicingSelect.Selections.fold_selects_internaladd_selectionNoneset)(** Registered as a slicing request function:
Add selections that will be applied to all the slices of the function
(already existing or created later)
Note:
- the function begins by applying the remaining internal requests.
- the requests added for the last kernel function are not applied. *)letadd_persistent_cmdline()=SlicingParameters.feedback~level:1"interpreting slicing requests from the command line...";begintryletselection=refCil_datatype.Varinfo.Map.emptyinlettop_mark=SlicingMarks.mk_user_mark~addr:true~ctrl:true~data:trueinGlobals.Functions.iter(funkf->letadd_selectionoptselect=ifKernel_function.Set.memkf(opt())thenselection:=select!selection~spare:falsekfinadd_selectionSlicingParameters.Select.Return.getselect_func_return;add_selectionSlicingParameters.Select.Calls.getselect_func_calls_to;add_selectionSlicingParameters.Select.Pragma.get(funs->select_func_annotsstop_mark~threat:false~user_assert:false~slicing_pragma:true~loop_inv:false~loop_var:false);add_selectionSlicingParameters.Select.Threat.get(funs->select_func_annotsstop_mark~threat:true~user_assert:false~slicing_pragma:false~loop_inv:false~loop_var:false);add_selectionSlicingParameters.Select.Assert.get(funs->select_func_annotsstop_mark~threat:false~user_assert:true~slicing_pragma:false~loop_inv:false~loop_var:false);add_selectionSlicingParameters.Select.LoopInv.get(funs->select_func_annotsstop_mark~threat:false~user_assert:false~slicing_pragma:false~loop_inv:true~loop_var:false);add_selectionSlicingParameters.Select.LoopVar.get(funs->select_func_annotsstop_mark~threat:false~user_assert:false~slicing_pragma:false~loop_inv:false~loop_var:true););ifnot(Datatype.String.Set.is_empty(SlicingParameters.Select.Value.get()))||not(Datatype.String.Set.is_empty(SlicingParameters.Select.RdAccess.get()))||not(Datatype.String.Set.is_empty(SlicingParameters.Select.WrAccess.get()))thenbegin(* fprintf fmt "@\n[-slice-value] Select %s at end of the entry point %a@."
lval_str Db.pretty_name kf; *)letkf=fst(Globals.entry_point())inletki_scope_eval=Kernel_function.find_first_stmtkfinselection:=select_func_lval!selectiontop_mark(SlicingParameters.Select.Value.get())kf;selection:=select_func_lval_rw!selectiontop_mark~rd:(SlicingParameters.Select.RdAccess.get())~wr:(SlicingParameters.Select.WrAccess.get())~eval:ki_scope_evalkf;SlicingParameters.Select.Value.clear();SlicingParameters.Select.RdAccess.clear();SlicingParameters.Select.WrAccess.clear();end;add_persistent_selection!selection;withLogic_parse_string.Error(_loc,msg)->SlicingParameters.warning~wkey:SlicingParameters.wkey_cmdline"%s. Slicing requests from the command line are ignored."msgend;SlicingParameters.feedback~level:2"done (interpreting slicing requests from the command line)."(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)