[Bucketing] Improve error bucketing by using constant propagation when detecting direct null assignments.

master
Cristiano Calcagno 10 years ago
parent 1356fd331f
commit 6bde9bda88

@ -61,9 +61,17 @@ let check_access access_opt de_opt =
!formal_ids in !formal_ids in
let formal_param_used_in_call = ref false in let formal_param_used_in_call = ref false in
let has_call_or_sets_null node = let has_call_or_sets_null node =
let rec exp_is_null = function let rec exp_is_null exp = match exp with
| Sil.Const (Sil.Cint n) -> Sil.Int.iszero n | Sil.Const (Sil.Cint n) -> Sil.Int.iszero n
| Sil.Cast (_, e) -> exp_is_null e | Sil.Cast (_, e) -> exp_is_null e
| Sil.Var _
| Sil.Lvar _ ->
begin
match State.get_const_map () node exp with
| Some (Sil.Cint n) ->
Sil.Int.iszero n
| _ -> false
end
| _ -> false in | _ -> false in
let filter = function let filter = function
| Sil.Call (_, _, etl, _, _) -> | Sil.Call (_, _, etl, _, _) ->
@ -73,7 +81,8 @@ let check_access access_opt de_opt =
| _ -> false in | _ -> false in
if list_exists arg_is_formal_param etl then formal_param_used_in_call := true; if list_exists arg_is_formal_param etl then formal_param_used_in_call := true;
true true
| Sil.Set (_, _, e, _) -> exp_is_null e | Sil.Set (_, _, e, _) ->
exp_is_null e
| _ -> false in | _ -> false in
list_exists filter (Cfg.Node.get_instrs node) in list_exists filter (Cfg.Node.get_instrs node) in
let local_access_found = ref false in let local_access_found = ref false in

@ -467,11 +467,12 @@ let check_assignement_guard node =
(** Perform symbolic execution for a node starting from an initial prop *) (** Perform symbolic execution for a node starting from an initial prop *)
let do_symbolic_execution handle_exn cfg tenv let do_symbolic_execution handle_exn cfg tenv
(node : Cfg.node) (prop: Prop.normal Prop.t) (path : Paths.Path.t) = (node : Cfg.node) (prop: Prop.normal Prop.t) (path : Paths.Path.t) =
let pdesc = Cfg.Node.get_proc_desc node in
State.mark_execution_start node; State.mark_execution_start node;
State.set_const_map (ConstantPropagation.build_const_map pdesc); (* build the const map lazily *)
check_assignement_guard node; check_assignement_guard node;
let instrs = Cfg.Node.get_instrs node in let instrs = Cfg.Node.get_instrs node in
Ident.update_name_generator (instrs_get_normal_vars instrs); (* fresh normal vars must be fresh w.r.t. instructions *) Ident.update_name_generator (instrs_get_normal_vars instrs); (* fresh normal vars must be fresh w.r.t. instructions *)
let pdesc = Cfg.Node.get_proc_desc node in
let pset = let pset =
SymExec.lifted_sym_exec handle_exn cfg tenv pdesc SymExec.lifted_sym_exec handle_exn cfg tenv pdesc
(Paths.PathSet.from_renamed_list [(prop, path)]) node instrs in (Paths.PathSet.from_renamed_list [(prop, path)]) node instrs in

@ -2772,23 +2772,19 @@ end = struct
let pi_size pi = pi_weight * list_length pi let pi_size pi = pi_weight * list_length pi
module ExpMap =
Map.Make (struct
type t = Sil.exp
let compare = Sil.exp_compare end)
(** Approximate the size of the longest chain by counting the max (** Approximate the size of the longest chain by counting the max
number of |-> with the same type and whose lhs is primed or number of |-> with the same type and whose lhs is primed or
footprint *) footprint *)
let sigma_chain_size sigma = let sigma_chain_size sigma =
let tbl = ref ExpMap.empty in let tbl = ref Sil.ExpMap.empty in
let add t = let add t =
try try
let count = ExpMap.find t !tbl in let count = Sil.ExpMap.find t !tbl in
tbl := ExpMap.add t (count + 1) !tbl tbl := Sil.ExpMap.add t (count + 1) !tbl
with with
| Not_found -> | Not_found ->
tbl := ExpMap.add t 1 !tbl in tbl := Sil.ExpMap.add t 1 !tbl in
let process_hpred = function let process_hpred = function
| Sil.Hpointsto (e, _, te) -> | Sil.Hpointsto (e, _, te) ->
(match e with (match e with
@ -2797,7 +2793,7 @@ end = struct
| Sil.Hlseg _ | Sil.Hdllseg _ -> () in | Sil.Hlseg _ | Sil.Hdllseg _ -> () in
list_iter process_hpred sigma; list_iter process_hpred sigma;
let size = ref 0 in let size = ref 0 in
ExpMap.iter (fun t n -> size := max n !size) !tbl; Sil.ExpMap.iter (fun t n -> size := max n !size) !tbl;
!size !size
(** Compute a size value for the prop, which indicates its (** Compute a size value for the prop, which indicates its

@ -233,11 +233,6 @@ module Inequalities : sig
val d_neqs : t -> unit val d_neqs : t -> unit
end = struct end = struct
module ExpMap =
Map.Make (struct
type t = Sil.exp
let compare = Sil.exp_compare end)
type t = { type t = {
mutable leqs: (Sil.exp * Sil.exp) list; (** le fasts [e1 <= e2] *) mutable leqs: (Sil.exp * Sil.exp) list; (** le fasts [e1 <= e2] *)
mutable lts: (Sil.exp * Sil.exp) list; (** lt facts [e1 < e2] *) mutable lts: (Sil.exp * Sil.exp) list; (** lt facts [e1 < e2] *)
@ -281,14 +276,14 @@ end = struct
else begin else begin
let umap_add umap e new_upper = let umap_add umap e new_upper =
try try
let old_upper = ExpMap.find e umap in let old_upper = Sil.ExpMap.find e umap in
if Sil.Int.leq old_upper new_upper then umap else ExpMap.add e new_upper umap if Sil.Int.leq old_upper new_upper then umap else Sil.ExpMap.add e new_upper umap
with Not_found -> ExpMap.add e new_upper umap in with Not_found -> Sil.ExpMap.add e new_upper umap in
let lmap_add lmap e new_lower = let lmap_add lmap e new_lower =
try try
let old_lower = ExpMap.find e lmap in let old_lower = Sil.ExpMap.find e lmap in
if Sil.Int.geq old_lower new_lower then lmap else ExpMap.add e new_lower lmap if Sil.Int.geq old_lower new_lower then lmap else Sil.ExpMap.add e new_lower lmap
with Not_found -> ExpMap.add e new_lower lmap in with Not_found -> Sil.ExpMap.add e new_lower lmap in
let rec umap_create_from_leqs umap = function let rec umap_create_from_leqs umap = function
| [] -> umap | [] -> umap
| (e1, Sil.Const (Sil.Cint upper1)):: leqs_rest -> | (e1, Sil.Const (Sil.Cint upper1)):: leqs_rest ->
@ -306,7 +301,7 @@ end = struct
| constr:: constrs_rest -> | constr:: constrs_rest ->
try try
let e1, e2, n = DiffConstr.to_triple constr (* e1 - e2 <= n *) in let e1, e2, n = DiffConstr.to_triple constr (* e1 - e2 <= n *) in
let upper2 = ExpMap.find e2 umap in let upper2 = Sil.ExpMap.find e2 umap in
let new_upper1 = upper2 ++ n in let new_upper1 = upper2 ++ n in
let new_umap = umap_add umap e1 new_upper1 in let new_umap = umap_add umap e1 new_upper1 in
umap_improve_by_difference_constraints new_umap constrs_rest umap_improve_by_difference_constraints new_umap constrs_rest
@ -317,22 +312,26 @@ end = struct
| constr:: constrs_rest -> (* e2 - e1 > -n-1 *) | constr:: constrs_rest -> (* e2 - e1 > -n-1 *)
try try
let e1, e2, n = DiffConstr.to_triple constr (* e2 - e1 > -n-1 *) in let e1, e2, n = DiffConstr.to_triple constr (* e2 - e1 > -n-1 *) in
let lower1 = ExpMap.find e1 lmap in let lower1 = Sil.ExpMap.find e1 lmap in
let new_lower2 = lower1 -- n -- Sil.Int.one in let new_lower2 = lower1 -- n -- Sil.Int.one in
let new_lmap = lmap_add lmap e2 new_lower2 in let new_lmap = lmap_add lmap e2 new_lower2 in
lmap_improve_by_difference_constraints new_lmap constrs_rest lmap_improve_by_difference_constraints new_lmap constrs_rest
with Not_found -> with Not_found ->
lmap_improve_by_difference_constraints lmap constrs_rest in lmap_improve_by_difference_constraints lmap constrs_rest in
let leqs_res = let leqs_res =
let umap = umap_create_from_leqs ExpMap.empty leqs in let umap = umap_create_from_leqs Sil.ExpMap.empty leqs in
let umap' = umap_improve_by_difference_constraints umap diff_constraints2 in let umap' = umap_improve_by_difference_constraints umap diff_constraints2 in
let leqs' = ExpMap.fold (fun e upper acc_leqs -> (e, Sil.exp_int upper):: acc_leqs) umap' [] in let leqs' = Sil.ExpMap.fold
(fun e upper acc_leqs -> (e, Sil.exp_int upper):: acc_leqs)
umap' [] in
let leqs'' = (list_map DiffConstr.to_leq diff_constraints2) @ leqs' in let leqs'' = (list_map DiffConstr.to_leq diff_constraints2) @ leqs' in
leqs_sort_then_remove_redundancy leqs'' in leqs_sort_then_remove_redundancy leqs'' in
let lts_res = let lts_res =
let lmap = lmap_create_from_lts ExpMap.empty lts in let lmap = lmap_create_from_lts Sil.ExpMap.empty lts in
let lmap' = lmap_improve_by_difference_constraints lmap diff_constraints2 in let lmap' = lmap_improve_by_difference_constraints lmap diff_constraints2 in
let lts' = ExpMap.fold (fun e lower acc_lts -> (Sil.exp_int lower, e):: acc_lts) lmap' [] in let lts' = Sil.ExpMap.fold
(fun e lower acc_lts -> (Sil.exp_int lower, e):: acc_lts)
lmap' [] in
let lts'' = (list_map DiffConstr.to_lt diff_constraints2) @ lts' in let lts'' = (list_map DiffConstr.to_lt diff_constraints2) @ lts' in
lts_sort_then_remove_redundancy lts'' in lts_sort_then_remove_redundancy lts'' in
{ leqs = leqs_res; lts = lts_res; neqs = neqs } { leqs = leqs_res; lts = lts_res; neqs = neqs }

@ -1658,6 +1658,12 @@ module ExpSet = Set.Make
let compare = exp_compare let compare = exp_compare
end) end)
module ExpMap = Map.Make(struct
type t = exp
let compare = exp_compare
end)
let elist_to_eset es = let elist_to_eset es =
list_fold_left (fun set e -> ExpSet.add e set) ExpSet.empty es list_fold_left (fun set e -> ExpSet.add e set) ExpSet.empty es

@ -349,6 +349,9 @@ module TypMap : Map.S with type key = typ
(** Sets of expressions. *) (** Sets of expressions. *)
module ExpSet : Set.S with type elt = exp module ExpSet : Set.S with type elt = exp
(** Maps with expression keys. *)
module ExpMap : Map.S with type key = exp
(** Hashtable with expressions as keys. *) (** Hashtable with expressions as keys. *)
module ExpHash : Hashtbl.S with type key = exp module ExpHash : Hashtbl.S with type key = exp

@ -10,6 +10,12 @@ module L = Logging
module F = Format module F = Format
open Utils open Utils
type const_map = Cfg.Node.t -> Sil.exp -> Sil.const option
(** Constant map for the procedure *)
let const_map : const_map ref =
ref (fun node exp -> None)
(** Diverging states since the last reset for the node *) (** Diverging states since the last reset for the node *)
let diverging_states_node = ref Paths.PathSet.empty let diverging_states_node = ref Paths.PathSet.empty
@ -318,3 +324,9 @@ let set_node (node: Cfg.node) =
let set_session (session: int) = let set_session (session: int) =
last_session := session last_session := session
let get_const_map () =
!const_map
let set_const_map const_map' =
const_map := const_map'

@ -11,6 +11,11 @@ open Utils
(** Add diverging states *) (** Add diverging states *)
val add_diverging_states : Paths.PathSet.t -> unit val add_diverging_states : Paths.PathSet.t -> unit
type const_map = Cfg.Node.t -> Sil.exp -> Sil.const option
(** Get the constant map for the current procedure. *)
val get_const_map : unit -> const_map
(** Get the diverging states for the node *) (** Get the diverging states for the node *)
val get_diverging_states_node : unit -> Paths.PathSet.t val get_diverging_states_node : unit -> Paths.PathSet.t
@ -93,6 +98,9 @@ val reset : unit -> unit
(** Reset the diverging states and goto information for the node *) (** Reset the diverging states and goto information for the node *)
val reset_diverging_states_goto_node : unit -> unit val reset_diverging_states_goto_node : unit -> unit
(** Set the constant map for the current procedure. *)
val set_const_map : const_map -> unit
(** Set the node target of a Sil.Goto_node instruction *) (** Set the node target of a Sil.Goto_node instruction *)
val set_goto_node : int -> unit val set_goto_node : int -> unit

@ -1229,8 +1229,8 @@ and sym_exe_check_variadic_sentinel cfg pdesc tenv prop path actual_params fails
(* sentinels start counting from the last argument to the function *) (* sentinels start counting from the last argument to the function *)
let n = nargs - sentinel - 1 in let n = nargs - sentinel - 1 in
let build_argsi (acc, i) a = let build_argsi (acc, i) a =
if i = n then (acc, i+1) if i = n then (acc, i +1)
else ((a,i)::acc, i+1) in else ((a, i):: acc, i +1) in
(* list_fold_left reverses the arguments *) (* list_fold_left reverses the arguments *)
let non_terminal_actuals_i = fst (list_fold_left build_argsi ([], 0) args) in let non_terminal_actuals_i = fst (list_fold_left build_argsi ([], 0) args) in
let check_allocated result ((lexp, typ), i) = let check_allocated result ((lexp, typ), i) =
@ -1374,7 +1374,7 @@ and sym_exec_wrapper handle_exn cfg tenv pdesc instr ((prop: Prop.normal Prop.t)
let lifted_sym_exec let lifted_sym_exec
handle_exn cfg tenv pdesc (pset : Paths.PathSet.t) node (instrs : Sil.instr list) handle_exn cfg tenv pdesc (pset : Paths.PathSet.t) node (instrs : Sil.instr list)
: Paths.PathSet.t = : Paths.PathSet.t =
let pname = Cfg.Procdesc.get_proc_name pdesc in let pname = Cfg.Procdesc.get_proc_name pdesc in
let exe_instr_prop instr p tr (pset1: Paths.PathSet.t) = let exe_instr_prop instr p tr (pset1: Paths.PathSet.t) =
let pset2 = let pset2 =

@ -8,10 +8,6 @@ module L = Logging
type t type t
module ConstantMap = Map.Make(struct
type t = string
let compare = string_compare
end)
let string_widening_limit = 1000 let string_widening_limit = 1000
let verbose = false let verbose = false
@ -24,19 +20,22 @@ let merge_values key c1_opt c2_opt =
| None, Some c -> Some c | None, Some c -> Some c
| _ -> Some None | _ -> Some None
module ConstantMap = Sil.ExpMap
(** Dataflow struct *) (** Dataflow struct *)
module ConstantFlow = Dataflow.MakeDF(struct module ConstantFlow = Dataflow.MakeDF(struct
type t = (Sil.const option) ConstantMap.t type t = (Sil.const option) ConstantMap.t
let pp fmt constants = let pp fmt constants =
let pp_key fmt = Sil.pp_exp pe_text fmt in
let print_kv k = function let print_kv k = function
| Some v -> Format.fprintf fmt " %s -> %a@." k (Sil.pp_const pe_text) v | Some v -> Format.fprintf fmt " %a -> %a@." pp_key k (Sil.pp_const pe_text) v
| _ -> Format.fprintf fmt " %s -> None@." k in | _ -> Format.fprintf fmt " %a -> None@." pp_key k in
Format.fprintf fmt "[@."; Format.fprintf fmt "[@.";
ConstantMap.iter print_kv constants; ConstantMap.iter print_kv constants;
Format.fprintf fmt "]@." Format.fprintf fmt "]@."
(* Item-wise equality where values are equal iff (* Item - wise equality where values are equal iff
- both are None - both are None
- both are a constant and equal wrt. Sil.const_equal *) - both are a constant and equal wrt. Sil.const_equal *)
let equal m n = ConstantMap.equal (opt_equal Sil.const_equal) m n let equal m n = ConstantMap.equal (opt_equal Sil.const_equal) m n
@ -57,38 +56,31 @@ module ConstantFlow = Dataflow.MakeDF(struct
match instr with match instr with
| Sil.Letderef (i, Sil.Lvar p, _, _) -> (* tmp = var *) | Sil.Letderef (i, Sil.Lvar p, _, _) -> (* tmp = var *)
let lvar = Ident.to_string i in update (Sil.Var i) (ConstantMap.find (Sil.Lvar p) constants) constants
let rvar = Sil.pvar_to_string p in
update lvar (ConstantMap.find rvar constants) constants
| Sil.Set (Sil.Lvar p, _, Sil.Const c, _) -> (* var = const *) | Sil.Set (Sil.Lvar p, _, Sil.Const c, _) -> (* var = const *)
update (Sil.pvar_to_string p) (Some c) constants update (Sil.Lvar p) (Some c) constants
| Sil.Set (Sil.Lvar p, _, Sil.Var i, _) -> (* var = tmp *) | Sil.Set (Sil.Lvar p, _, Sil.Var i, _) -> (* var = tmp *)
let lvar = Sil.pvar_to_string p in update (Sil.Lvar p) (ConstantMap.find (Sil.Var i) constants) constants
let rvar = Ident.to_string i in
update lvar (ConstantMap.find rvar constants) constants
(* Handle propagation of string with StringBuilder. Does not handle null case *) (* Handle propagation of string with StringBuilder. Does not handle null case *)
| Sil.Call (_, Sil.Const (Sil.Cfun pn), (Sil.Var sb, _):: [], _, _) | Sil.Call (_, Sil.Const (Sil.Cfun pn), (Sil.Var sb, _):: [], _, _)
when Procname.java_get_class pn = "java.lang.StringBuilder" when Procname.java_get_class pn = "java.lang.StringBuilder"
&& Procname.java_get_method pn = "<init>" -> (* StringBuilder.<init> *) && Procname.java_get_method pn = "<init>" -> (* StringBuilder.<init> *)
update (Ident.to_string sb) (Some (Sil.Cstr "")) constants update (Sil.Var sb) (Some (Sil.Cstr "")) constants
| Sil.Call (i:: [], Sil.Const (Sil.Cfun pn), (Sil.Var i1, _):: [], _, _) | Sil.Call (i:: [], Sil.Const (Sil.Cfun pn), (Sil.Var i1, _):: [], _, _)
when Procname.java_get_class pn = "java.lang.StringBuilder" when Procname.java_get_class pn = "java.lang.StringBuilder"
&& Procname.java_get_method pn = "toString" -> (* StringBuilder.toString *) && Procname.java_get_method pn = "toString" -> (* StringBuilder.toString *)
let lvar = Ident.to_string i in update (Sil.Var i) (ConstantMap.find (Sil.Var i1) constants) constants
let rvar = Ident.to_string i1 in
update lvar (ConstantMap.find rvar constants) constants
| Sil.Call (i:: [], Sil.Const (Sil.Cfun pn), (Sil.Var i1, _):: (Sil.Var i2, _):: [], _, _) | Sil.Call (i:: [], Sil.Const (Sil.Cfun pn), (Sil.Var i1, _):: (Sil.Var i2, _):: [], _, _)
when Procname.java_get_class pn = "java.lang.StringBuilder" when Procname.java_get_class pn = "java.lang.StringBuilder"
&& Procname.java_get_method pn = "append" -> (* StringBuilder.append *) && Procname.java_get_method pn = "append" -> (* StringBuilder.append *)
let lvar = Ident.to_string i in (match
let rvar1 = Ident.to_string i1 in ConstantMap.find (Sil.Var i1) constants,
let rvar2 = Ident.to_string i2 in ConstantMap.find (Sil.Var i2) constants with
(match ConstantMap.find rvar1 constants, ConstantMap.find rvar2 constants with
| Some (Sil.Cstr s1), Some (Sil.Cstr s2) -> | Some (Sil.Cstr s1), Some (Sil.Cstr s2) ->
begin begin
let s = s1 ^ s2 in let s = s1 ^ s2 in
@ -97,7 +89,7 @@ module ConstantFlow = Dataflow.MakeDF(struct
Some (Sil.Cstr s) Some (Sil.Cstr s)
else else
None in None in
update lvar u constants update (Sil.Var i) u constants
end end
| _ -> constants) | _ -> constants)
@ -119,7 +111,7 @@ module ConstantFlow = Dataflow.MakeDF(struct
(Cfg.Node.get_instrs node) in (Cfg.Node.get_instrs node) in
if verbose then L.stdout "%a\n@." pp constants; if verbose then L.stdout "%a\n@." pp constants;
[constants], [constants] [constants], [constants]
end) end)
let run proc_desc = let run proc_desc =
let transitions = ConstantFlow.run proc_desc ConstantMap.empty in let transitions = ConstantFlow.run proc_desc ConstantMap.empty in
@ -128,3 +120,15 @@ let run proc_desc =
| ConstantFlow.Transition (_, post_states, _) -> ConstantFlow.join post_states ConstantMap.empty | ConstantFlow.Transition (_, post_states, _) -> ConstantFlow.join post_states ConstantMap.empty
| ConstantFlow.Dead_state -> ConstantMap.empty in | ConstantFlow.Dead_state -> ConstantMap.empty in
get_constants get_constants
type const_map = Cfg.Node.t -> Sil.exp -> Sil.const option
(** Build a const map lazily. *)
let build_const_map pdesc =
let const_map = lazy (run pdesc) in
let f node exp =
try
let map = (Lazy.force const_map) node in
ConstantMap.find exp map
with Not_found -> None in
f

@ -2,8 +2,7 @@
* Copyright (c) 2014 - Facebook. All rights reserved. * Copyright (c) 2014 - Facebook. All rights reserved.
*) *)
module ConstantMap: Map.S with type key = string type const_map = Cfg.Node.t -> Sil.exp -> Sil.const option
module ConstantFlow: Dataflow.DF with type state = (Sil.const option) ConstantMap.t (** Build a const map lazily. *)
val build_const_map : Cfg.Procdesc.t -> const_map
val run: Cfg.Procdesc.t -> (Cfg.Node.t -> ConstantFlow.state)

@ -3,7 +3,6 @@
*) *)
open Utils open Utils
open ConstantPropagation
module L = Logging module L = Logging
@ -23,19 +22,15 @@ let callback_sql all_procs get_proc_desc idenv tenv proc_name proc_desc =
list_map Str.regexp_case_fold _sql_start in list_map Str.regexp_case_fold _sql_start in
(* Check for SQL string concatenations *) (* Check for SQL string concatenations *)
let do_instr get_constants node = function let do_instr const_map node = function
| Sil.Call (_, Sil.Const (Sil.Cfun pn), (Sil.Var i1, _):: (Sil.Var i2, _):: [], l, _) | Sil.Call (_, Sil.Const (Sil.Cfun pn), (Sil.Var i1, _):: (Sil.Var i2, _):: [], l, _)
when Procname.java_get_class pn = "java.lang.StringBuilder" when Procname.java_get_class pn = "java.lang.StringBuilder"
&& Procname.java_get_method pn = "append" -> && Procname.java_get_method pn = "append" ->
let rvar1 = Ident.to_string i1 in let rvar1 = Sil.Var i1 in
let rvar2 = Ident.to_string i2 in let rvar2 = Sil.Var i2 in
begin begin
let matches s r = Str.string_match r s 0 in let matches s r = Str.string_match r s 0 in
let constants = get_constants node in match const_map node rvar1, const_map node rvar2 with
if ConstantMap.mem rvar1 constants
&& ConstantMap.mem rvar2 constants then
begin
match ConstantMap.find rvar1 constants, ConstantMap.find rvar2 constants with
| Some (Sil.Cstr ""), Some (Sil.Cstr s2) -> | Some (Sil.Cstr ""), Some (Sil.Cstr s2) ->
if list_exists (matches s2) sql_start then if list_exists (matches s2) sql_start then
begin begin
@ -48,11 +43,10 @@ let callback_sql all_procs get_proc_desc idenv tenv proc_name proc_desc =
end end
| _ -> () | _ -> ()
end end
end
| _ -> () in | _ -> () in
try try
let get_constants = ConstantPropagation.run proc_desc in let const_map = ConstantPropagation.build_const_map proc_desc in
if verbose then L.stdout "Analyzing %a...\n@." Procname.pp proc_name; if verbose then L.stdout "Analyzing %a...\n@." Procname.pp proc_name;
Cfg.Procdesc.iter_instrs (do_instr get_constants) proc_desc Cfg.Procdesc.iter_instrs (do_instr const_map) proc_desc
with _ -> () with _ -> ()

Loading…
Cancel
Save