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
master
Andrzej Kotulski 9 years ago
parent 35b7011f81
commit 687f4958c8

@ -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 deref_str_nil_argument_in_variadic_method pn total_args arg_number =
let tags = Tags.create () in let tags = Tags.create () in
let function_method, nil_null = 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 = let problem_str =
Printf.sprintf Printf.sprintf
"could be %s which results in a call to %s with %d arguments instead of %d \ "could be %s which results in a call to %s with %d arguments instead of %d \

@ -30,16 +30,18 @@ type java_signature = {
kind: method_kind kind: method_kind
} }
type objc_signature = { (* C++/ObjC method signature *)
objc_class : string; type c_method_signature = {
objc_method: string; class_name: string;
method_name: string;
mangled: string option;
} }
type t = type t =
| JAVA of java_signature | 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) *) | 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 | OBJC_BLOCK of string
(* Defines the level of verbosity of some to_string functions *) (* 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 java_return_type_compare js1.returntype js2.returntype
|> next method_kind_compare js1.kind js2.kind |> next method_kind_compare js1.kind js2.kind
(** Compare objc signatures. *) (** Compare c_method signatures. *)
let objc_sig_compare osig1 osig2 = let c_meth_sig_compare osig1 osig2 =
let n = string_compare osig1.objc_class osig2.objc_class in let n = string_compare osig1.class_name osig2.class_name in
if n <> 0 then n else string_compare osig1.objc_method osig2.objc_method 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) *) (** Given a package.classname string, it looks for the latest dot and split the string in two (package, classname) *)
let split_classname package_classname = let split_classname package_classname =
string_split_character 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_c_fun (plain: string) (mangled: string) = C_FUNCTION (plain, Some mangled)
let mangled_cpp (plain: string) (mangled: string) = C_CPP (plain, Some mangled)
(** Create a static procedure name from a plain name and source file *) (** Create a static procedure name from a plain name and source file *)
let mangled_static (plain: string) (source_file: DB.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. *) (** Create an objc procedure name from a class_name and method_name. *)
let mangled_objc objc_class objc_method = let mangled_c_method class_name method_name mangled =
OBJC { C_METHOD {
objc_class = objc_class; class_name = class_name;
objc_method = objc_method; method_name = method_name;
mangled = mangled;
} }
(** Create an objc procedure name from a class_name and method_name. *) (** Create an objc procedure name from a class_name and method_name. *)
@ -161,8 +162,8 @@ let is_java = function
| JAVA _ -> true | JAVA _ -> true
| _ -> false | _ -> false
let is_objc = function let is_c_method = function
| OBJC _ -> true | C_METHOD _ -> true
| _ -> false | _ -> false
(** Replace package and classname of a java procname. *) (** Replace package and classname of a java procname. *)
@ -172,9 +173,9 @@ let java_replace_class p package_classname =
| _ -> assert false | _ -> assert false
(** Replace the class name of an objc procedure name. *) (** 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 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 | _ -> assert false
(** Return the package.classname of a java procname. *) (** 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 } | JAVA p -> JAVA { p with returntype = Some ret_type }
| _ -> assert false | _ -> assert false
(** Return the method of a objc procname. *) (** Return the method of a objc/c++ procname. *)
let clang_get_method = function let c_get_method = function
| OBJC name -> name.objc_method | C_METHOD name -> name.method_name
| C_CPP (name, _) -> name | C_FUNCTION (name, _) -> name
| OBJC_BLOCK name -> name | OBJC_BLOCK name -> name
| _ -> assert false | _ -> assert false
@ -317,7 +318,7 @@ let java_is_vararg = function
(** [is_constructor pname] returns true if [pname] is a constructor *) (** [is_constructor pname] returns true if [pname] is a constructor *)
let is_constructor = function let is_constructor = function
| JAVA js -> js.methodname = "<init>" | JAVA js -> js.methodname = "<init>"
| OBJC name -> Utils.string_is_prefix "init" name.objc_method | C_METHOD name -> Utils.string_is_prefix "init" name.method_name
| _ -> false | _ -> false
@ -340,7 +341,7 @@ let is_infer_undefined pn = match pn with
(* TODO: add cases for obj-c, c, c++ *) (* TODO: add cases for obj-c, c, c++ *)
false 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 to_readable_string (c1, c2) verbose =
let plain = c1 in let plain = c1 in
if verbose then if verbose then
@ -350,38 +351,41 @@ let to_readable_string (c1, c2) verbose =
else else
plain plain
let objc_to_string osig detail_level = let c_method_to_string osig detail_level =
match detail_level with match detail_level with
| SIMPLE -> | SIMPLE ->
osig.objc_method osig.method_name
| VERBOSE | NON_VERBOSE -> | 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 *) (** Very verbose representation of an existing Procname.t *)
let to_unique_id pn = let to_unique_id pn =
match pn with match pn with
| JAVA j -> java_to_string j VERBOSE | 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 | 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 | OBJC_BLOCK name -> name
(** Convert a proc name to a string for the user to see *) (** Convert a proc name to a string for the user to see *)
let to_string p = let to_string p =
match p with match p with
| JAVA j -> (java_to_string j NON_VERBOSE) | 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 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 | OBJC_BLOCK name -> name
(** Convenient representation of a procname for external tools (e.g. eclipse plugin) *) (** Convenient representation of a procname for external tools (e.g. eclipse plugin) *)
let to_simplified_string ?withclass: (wc = false) p = let to_simplified_string ?withclass: (wc = false) p =
match p with match p with
| JAVA j -> (java_to_string ~withclass: wc j SIMPLE) | 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 ^ "()" 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" | OBJC_BLOCK name -> "block"
(** Convert a proc name to a filename *) (** Convert a proc name to a filename *)
@ -400,16 +404,16 @@ let pp f pn =
(** Compare function for Procname.t types *) (** Compare function for Procname.t types *)
(* These rules create an ordered set of procnames grouped with the following priority (lowest to highest): *) (* 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 let compare pn1 pn2 = match pn1, pn2 with
| JAVA j1, JAVA j2 -> java_sig_compare j1 j2 | JAVA j1, JAVA j2 -> java_sig_compare j1 j2
| JAVA _, _ -> -1 | JAVA _, _ -> -1
| _, 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 let n = string_compare c1 c3 in
if n <> 0 then n else mangled_compare c2 c4 if n <> 0 then n else mangled_compare c2 c4
| C_CPP _, _ -> -1 | C_FUNCTION _, _ -> -1
| _, C_CPP _ -> 1 | _, C_FUNCTION _ -> 1
| STATIC (c1, c2), STATIC (c3, c4) -> (* Compare STATIC types *) | STATIC (c1, c2), STATIC (c3, c4) -> (* Compare STATIC types *)
let n = string_compare c1 c3 in let n = string_compare c1 c3 in
if n <> 0 then n else mangled_compare c2 c4 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 string_compare s1 s2
| OBJC_BLOCK _, _ -> -1 | OBJC_BLOCK _, _ -> -1
| _, 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 = let equal pn1 pn2 =
compare pn1 pn2 = 0 compare pn1 pn2 = 0

@ -31,7 +31,7 @@ val equal : t -> t -> bool
val from_string : string -> t val from_string : string -> t
(** Create a C++ procedure name from plain and mangled name *) (** 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 *) (** Create a static procedure name from a plain name and source file *)
val mangled_static : string -> DB.source_file -> t 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 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. *) (** 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. *) (** Create an objc block name. *)
val mangled_objc_block : string -> t 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 *) (** Return true if this is a Java procedure name *)
val is_java : t -> bool val is_java : t -> bool
(** Return true if this is an Objective-C procedure name *) (** Return true if this is an Objective-C/C++ method name *)
val is_objc : t -> bool val is_c_method : t -> bool
(** Replace package and classname of a java procname. *) (** Replace package and classname of a java procname. *)
val java_replace_class : t -> string -> t 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 val java_replace_return_type : t -> java_type -> t
(** Replace the class name of an Objective-C procedure name. *) (** 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. *) (** Return the class name of a java procedure name. *)
val java_get_class : t -> string 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. *) (** Return the method name of a java procedure name. *)
val java_get_method : t -> string val java_get_method : t -> string
(** Return the method name of a objc procedure name. *) (** Return the method of a objc/c++ procname. *)
val clang_get_method : t -> string val c_get_method : t -> string
(** Replace the method name of an existing java procname. *) (** Replace the method name of an existing java procname. *)
val java_replace_method : t -> string -> t val java_replace_method : t -> string -> t
@ -133,9 +133,6 @@ val to_unique_id : t -> string
(** Convert a proc name to a filename *) (** Convert a proc name to a filename *)
val to_filename : t -> string val to_filename : t -> string
(** empty proc name *)
val empty : t
(** Pretty print a proc name *) (** Pretty print a proc name *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit

@ -672,7 +672,7 @@ let resolve_method tenv class_name proc_name =
let right_proc_name = let right_proc_name =
if Procname.is_java proc_name then if Procname.is_java proc_name then
Procname.java_replace_class proc_name (Mangled.to_string class_name) 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 let type_name = Sil.TN_csu (Sil.Class, class_name) in
match Sil.tenv_lookup tenv type_name with match Sil.tenv_lookup tenv type_name with
| Some (Sil.Tstruct (_, _, Sil.Class, cls, super_classes, methods, iann)) -> | Some (Sil.Tstruct (_, _, Sil.Class, cls, super_classes, methods, iann)) ->
@ -2322,11 +2322,11 @@ module ModelBuiltins = struct
let _ = let _ =
Builtin.register_procname Builtin.register_procname
(Procname.mangled_objc "NSArray" "arrayWithObjects:count:") (Procname.mangled_c_method "NSArray" "arrayWithObjects:count:" None)
execute_NSArray_arrayWithObjects_count execute_NSArray_arrayWithObjects_count
let _ = let _ =
Builtin.register_procname Builtin.register_procname
(Procname.mangled_objc "NSArray" "arrayWithObjects:") (Procname.mangled_c_method "NSArray" "arrayWithObjects:" None)
execute_NSArray_arrayWithObjects execute_NSArray_arrayWithObjects
end end
(* ============== END of ModelBuiltins ============== *) (* ============== END of ModelBuiltins ============== *)

@ -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 callback_print_c_method_calls all_procs get_proc_desc idenv tenv proc_name proc_desc =
let do_instr node = function let do_instr node = function
| Sil.Call (ret_ids, Sil.Const (Sil.Cfun pn), (e, t):: args, loc, cf) | 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 let receiver = match Errdesc.exp_rv_dexp node e with
| Some de -> Sil.dexp_to_string de | Some de -> Sil.dexp_to_string de
| None -> "?" in | None -> "?" in

@ -28,10 +28,10 @@ type method_call_type =
let mk_procname_from_function name type_name = let mk_procname_from_function name type_name =
let type_name_crc = CRC.crc16 type_name in 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 = 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 rec resolve_method_class tenv class_name method_name =
let type_name = Sil.TN_csu (Sil.Class, class_name) in let type_name = Sil.TN_csu (Sil.Class, class_name) in

@ -38,7 +38,7 @@ module CTrans_funct(M: CModule_type.CMethod_declaration) : CTrans =
struct struct
let add_autorelease_call context exp typ sil_loc = 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 && if !Config.arc_mode &&
not (CTrans_utils.is_owning_name method_name) && not (CTrans_utils.is_owning_name method_name) &&
ObjcInterface_decl.is_pointer_to_objc_class context.CContext.tenv typ then ObjcInterface_decl.is_pointer_to_objc_class context.CContext.tenv typ then

Loading…
Cancel
Save