[clang] Add new procname type for specializing methods with block parameters

Reviewed By: mbouaziz

Differential Revision: D6246401

fbshipit-source-id: 2aafbee
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent 5902f6363b
commit 718747e39c

@ -561,15 +561,18 @@ module Procname = struct
[@@deriving compare] [@@deriving compare]
(** Type of Objective C block names. *) (** Type of Objective C block names. *)
type block = string [@@deriving compare] type block_name = string [@@deriving compare]
let block_from_string s = s
(** Type of procedure names. *) (** Type of procedure names. *)
type t = type t =
| Java of java | Java of java
| C of c | C of c
| Linters_dummy_method | Linters_dummy_method
| Block of block | Block of block_name
| ObjC_Cpp of objc_cpp | ObjC_Cpp of objc_cpp
| WithBlockParameters of t * block_name list
[@@deriving compare] [@@deriving compare]
let equal = [%compare.equal : t] let equal = [%compare.equal : t]
@ -585,6 +588,14 @@ module Procname = struct
if is_instance then ObjCInstanceMethod else ObjCClassMethod if is_instance then ObjCInstanceMethod else ObjCClassMethod
let block_name_of_procname procname =
match procname with
| Block block_name ->
block_name
| _ ->
Logging.die InternalError "Only to be called with Objective-C block names"
let empty_block = Block "" let empty_block = Block ""
let is_verbose v = match v with Verbose -> true | _ -> false let is_verbose v = match v with Verbose -> true | _ -> false
@ -650,6 +661,8 @@ module Procname = struct
{class_name; method_name; kind; template_args; is_generic_model} {class_name; method_name; kind; template_args; is_generic_model}
let with_block_parameters base blocks = WithBlockParameters (base, blocks)
(** 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_block name = Block name let mangled_objc_block name = Block name
@ -663,20 +676,24 @@ module Procname = struct
(** Replace the class name component of a procedure name. (** Replace the class name component of a procedure name.
In case of Java, replace package and class name. *) In case of Java, replace package and class name. *)
let replace_class t (new_class: Name.t) = let rec replace_class t (new_class: Name.t) =
match t with match t with
| Java j -> | Java j ->
Java {j with class_name= new_class} Java {j with class_name= new_class}
| ObjC_Cpp osig -> | ObjC_Cpp osig ->
ObjC_Cpp {osig with class_name= new_class} ObjC_Cpp {osig with class_name= new_class}
| WithBlockParameters (base, blocks) ->
WithBlockParameters (replace_class base new_class, blocks)
| C _ | Block _ | Linters_dummy_method -> | C _ | Block _ | Linters_dummy_method ->
t t
let objc_cpp_replace_method_name t (new_method_name: string) = let rec objc_cpp_replace_method_name t (new_method_name: string) =
match t with match t with
| ObjC_Cpp osig -> | ObjC_Cpp osig ->
ObjC_Cpp {osig with method_name= new_method_name} ObjC_Cpp {osig with method_name= new_method_name}
| WithBlockParameters (base, blocks) ->
WithBlockParameters (objc_cpp_replace_method_name base new_method_name, blocks)
| C _ | Block _ | Linters_dummy_method | Java _ -> | C _ | Block _ | Linters_dummy_method | Java _ ->
t t
@ -711,9 +728,11 @@ module Procname = struct
let java_replace_parameters j parameters = {j with parameters} let java_replace_parameters j parameters = {j with parameters}
(** Return the method/function of a procname. *) (** Return the method/function of a procname. *)
let get_method = function let rec get_method = function
| ObjC_Cpp name -> | ObjC_Cpp name ->
name.method_name name.method_name
| WithBlockParameters (base, _) ->
get_method base
| C {name} -> | C {name} ->
QualifiedCppName.to_qual_string name QualifiedCppName.to_qual_string name
| Block name -> | Block name ->
@ -727,6 +746,8 @@ module Procname = struct
(** Return whether the procname is a block procname. *) (** Return whether the procname is a block procname. *)
let is_objc_block = function Block _ -> true | _ -> false let is_objc_block = function Block _ -> true | _ -> false
let is_with_block_parameters = function WithBlockParameters _ -> true | _ -> false
(** Return whether the procname is a cpp lambda. *) (** Return whether the procname is a cpp lambda. *)
let is_cpp_lambda procname = String.is_substring ~substring:"operator()" (get_method procname) let is_cpp_lambda procname = String.is_substring ~substring:"operator()" (get_method procname)
@ -740,6 +761,8 @@ module Procname = struct
Config.Clang Config.Clang
| Linters_dummy_method -> | Linters_dummy_method ->
Config.Clang Config.Clang
| WithBlockParameters _ ->
Config.Clang
| Java _ -> | Java _ ->
Config.Java Config.Java
@ -988,8 +1011,13 @@ module Procname = struct
Name.name osig.class_name ^ "_" ^ osig.method_name ^ m_str Name.name osig.class_name ^ "_" ^ osig.method_name ^ m_str
let with_blocks_parameters_to_string base blocks to_string_f =
let base_id = to_string_f base in
String.concat ~sep:"_" (base_id :: blocks)
(** Very verbose representation of an existing Procname.t *) (** Very verbose representation of an existing Procname.t *)
let to_unique_id pn = let rec to_unique_id pn =
match pn with match pn with
| Java j -> | Java j ->
java_to_string j Verbose java_to_string j Verbose
@ -999,12 +1027,14 @@ module Procname = struct
c_method_to_string osig Verbose c_method_to_string osig Verbose
| Block name -> | Block name ->
name name
| WithBlockParameters (base, blocks) ->
with_blocks_parameters_to_string base blocks to_unique_id
| Linters_dummy_method -> | Linters_dummy_method ->
"Linters_dummy_method" "Linters_dummy_method"
(** 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 rec to_string p =
match p with match p with
| Java j -> | Java j ->
java_to_string j Non_verbose java_to_string j Non_verbose
@ -1014,6 +1044,8 @@ module Procname = struct
c_method_to_string osig Non_verbose c_method_to_string osig Non_verbose
| Block name -> | Block name ->
name name
| WithBlockParameters (base, blocks) ->
with_blocks_parameters_to_string base blocks to_string
| Linters_dummy_method -> | Linters_dummy_method ->
to_unique_id p to_unique_id p
@ -1021,7 +1053,7 @@ module Procname = struct
let sexp_of_t p = Sexp.Atom (to_string p) let sexp_of_t p = Sexp.Atom (to_string p)
(** 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= false) p = let rec to_simplified_string ?(withclass= false) p =
match p with match p with
| Java j -> | Java j ->
java_to_string ~withclass j Simple java_to_string ~withclass j Simple
@ -1031,6 +1063,8 @@ module Procname = struct
c_method_to_string osig Simple c_method_to_string osig Simple
| Block _ -> | Block _ ->
"block" "block"
| WithBlockParameters (base, _) ->
to_simplified_string base
| Linters_dummy_method -> | Linters_dummy_method ->
to_unique_id p to_unique_id p

@ -272,17 +272,27 @@ module Procname : sig
type objc_cpp type objc_cpp
(** Type of Objective C block names. *) (** Type of Objective C block names. *)
type block type block_name
(** Type of procedure names. *) (** Type of procedure names.
WithBlockParameters is used for creating an instantiation of a method that contains block parameters
and it's called with concrete blocks. For example:
foo(Block block) {block();}
bar() {foo(my_block)} is executed as foo_my_block() {my_block(); }
where foo_my_block is created with WithBlockParameters (foo, [my_block]) *)
type t = type t =
| Java of java | Java of java
| C of c | C of c
| Linters_dummy_method | Linters_dummy_method
| Block of block | Block of block_name
| ObjC_Cpp of objc_cpp | ObjC_Cpp of objc_cpp
| WithBlockParameters of t * block_name list
[@@deriving compare] [@@deriving compare]
val block_from_string : string -> block_name
val block_name_of_procname : t -> block_name
val equal : t -> t -> bool val equal : t -> t -> bool
val hash : t -> int val hash : t -> int
@ -335,6 +345,9 @@ module Procname : sig
val is_objc_block : t -> bool val is_objc_block : t -> bool
(** Return whether the procname is a block procname. *) (** Return whether the procname is a block procname. *)
val is_with_block_parameters : t -> bool
(** Return whether the procname is a procname instantiated with block parameters. *)
val is_cpp_lambda : t -> bool val is_cpp_lambda : t -> bool
(** Return whether the procname is a cpp lambda. *) (** Return whether the procname is a cpp lambda. *)
@ -389,6 +402,10 @@ module Procname : sig
-> objc_cpp -> objc_cpp
(** 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 with_block_parameters : t -> block_name list -> t
(** Create a procedure name instantiated with block parameters from a base procedure name
and a list of block procedure names (the arguments). *)
val objc_cpp_get_class_name : objc_cpp -> string val objc_cpp_get_class_name : objc_cpp -> string
(** Get the class name of a Objective-C/C++ procedure name. *) (** Get the class name of a Objective-C/C++ procedure name. *)

@ -118,7 +118,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
(Typ.Procname.objc_cpp_get_class_name objc_cpp_prod) (Typ.Procname.objc_cpp_get_class_name objc_cpp_prod)
| Typ.Procname.C _ -> | Typ.Procname.C _ ->
true (* Needed for test code. *) true (* Needed for test code. *)
| Typ.Procname.Block _ | Typ.Procname.Linters_dummy_method -> | Typ.Procname.Block _
| Typ.Procname.Linters_dummy_method
| Typ.Procname.WithBlockParameters _ ->
L.(die InternalError) "Proc type not supported by crashcontext: block" L.(die InternalError) "Proc type not supported by crashcontext: block"
in in
String.equal frame.Stacktrace.method_str (Typ.Procname.get_method caller) String.equal frame.Stacktrace.method_str (Typ.Procname.get_method caller)

Loading…
Cancel
Save