let compute_internal_using_cfg kf =
let compute_for_definition kf f =
try
let module Computer =
Computer
(struct let stmt_can_reach = Stmts_graph.stmt_can_reach kf end)
in
let module Compute = Dataflow.Forwards(Computer) in
Stack.iter
(fun g -> if kf == g then begin
if Db.Value.ignored_recursive_call kf then
Inout_parameters.warning ~current:true
"During inout context analysis of %a: ignoring probable recursive call."
Kernel_function.pretty kf;
raise Exit
end)
call_stack;
Stack.push kf call_stack;
let res_if_termination =
match f.sbody.bstmts with
[] -> assert false
| start :: _ ->
try
let ret_id = Kernel_function.find_return kf in
Computer.StmtStartData.add
start
(Computer.computeFirstPredecessor
start
empty);
Compute.compute [start];
ignore (Stack.pop call_stack);
try Computer.StmtStartData.find ret_id with Not_found -> bottom
with Kernel_function.No_Statement->
assert false
in
{ Inout_type.over_inputs_if_termination = res_if_termination.over_inputs;
under_outputs_if_termination = res_if_termination.under_outputs ;
over_inputs =
let acc = Computer.non_terminating_callees_inputs
in
Computer.StmtStartData.iter
(fun _sid data -> acc := Zone.join data.over_inputs !acc);
!acc}
with Exit ->
{ Inout_type.over_inputs_if_termination = empty.over_inputs ;
under_outputs_if_termination = empty.under_outputs ;
over_inputs = empty.over_inputs
}
in
match kf.fundec with
| Declaration _ ->
invalid_arg
"compute_using_cfg cannot be called on library functions"
| Definition (f, _) ->
compute_for_definition kf f