get_vararg_type_names: refactor to prepare for new instrs

Summary:
Preparing for the future change, we won't see instructions as lists but as an abstract type.
This change may be a very minor perf regression: does a few more (but bounded by a constant) instructions traversals only for the nodes involving a Printf-like function call, only for the PrintfArgs checker...

Reviewed By: jvillard

Differential Revision: D8094124

fbshipit-source-id: e2e2c5e
master
Mehdi Bouaziz 7 years ago committed by Facebook Github Bot
parent 42b3958a07
commit 3a41f50830

@ -116,66 +116,76 @@ let java_get_const_type_name (const: Const.t) : string =
let get_vararg_type_names tenv (call_node: Procdesc.Node.t) (ivar: Pvar.t) : string list = let get_vararg_type_names tenv (call_node: Procdesc.Node.t) (ivar: Pvar.t) : string list =
(* Is this the node creating ivar? *) (* Is this the node creating ivar? *)
let rec initializes_array instrs = let initializes_array instrs =
match instrs with instrs
| Sil.Call ((t1, _), Exp.Const (Const.Cfun pn), _, _, _) |> List.find_map ~f:(function
:: Sil.Store (Exp.Lvar iv, _, Exp.Var t2, _) :: is -> | Sil.Store (Exp.Lvar iv, _, Exp.Var t2, _) when Pvar.equal ivar iv ->
Pvar.equal ivar iv && Ident.equal t1 t2 Some t2
&& Typ.Procname.equal pn (Typ.Procname.from_string_c_fun "__new_array") | _ ->
|| initializes_array is None )
| _ :: is -> |> Option.exists ~f:(fun t2 ->
initializes_array is List.exists instrs ~f:(function
| _ -> | Sil.Call ((t1, _), Exp.Const (Const.Cfun pn), _, _, _) ->
false Ident.equal t1 t2
&& Typ.Procname.equal pn (Typ.Procname.from_string_c_fun "__new_array")
| _ ->
false ) )
in in
(* Get the type name added to ivar or None *) (* Get the type name added to ivar or None *)
let added_type_name node = let added_type_name instrs =
let rec nvar_type_name nvar instrs = let nvar_type_name nvar =
match instrs with instrs
| Sil.Load (nv, Exp.Lfield (_, id, t), _, _) :: _ when Ident.equal nv nvar -> |> List.find_map ~f:(function
get_field_type_name tenv t id | Sil.Load (nv, e, t, _) when Ident.equal nv nvar ->
| Sil.Load (nv, _, t, _) :: _ when Ident.equal nv nvar -> Some (e, t)
Some (get_type_name t) | _ ->
| _ :: is -> None )
nvar_type_name nvar is |> Option.bind ~f:(function
| _ -> | Exp.Lfield (_, id, t), _ ->
None get_field_type_name tenv t id
| _, t ->
Some (get_type_name t) )
in in
let rec added_nvar array_nvar instrs = let added_nvar array_nvar =
match instrs with instrs
| Sil.Store (Exp.Lindex (Exp.Var iv, _), _, Exp.Var nvar, _) :: _ |> List.find_map ~f:(function
when Ident.equal iv array_nvar -> | Sil.Store (Exp.Lindex (Exp.Var iv, _), _, Exp.Var nvar, _)
nvar_type_name nvar (Procdesc.Node.get_instrs node) when Ident.equal iv array_nvar ->
| Sil.Store (Exp.Lindex (Exp.Var iv, _), _, Exp.Const c, _) :: _ Some (nvar_type_name nvar)
when Ident.equal iv array_nvar -> | Sil.Store (Exp.Lindex (Exp.Var iv, _), _, Exp.Const c, _)
Some (java_get_const_type_name c) when Ident.equal iv array_nvar ->
| _ :: is -> Some (Some (java_get_const_type_name c))
added_nvar array_nvar is | _ ->
| _ -> None )
None |> Option.join
in in
let rec array_nvar instrs = let array_nvar =
match instrs with instrs
| Sil.Load (nv, Exp.Lvar iv, _, _) :: _ when Pvar.equal iv ivar -> |> List.find_map ~f:(function
added_nvar nv instrs | Sil.Load (nv, Exp.Lvar iv, _, _) when Pvar.equal iv ivar ->
| _ :: is -> Some nv
array_nvar is | _ ->
| _ -> None )
None |> Option.bind ~f:added_nvar
in in
array_nvar (Procdesc.Node.get_instrs node) array_nvar
in in
(* Walk nodes backward until definition of ivar, adding type names *) (* Walk nodes backward until definition of ivar, adding type names *)
let rec type_names node = let rec type_names acc node =
if initializes_array (Procdesc.Node.get_instrs node) then [] let instrs = Procdesc.Node.get_instrs node in
if initializes_array instrs then acc
else else
match Procdesc.Node.get_preds node with match Procdesc.Node.get_preds node with
| [n] -> ( | [n] -> (
match added_type_name node with Some name -> name :: type_names n | None -> type_names n ) match added_type_name instrs with
| Some name ->
type_names (name :: acc) n
| None ->
type_names acc n )
| _ -> | _ ->
raise Caml.Not_found raise Caml.Not_found
in in
List.rev (type_names call_node) type_names [] call_node
let is_getter pname_java = let is_getter pname_java =

@ -136,25 +136,25 @@ let check_printf_args_ok tenv (node: Procdesc.Node.t) (instr: Sil.instr)
Reporting.log_error summary ~loc:instr_loc exn Reporting.log_error summary ~loc:instr_loc exn
in in
(* Get the array ivar for a given nvar *) (* Get the array ivar for a given nvar *)
let rec array_ivar instrs nvar = let array_ivar instrs nvar =
match (instrs, nvar) with match nvar with
| Sil.Load (id, Exp.Lvar iv, _, _) :: _, Exp.Var nid when Ident.equal id nid -> | Exp.Var nid ->
iv List.find_map_exn instrs ~f:(function
| _ :: is, _ -> | Sil.Load (id, Exp.Lvar iv, _, _) when Ident.equal id nid ->
array_ivar is nvar Some iv
| _ ->
None )
| _ -> | _ ->
raise Caml.Not_found raise Caml.Not_found
in in
let rec fixed_nvar_type_name instrs nvar = let fixed_nvar_type_name instrs nvar =
match nvar with match nvar with
| Exp.Var nid -> ( | Exp.Var nid ->
match instrs with List.find_map_exn instrs ~f:(function
| Sil.Load (id, Exp.Lvar _, t, _) :: _ when Ident.equal id nid -> | Sil.Load (id, Exp.Lvar _, t, _) when Ident.equal id nid ->
PatternMatch.get_type_name t Some (PatternMatch.get_type_name t)
| _ :: is -> | _ ->
fixed_nvar_type_name is nvar None )
| _ ->
raise Caml.Not_found )
| Exp.Const c -> | Exp.Const c ->
PatternMatch.java_get_const_type_name c PatternMatch.java_get_const_type_name c
| _ -> | _ ->

Loading…
Cancel
Save