From 687f4958c80319c9466c14cc7df75b5a0404a535 Mon Sep 17 00:00:00 2001 From: Andrzej Kotulski Date: Thu, 23 Jul 2015 14:40:51 -0100 Subject: [PATCH] Change procname types for objc/c functions Summary: In preparation for C++ methods, we need to have type with class, method, mangled (for overloading?) 1. Change objc method to support it 2. Do some renames to be less confusing --- infer/src/backend/localise.ml | 2 +- infer/src/backend/procname.ml | 86 +++++++++++++++++--------------- infer/src/backend/procname.mli | 17 +++---- infer/src/backend/symExec.ml | 6 +-- infer/src/checkers/checkers.ml | 2 +- infer/src/clang/cMethod_trans.ml | 4 +- infer/src/clang/cTrans.ml | 2 +- 7 files changed, 60 insertions(+), 59 deletions(-) diff --git a/infer/src/backend/localise.ml b/infer/src/backend/localise.ml index 67f791a10..2e10244e6 100644 --- a/infer/src/backend/localise.ml +++ b/infer/src/backend/localise.ml @@ -269,7 +269,7 @@ let deref_str_nullable proc_name_opt nullable_obj_str = let deref_str_nil_argument_in_variadic_method pn total_args arg_number = let tags = Tags.create () in let function_method, nil_null = - if Procname.is_objc pn then ("method", "nil") else ("function", "null") in + if Procname.is_c_method pn then ("method", "nil") else ("function", "null") in let problem_str = Printf.sprintf "could be %s which results in a call to %s with %d arguments instead of %d \ diff --git a/infer/src/backend/procname.ml b/infer/src/backend/procname.ml index d1f610688..b0829ab0c 100644 --- a/infer/src/backend/procname.ml +++ b/infer/src/backend/procname.ml @@ -30,16 +30,18 @@ type java_signature = { kind: method_kind } -type objc_signature = { - objc_class : string; - objc_method: string; +(* C++/ObjC method signature *) +type c_method_signature = { + class_name: string; + method_name: string; + mangled: string option; } type t = | JAVA of java_signature - | C_CPP of string * (string option) (* it is a pair (plain, mangled optional) *) + | C_FUNCTION of string * (string option) (* it is a pair (plain, mangled optional) *) | STATIC of string * (string option) (* it is a pair (plain name, filename optional) *) - | OBJC of objc_signature + | C_METHOD of c_method_signature | OBJC_BLOCK of string (* Defines the level of verbosity of some to_string functions *) @@ -115,20 +117,18 @@ let java_sig_compare js1 js2 = |> next java_return_type_compare js1.returntype js2.returntype |> next method_kind_compare js1.kind js2.kind -(** Compare objc signatures. *) -let objc_sig_compare osig1 osig2 = - let n = string_compare osig1.objc_class osig2.objc_class in - if n <> 0 then n else string_compare osig1.objc_method osig2.objc_method +(** Compare c_method signatures. *) +let c_meth_sig_compare osig1 osig2 = + let n = string_compare osig1.class_name osig2.class_name in + if n <> 0 then n else string_compare osig1.method_name osig2.method_name (** Given a package.classname string, it looks for the latest dot and split the string in two (package, classname) *) let split_classname package_classname = string_split_character package_classname '.' -let from_string (s: string) = C_CPP (s, None) +let from_string (s: string) = C_FUNCTION (s, None) -let empty = C_CPP ("", None) - -let mangled_cpp (plain: string) (mangled: string) = C_CPP (plain, Some mangled) +let mangled_c_fun (plain: string) (mangled: string) = C_FUNCTION (plain, Some mangled) (** Create a static procedure name from a plain name and source file *) let mangled_static (plain: string) (source_file: DB.source_file) = @@ -147,10 +147,11 @@ let mangled_java class_name ret_type method_name params _kind = } (** Create an objc procedure name from a class_name and method_name. *) -let mangled_objc objc_class objc_method = - OBJC { - objc_class = objc_class; - objc_method = objc_method; +let mangled_c_method class_name method_name mangled = + C_METHOD { + class_name = class_name; + method_name = method_name; + mangled = mangled; } (** Create an objc procedure name from a class_name and method_name. *) @@ -161,8 +162,8 @@ let is_java = function | JAVA _ -> true | _ -> false -let is_objc = function - | OBJC _ -> true +let is_c_method = function + | C_METHOD _ -> true | _ -> false (** Replace package and classname of a java procname. *) @@ -172,9 +173,9 @@ let java_replace_class p package_classname = | _ -> assert false (** Replace the class name of an objc procedure name. *) -let objc_replace_class t objc_class = +let c_method_replace_class t class_name = match t with - | OBJC osig -> OBJC { osig with objc_class = objc_class } + | C_METHOD osig -> C_METHOD { osig with class_name = class_name } | _ -> assert false (** Return the package.classname of a java procname. *) @@ -205,10 +206,10 @@ let java_replace_return_type p ret_type = match p with | JAVA p -> JAVA { p with returntype = Some ret_type } | _ -> assert false -(** Return the method of a objc procname. *) -let clang_get_method = function - | OBJC name -> name.objc_method - | C_CPP (name, _) -> name +(** Return the method of a objc/c++ procname. *) +let c_get_method = function + | C_METHOD name -> name.method_name + | C_FUNCTION (name, _) -> name | OBJC_BLOCK name -> name | _ -> assert false @@ -317,7 +318,7 @@ let java_is_vararg = function (** [is_constructor pname] returns true if [pname] is a constructor *) let is_constructor = function | JAVA js -> js.methodname = "" - | OBJC name -> Utils.string_is_prefix "init" name.objc_method + | C_METHOD name -> Utils.string_is_prefix "init" name.method_name | _ -> false @@ -340,7 +341,7 @@ let is_infer_undefined pn = match pn with (* TODO: add cases for obj-c, c, c++ *) false -(** to_string for C_CPP and STATIC types *) +(** to_string for C_FUNCTION and STATIC types *) let to_readable_string (c1, c2) verbose = let plain = c1 in if verbose then @@ -350,38 +351,41 @@ let to_readable_string (c1, c2) verbose = else plain -let objc_to_string osig detail_level = +let c_method_to_string osig detail_level = match detail_level with | SIMPLE -> - osig.objc_method + osig.method_name | VERBOSE | NON_VERBOSE -> - osig.objc_class ^ "_" ^ osig.objc_method + let m_str = match osig.mangled with + | None -> "" + | Some s -> "{" ^ s ^ "}" in + osig.class_name ^ "_" ^ osig.method_name ^ m_str (** Very verbose representation of an existing Procname.t *) let to_unique_id pn = match pn with | JAVA j -> java_to_string j VERBOSE - | C_CPP (c1, c2) -> to_readable_string (c1, c2) true + | C_FUNCTION (c1, c2) -> to_readable_string (c1, c2) true | STATIC (s1, s2) -> to_readable_string (s1, s2) true - | OBJC osig -> objc_to_string osig VERBOSE + | C_METHOD osig -> c_method_to_string osig VERBOSE | OBJC_BLOCK name -> name (** Convert a proc name to a string for the user to see *) let to_string p = match p with | JAVA j -> (java_to_string j NON_VERBOSE) - | C_CPP (c1, c2) | STATIC (c1, c2) -> + | C_FUNCTION (c1, c2) | STATIC (c1, c2) -> to_readable_string (c1, c2) false - | OBJC osig -> objc_to_string osig NON_VERBOSE + | C_METHOD osig -> c_method_to_string osig NON_VERBOSE | OBJC_BLOCK name -> name (** Convenient representation of a procname for external tools (e.g. eclipse plugin) *) let to_simplified_string ?withclass: (wc = false) p = match p with | JAVA j -> (java_to_string ~withclass: wc j SIMPLE) - | C_CPP (c1, c2) | STATIC (c1, c2) -> + | C_FUNCTION (c1, c2) | STATIC (c1, c2) -> to_readable_string (c1, c2) false ^ "()" - | OBJC osig -> objc_to_string osig SIMPLE + | C_METHOD osig -> c_method_to_string osig SIMPLE | OBJC_BLOCK name -> "block" (** Convert a proc name to a filename *) @@ -400,16 +404,16 @@ let pp f pn = (** Compare function for Procname.t types *) (* These rules create an ordered set of procnames grouped with the following priority (lowest to highest): *) -(* JAVA, C_CPP, STATIC, OBJC *) +(* JAVA, C_FUNCTION, STATIC, OBJC *) let compare pn1 pn2 = match pn1, pn2 with | JAVA j1, JAVA j2 -> java_sig_compare j1 j2 | JAVA _, _ -> -1 | _, JAVA _ -> 1 - | C_CPP (c1, c2), C_CPP (c3, c4) -> (* Compare C_CPP types *) + | C_FUNCTION (c1, c2), C_FUNCTION (c3, c4) -> (* Compare C_FUNCTION types *) let n = string_compare c1 c3 in if n <> 0 then n else mangled_compare c2 c4 - | C_CPP _, _ -> -1 - | _, C_CPP _ -> 1 + | C_FUNCTION _, _ -> -1 + | _, C_FUNCTION _ -> 1 | STATIC (c1, c2), STATIC (c3, c4) -> (* Compare STATIC types *) let n = string_compare c1 c3 in if n <> 0 then n else mangled_compare c2 c4 @@ -419,7 +423,7 @@ let compare pn1 pn2 = match pn1, pn2 with string_compare s1 s2 | OBJC_BLOCK _, _ -> -1 | _, OBJC_BLOCK _ -> 1 - | OBJC osig1, OBJC osig2 -> objc_sig_compare osig1 osig2 + | C_METHOD osig1, C_METHOD osig2 -> c_meth_sig_compare osig1 osig2 let equal pn1 pn2 = compare pn1 pn2 = 0 diff --git a/infer/src/backend/procname.mli b/infer/src/backend/procname.mli index ac5123df7..48af4f8d6 100644 --- a/infer/src/backend/procname.mli +++ b/infer/src/backend/procname.mli @@ -31,7 +31,7 @@ val equal : t -> t -> bool val from_string : string -> t (** Create a C++ procedure name from plain and mangled name *) -val mangled_cpp : string -> string -> t +val mangled_c_fun : string -> string -> t (** Create a static procedure name from a plain name and source file *) val mangled_static : string -> DB.source_file -> t @@ -40,7 +40,7 @@ val mangled_static : string -> DB.source_file -> t val mangled_java : java_type -> java_type option -> string -> java_type list -> method_kind -> t (** Create an objc procedure name from a class_name and method_name. *) -val mangled_objc : string -> string -> t +val mangled_c_method : string -> string -> string option -> t (** Create an objc block name. *) val mangled_objc_block : string -> t @@ -48,8 +48,8 @@ val mangled_objc_block : string -> t (** Return true if this is a Java procedure name *) val is_java : t -> bool -(** Return true if this is an Objective-C procedure name *) -val is_objc : t -> bool +(** Return true if this is an Objective-C/C++ method name *) +val is_c_method : t -> bool (** Replace package and classname of a java procname. *) val java_replace_class : t -> string -> t @@ -61,7 +61,7 @@ val java_replace_method : t -> string -> t val java_replace_return_type : t -> java_type -> t (** Replace the class name of an Objective-C procedure name. *) -val objc_replace_class : t -> string -> t +val c_method_replace_class : t -> string -> t (** Return the class name of a java procedure name. *) val java_get_class : t -> string @@ -72,8 +72,8 @@ val java_get_simple_class : t -> string (** Return the method name of a java procedure name. *) val java_get_method : t -> string -(** Return the method name of a objc procedure name. *) -val clang_get_method : t -> string +(** Return the method of a objc/c++ procname. *) +val c_get_method : t -> string (** Replace the method name of an existing java procname. *) val java_replace_method : t -> string -> t @@ -133,9 +133,6 @@ val to_unique_id : t -> string (** Convert a proc name to a filename *) val to_filename : t -> string -(** empty proc name *) -val empty : t - (** Pretty print a proc name *) val pp : Format.formatter -> t -> unit diff --git a/infer/src/backend/symExec.ml b/infer/src/backend/symExec.ml index a28eefcd7..9e17cd955 100644 --- a/infer/src/backend/symExec.ml +++ b/infer/src/backend/symExec.ml @@ -672,7 +672,7 @@ let resolve_method tenv class_name proc_name = let right_proc_name = if Procname.is_java proc_name then Procname.java_replace_class proc_name (Mangled.to_string class_name) - else Procname.objc_replace_class proc_name (Mangled.to_string class_name) in + else Procname.c_method_replace_class proc_name (Mangled.to_string class_name) in let type_name = Sil.TN_csu (Sil.Class, class_name) in match Sil.tenv_lookup tenv type_name with | Some (Sil.Tstruct (_, _, Sil.Class, cls, super_classes, methods, iann)) -> @@ -2322,11 +2322,11 @@ module ModelBuiltins = struct let _ = Builtin.register_procname - (Procname.mangled_objc "NSArray" "arrayWithObjects:count:") + (Procname.mangled_c_method "NSArray" "arrayWithObjects:count:" None) execute_NSArray_arrayWithObjects_count let _ = Builtin.register_procname - (Procname.mangled_objc "NSArray" "arrayWithObjects:") + (Procname.mangled_c_method "NSArray" "arrayWithObjects:" None) execute_NSArray_arrayWithObjects end (* ============== END of ModelBuiltins ============== *) diff --git a/infer/src/checkers/checkers.ml b/infer/src/checkers/checkers.ml index c786a52a1..142255234 100644 --- a/infer/src/checkers/checkers.ml +++ b/infer/src/checkers/checkers.ml @@ -478,7 +478,7 @@ let callback_check_field_access all_procs get_proc_desc idenv tenv proc_name pro let callback_print_c_method_calls all_procs get_proc_desc idenv tenv proc_name proc_desc = let do_instr node = function | Sil.Call (ret_ids, Sil.Const (Sil.Cfun pn), (e, t):: args, loc, cf) - when Procname.is_objc pn -> + when Procname.is_c_method pn -> let receiver = match Errdesc.exp_rv_dexp node e with | Some de -> Sil.dexp_to_string de | None -> "?" in diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 4c0cbbe58..6dd6dd127 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -28,10 +28,10 @@ type method_call_type = let mk_procname_from_function name type_name = let type_name_crc = CRC.crc16 type_name in - Procname.mangled_cpp name type_name_crc + Procname.mangled_c_fun name type_name_crc let mk_procname_from_method class_name method_name = - Procname.mangled_objc class_name method_name + Procname.mangled_c_method class_name method_name None let rec resolve_method_class tenv class_name method_name = let type_name = Sil.TN_csu (Sil.Class, class_name) in diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 6e3309512..3c7898b7c 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -38,7 +38,7 @@ module CTrans_funct(M: CModule_type.CMethod_declaration) : CTrans = struct let add_autorelease_call context exp typ sil_loc = - let method_name = Procname.clang_get_method (Cfg.Procdesc.get_proc_name context.procdesc) in + let method_name = Procname.c_get_method (Cfg.Procdesc.get_proc_name context.procdesc) in if !Config.arc_mode && not (CTrans_utils.is_owning_name method_name) && ObjcInterface_decl.is_pointer_to_objc_class context.CContext.tenv typ then