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 10 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