@ -15,7 +15,9 @@ module VarSet = AbstractDomain.FiniteSet (Var)
module Domain = VarSet
module Domain = VarSet
(* * only kill pvars that are local; don't kill those that can escape *)
(* * only kill pvars that are local; don't kill those that can escape *)
let is_always_in_scope pvar = Pvar . is_return pvar | | Pvar . is_global pvar
let is_always_in_scope proc_desc pvar =
Pvar . is_return pvar | | Pvar . is_global pvar | | Procdesc . is_captured_pvar proc_desc pvar
let json_error ~ option_name ~ expected ~ actual =
let json_error ~ option_name ~ expected ~ actual =
L . die UserError " When parsing option %s: expected %s but got '%s' " option_name expected
L . die UserError " When parsing option %s: expected %s but got '%s' " option_name expected
@ -92,7 +94,7 @@ module TransferFunctions (LConfig : LivenessConfig) (CFG : ProcCfg.S) = struct
module CFG = CFG
module CFG = CFG
module Domain = Domain
module Domain = Domain
type analysis_data = uni t
type analysis_data = Procdesc . t
(* * add all of the vars read in [exp] to the live set *)
(* * add all of the vars read in [exp] to the live set *)
let exp_add_live exp astate =
let exp_add_live exp astate =
@ -122,7 +124,7 @@ module TransferFunctions (LConfig : LivenessConfig) (CFG : ProcCfg.S) = struct
add_live_actuals_ actuals live_acc
add_live_actuals_ actuals live_acc
let exec_instr astate () _ = function
let exec_instr astate proc_desc _ = function
| Sil . Load { id = lhs_id } when Ident . is_none lhs_id ->
| Sil . Load { id = lhs_id } when Ident . is_none lhs_id ->
(* dummy deref inserted by frontend--don't count as a read *)
(* dummy deref inserted by frontend--don't count as a read *)
astate
astate
@ -130,7 +132,7 @@ module TransferFunctions (LConfig : LivenessConfig) (CFG : ProcCfg.S) = struct
Domain . remove ( Var . of_id lhs_id ) astate | > exp_add_live rhs_exp
Domain . remove ( Var . of_id lhs_id ) astate | > exp_add_live rhs_exp
| Sil . Store { e1 = Lvar lhs_pvar ; e2 = rhs_exp } ->
| Sil . Store { e1 = Lvar lhs_pvar ; e2 = rhs_exp } ->
let astate' =
let astate' =
if is_always_in_scope lhs_pvar then astate (* never kill globals *)
if is_always_in_scope proc_desc lhs_pvar then astate (* never kill globals *)
else Domain . remove ( Var . of_pvar lhs_pvar ) astate
else Domain . remove ( Var . of_pvar lhs_pvar ) astate
in
in
exp_add_live rhs_exp astate'
exp_add_live rhs_exp astate'
@ -147,7 +149,7 @@ module TransferFunctions (LConfig : LivenessConfig) (CFG : ProcCfg.S) = struct
let actuals_to_read , astate =
let actuals_to_read , astate =
if cf_assign_last_arg then
if cf_assign_last_arg then
match IList . split_last_rev actuals with
match IList . split_last_rev actuals with
| Some ( ( Exp . Lvar pvar , _ ) , actuals' ) when not ( is_always_in_scope p var) ->
| Some ( ( Exp . Lvar pvar , _ ) , actuals' ) when not ( is_always_in_scope p roc_desc p var) ->
( actuals' , Domain . remove ( Var . of_pvar pvar ) astate )
( actuals' , Domain . remove ( Var . of_pvar pvar ) astate )
| _ ->
| _ ->
( actuals , astate )
( actuals , astate )
@ -213,7 +215,7 @@ let get_captured_by_ref_invariant_map proc_desc =
let checker { IntraproceduralAnalysis . proc_desc ; err_log } =
let checker { IntraproceduralAnalysis . proc_desc ; err_log } =
let captured_by_ref_invariant_map = get_captured_by_ref_invariant_map proc_desc in
let captured_by_ref_invariant_map = get_captured_by_ref_invariant_map proc_desc in
let cfg = CFG . from_pdesc proc_desc in
let cfg = CFG . from_pdesc proc_desc in
let invariant_map = CheckerAnalyzer . exec_cfg cfg () ~ initial : Domain . empty in
let invariant_map = CheckerAnalyzer . exec_cfg cfg proc_desc ~ initial : Domain . empty in
(* we don't want to report in harmless cases like int i = 0; if ( ... ) { i = ... } else { i = ... }
(* we don't want to report in harmless cases like int i = 0; if ( ... ) { i = ... } else { i = ... }
that create an intentional dead store as an attempt to imitate default value semantics .
that create an intentional dead store as an attempt to imitate default value semantics .
use dead stores to a " sentinel " value as a heuristic for ignoring this case * )
use dead stores to a " sentinel " value as a heuristic for ignoring this case * )