From 776e728b63d27a818c1a66c080a610639d99ce38 Mon Sep 17 00:00:00 2001 From: Dulma Churchill Date: Tue, 12 Jun 2018 03:17:33 -0700 Subject: [PATCH] [biabduction] Rewrite the function resolve_java_pname in SymExec for all procnames Reviewed By: jeremydubreil Differential Revision: D8334702 fbshipit-source-id: 757442a --- infer/src/IR/Typ.ml | 101 +++++++++++++++++++++++++++++-- infer/src/IR/Typ.mli | 36 ++++++----- infer/src/biabduction/SymExec.ml | 41 +++++-------- 3 files changed, 132 insertions(+), 46 deletions(-) diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index e85c762d4..7bc9b74fe 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -593,6 +593,8 @@ module Procname = struct type_to_string_verbosity head verbosity ^ "," ^ param_list_to_string rest verbosity + let java_type_of_name class_name = Name.Java.Split.of_string (Name.name class_name) + (** It is the same as java_type_to_string_verbosity, but Java return types are optional because of constructors without type *) let return_type_to_string j verbosity = @@ -734,9 +736,13 @@ module Procname = struct end module Parameter = struct - (** [Some name] means the parameter is of type pointer to struct, with [name] -being the name of the struct, [None] means the parameter is of some other type. *) - type t = Name.t option [@@deriving compare] + (** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to struct, with [name] + being the name of the struct, [None] means the parameter is of some other type. *) + type clang_parameter = Name.t option [@@deriving compare] + + (** Type for parameters in procnames, for java and clang. *) + type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter + [@@deriving compare] let of_typ typ = match typ.T.desc with T.Tptr ({desc= Tstruct name}, Pk_pointer) -> Some name | _ -> None @@ -748,6 +754,9 @@ being the name of the struct, [None] means the parameter is of some other type. in let string_pars = List.map ~f:name_opt_to_string parameters in if List.is_empty parameters then "" else "(" ^ String.concat ~sep:"," string_pars ^ ")" + + + let clang_param_of_name class_name : clang_parameter = Some class_name end module ObjC_Cpp = struct @@ -764,7 +773,7 @@ being the name of the struct, [None] means the parameter is of some other type. { class_name: Name.t ; kind: kind ; method_name: string - ; parameters: Parameter.t list + ; parameters: Parameter.clang_parameter list ; template_args: template_spec_info } [@@deriving compare] @@ -839,6 +848,11 @@ being the name of the struct, [None] means the parameter is of some other type. let m_str = kind_to_verbose_string osig.kind in Name.name osig.class_name ^ "_" ^ osig.method_name ^ Parameter.parameters_to_string osig.parameters ^ m_str + + + let get_parameters osig = osig.parameters + + let replace_parameters new_parameters osig = {osig with parameters= new_parameters} end module C = struct @@ -846,7 +860,7 @@ being the name of the struct, [None] means the parameter is of some other type. type t = { name: QualifiedCppName.t ; mangled: string option - ; parameters: Parameter.t list + ; parameters: Parameter.clang_parameter list ; template_args: template_spec_info } [@@deriving compare] @@ -875,13 +889,18 @@ being the name of the struct, [None] means the parameter is of some other type. plain ^ Parameter.parameters_to_string parameters | Some s -> plain ^ Parameter.parameters_to_string parameters ^ "{" ^ s ^ "}" + + + let get_parameters c = c.parameters + + let replace_parameters new_parameters c = {c with parameters= new_parameters} end module Block = struct (** Type of Objective C block names. *) type block_name = string [@@deriving compare] - type t = {name: block_name; parameters: Parameter.t list} [@@deriving compare] + type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare] let make name parameters = {name; parameters} @@ -893,6 +912,11 @@ being the name of the struct, [None] means the parameter is of some other type. bsig.name | Verbose -> bsig.name ^ Parameter.parameters_to_string bsig.parameters + + + let get_parameters block = block.parameters + + let replace_parameters new_parameters block = {block with parameters= new_parameters} end (** Type of procedure names. *) @@ -1107,6 +1131,71 @@ being the name of the struct, [None] means the parameter is of some other type. to_simplified_string ~withclass:true p + let rec get_parameters procname = + let clang_param_to_param clang_params = + List.map ~f:(fun par -> Parameter.ClangParameter par) clang_params + in + match procname with + | Java j -> + List.map ~f:(fun par -> Parameter.JavaParameter par) (Java.get_parameters j) + | C osig -> + clang_param_to_param (C.get_parameters osig) + | ObjC_Cpp osig -> + clang_param_to_param (ObjC_Cpp.get_parameters osig) + | Block bsig -> + clang_param_to_param (Block.get_parameters bsig) + | WithBlockParameters (base, _) -> + get_parameters base + | Linters_dummy_method -> + [] + + + let rec replace_parameters new_parameters procname = + let params_to_java_params params = + List.map + ~f:(fun param -> + match param with + | Parameter.JavaParameter par -> + par + | _ -> + Logging.(die InternalError) + "Expected Java parameters in Java procname, but got Clang parameters" params ) + params + in + let params_to_clang_params params = + List.map + ~f:(fun param -> + match param with + | Parameter.ClangParameter par -> + par + | _ -> + Logging.(die InternalError) + "Expected Clang parameters in Clang procname, but got Java parameters" params ) + params + in + match procname with + | Java j -> + Java (Java.replace_parameters (params_to_java_params new_parameters) j) + | C osig -> + C (C.replace_parameters (params_to_clang_params new_parameters) osig) + | ObjC_Cpp osig -> + ObjC_Cpp (ObjC_Cpp.replace_parameters (params_to_clang_params new_parameters) osig) + | Block bsig -> + Block (Block.replace_parameters (params_to_clang_params new_parameters) bsig) + | WithBlockParameters (base, blocks) -> + WithBlockParameters (replace_parameters new_parameters base, blocks) + | Linters_dummy_method -> + procname + + + let parameter_of_name procname class_name = + match procname with + | Java _ -> + Parameter.JavaParameter (Java.java_type_of_name class_name) + | _ -> + Parameter.ClangParameter (Parameter.clang_param_of_name class_name) + + (** Pretty print a proc name *) let pp f pn = F.pp_print_string f (to_string pn) diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 8a8c4e79b..9c6070713 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -162,10 +162,6 @@ module Name : sig val make : ?package:string -> string -> t - val of_string : string -> t - (** Given a package.class_name string, look for the latest dot and split the string - in two (package, class_name). *) - val java_lang_object : t val java_lang_string : t @@ -365,11 +361,15 @@ module Procname : sig end module Parameter : sig - (** [Some name] means the parameter is of type pointer to struct, with [name] - being the name of the struct, [None] means the parameter is of some other type. *) - type t = Name.t option + (** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to struct, with [name] +being the name of the struct, [None] means the parameter is of some other type. *) + type clang_parameter = Name.t option [@@deriving compare] + + (** Type for parameters in procnames, for java and clang. *) + type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter + [@@deriving compare] - val of_typ : typ -> t + val of_typ : typ -> clang_parameter end module ObjC_Cpp : sig @@ -387,11 +387,12 @@ module Procname : sig { class_name: Name.t ; kind: kind ; method_name: string - ; parameters: Parameter.t list + ; parameters: Parameter.clang_parameter list ; template_args: template_spec_info } [@@deriving compare] - val make : Name.t -> string -> kind -> template_spec_info -> Parameter.t list -> t + val make : + Name.t -> string -> kind -> template_spec_info -> Parameter.clang_parameter list -> t (** Create an objc procedure name from a class_name and method_name. *) val get_class_name : t -> string @@ -430,10 +431,11 @@ module Procname : sig type t = private { name: QualifiedCppName.t ; mangled: string option - ; parameters: Parameter.t list + ; parameters: Parameter.clang_parameter list ; template_args: template_spec_info } - val c : QualifiedCppName.t -> string -> Parameter.t list -> template_spec_info -> t + val c : + QualifiedCppName.t -> string -> Parameter.clang_parameter list -> template_spec_info -> t (** Create a C procedure name from plain and mangled name. *) end @@ -441,9 +443,9 @@ module Procname : sig (** Type of Objective C block names. *) type block_name = string - type t = {name: block_name; parameters: Parameter.t list} [@@deriving compare] + type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare] - val make : block_name -> Parameter.t list -> t + val make : block_name -> Parameter.clang_parameter list -> t end (** Type of procedure names. @@ -465,6 +467,12 @@ module Procname : sig val equal : t -> t -> bool + val get_parameters : t -> Parameter.t list + + val replace_parameters : Parameter.t list -> t -> t + + val parameter_of_name : t -> Name.t -> Parameter.t + (** Hash tables with proc names as keys. *) module Hash : Caml.Hashtbl.S with type key = t diff --git a/infer/src/biabduction/SymExec.ml b/infer/src/biabduction/SymExec.ml index 8e71ca476..f699d33aa 100644 --- a/infer/src/biabduction/SymExec.ml +++ b/infer/src/biabduction/SymExec.ml @@ -624,53 +624,48 @@ let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Typ.Procna (** Resolve the name of the procedure to call based on the type of the arguments *) -let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.Java.t = - let resolve_from_args resolved_pname_java args = +let resolve_pname tenv prop args pname call_flags : Typ.Procname.t = + let resolve_from_args resolved_pname args = let resolved_params = List.fold2_exn ~f:(fun accu (arg_exp, _) name -> match resolve_typename prop arg_exp with | Some class_name -> - Typ.Name.Java.Split.of_string (Typ.Name.name class_name) :: accu + Typ.Procname.parameter_of_name resolved_pname class_name :: accu | None -> name :: accu ) ~init:[] args - (Typ.Procname.Java.get_parameters resolved_pname_java) + (Typ.Procname.get_parameters resolved_pname) |> List.rev in - Typ.Procname.Java.replace_parameters resolved_params resolved_pname_java + Typ.Procname.replace_parameters resolved_params resolved_pname in - let resolved_pname_java, other_args = - let pname = Typ.Procname.Java pname_java - and parameters = Typ.Procname.Java.get_parameters pname_java in + let resolved_pname, other_args = + let parameters = Typ.Procname.get_parameters pname in let match_parameters args = Int.equal (List.length args) (List.length parameters) in match args with | [] -> - (pname_java, []) + (pname, []) | (first_arg, _) :: other_args when call_flags.CallFlags.cf_virtual -> let resolved = match resolve_typename prop first_arg with - | Some class_name -> ( - match resolve_method tenv class_name pname with - | Typ.Procname.Java resolved_pname_java -> - resolved_pname_java - | _ -> - pname_java ) + | Some class_name -> + resolve_method tenv class_name pname | None -> - pname_java + pname in (resolved, other_args) | _ :: other_args when match_parameters other_args (* Non-virtual call, e.g. constructors or private methods *) -> - (pname_java, other_args) + (pname, other_args) | args when match_parameters args (* Static call *) -> - (pname_java, args) + (pname, args) | args -> L.(die InternalError) "Call mismatch: method %a has %i paramters but is called with %i arguments@." Typ.Procname.pp pname (List.length parameters) (List.length args) in - resolve_from_args resolved_pname_java other_args + resolve_from_args resolved_pname other_args (** Resolve the procedure name and run the analysis of the resolved procedure @@ -697,13 +692,7 @@ let resolve_and_analyze tenv ~caller_pdesc prop args callee_proc_name call_flags in Option.bind resolved_proc_desc_option ~f:analyze in - let resolved_pname = - match callee_proc_name with - | Typ.Procname.Java callee_proc_name_java -> - Typ.Procname.Java (resolve_java_pname tenv prop args callee_proc_name_java call_flags) - | _ -> - callee_proc_name - in + let resolved_pname = resolve_pname tenv prop args callee_proc_name call_flags in (resolved_pname, analyze_ondemand resolved_pname)