From f963363ee99033f29800319fbc750da29ee9d27d Mon Sep 17 00:00:00 2001 From: Jeremy Dubreil Date: Tue, 20 Dec 2016 12:10:10 -0800 Subject: [PATCH] [infer][java] For the lazy dynamic dispatch algorithm, only specialize the methods on object parameters Summary: The specialization of the methods based on the type of the arguments should only be performed when the type is an object type. This should in theory be always the case according to the Java semantics but the previous version of the code was relying on Infer to be correct all the way down the the method call: Before this diff, the analysis on examples like this: String foo(Object object) { object.toString(); } String bar() { int[] array = {1, 2, 3}; foo(array); } This is a legit code that Infer is getting wrong because Java objects are translated as C objects instead of objects containing a C-style object. There may be other issues like this so it is safer to filter out the types when performing the substitution. Reviewed By: jberdine Differential Revision: D4345760 fbshipit-source-id: 1c74593 --- infer/src/IR/Cfg.re | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/infer/src/IR/Cfg.re b/infer/src/IR/Cfg.re index 2e47f5170..5b25841b5 100644 --- a/infer/src/IR/Cfg.re +++ b/infer/src/IR/Cfg.re @@ -338,7 +338,7 @@ let store_cfg_to_file source_file::source_file (filename: DB.filename) (cfg: cfg /** clone a procedure description and apply the type substitutions where the parameters are used */ -let specialize_types_proc callee_pdesc resolved_pdesc substitutions => { +let specialize_types_proc callee_pdesc resolved_pdesc resolved_formals => { let resolved_pname = Procdesc.get_proc_name resolved_pdesc and callee_start_node = Procdesc.get_start_node callee_pdesc and callee_exit_node = Procdesc.get_exit_node callee_pdesc; @@ -361,7 +361,7 @@ let specialize_types_proc callee_pdesc resolved_pdesc substitutions => { | Sil.Load id (Exp.Lvar origin_pvar as origin_exp) origin_typ loc => { let (_, specialized_typ) = { let pvar_name = Pvar.get_name origin_pvar; - try (IList.find (fun (n, _) => Mangled.equal n pvar_name) substitutions) { + try (IList.find (fun (n, _) => Mangled.equal n pvar_name) resolved_formals) { | Not_found => (pvar_name, origin_typ) } }; @@ -468,15 +468,20 @@ let specialize_types_proc callee_pdesc resolved_pdesc substitutions => { all the type of the parameters are replaced in the instructions according to the list. The virtual calls are also replaced to match the parameter types */ let specialize_types callee_pdesc resolved_pname args => { - /* TODO (#9333890): This currently only works when the callee is defined in the same file. - Add support to search for the callee procedure description in the execution environment */ let callee_attributes = Procdesc.get_attributes callee_pdesc; let resolved_formals = - IList.fold_left2 - (fun accu (name, _) (_, arg_typ) => [(name, arg_typ), ...accu]) - [] + IList.map2 + ( + fun (param_name, param_typ) (_, arg_typ) => + switch arg_typ { + | Typ.Tptr (Tstruct _) _ => + /* Replace the type of the parameter by the type of the argument */ + (param_name, arg_typ) + | _ => (param_name, param_typ) + } + ) callee_attributes.formals - args |> IList.rev; + args; let resolved_attributes = { ...callee_attributes, formals: resolved_formals,