add constructor info to c++ methods

Summary:
Store more information inside Procname.objc_cpp type: replace mangling info
with "kind" info, which also contains mangling info when appropriate.

Reviewed By: akotulski

Differential Revision: D3580283

fbshipit-source-id: b1197ed
master
Jules Villard 8 years ago committed by Facebook Github Bot 0
parent e95ebca786
commit 9378913223

@ -39,9 +39,16 @@ type java = {
/** Type of c procedure names. */ /** Type of c procedure names. */
type c = (string, option string); type c = (string, option string);
type objc_cpp_method_kind =
| CPPMethod of (option string) /** with mangling */
| CPPConstructor of (option string) /** with mangling */
| ObjCInstanceMethod
| ObjCInternalMethod
| ObjCClassMethod;
/** Type of Objective C and C++ procedure names: method signatures. */ /** Type of Objective C and C++ procedure names: method signatures. */
type objc_cpp = {class_name: string, method_name: string, mangled: option string}; type objc_cpp = {class_name: string, method_name: string, kind: objc_cpp_method_kind};
/** Type of Objective C block names. */ /** Type of Objective C block names. */
@ -55,19 +62,11 @@ type t = | Java of java | C of c | ObjC_Cpp of objc_cpp | Block of block;
/** Level of verbosity of some to_string functions. */ /** Level of verbosity of some to_string functions. */
type detail_level = | Verbose | Non_verbose | Simple; type detail_level = | Verbose | Non_verbose | Simple;
type objc_method_kind = | Instance_objc_method | Class_objc_method;
let mangled_of_objc_method_kind kind =>
switch kind {
| Instance_objc_method => Some "instance"
| Class_objc_method => Some "class"
};
let objc_method_kind_of_bool is_instance => let objc_method_kind_of_bool is_instance =>
if is_instance { if is_instance {
Instance_objc_method ObjCInstanceMethod
} else { } else {
Class_objc_method ObjCClassMethod
}; };
let empty_block = Block ""; let empty_block = Block "";
@ -156,12 +155,21 @@ let java_compare (j1: java) (j2: java) =>
next java_return_type_compare j1.return_type j2.return_type |> next java_return_type_compare j1.return_type j2.return_type |>
next method_kind_compare j1.kind j2.kind; next method_kind_compare j1.kind j2.kind;
let c_function_mangled_compare mangled1 mangled2 => let objc_cpp_method_kind_compare k1 k2 =>
switch (mangled1, mangled2) { switch (k1, k2) {
| (Some _, None) => 1 | (CPPMethod mangled1, CPPMethod mangled2) => mangled_compare mangled1 mangled2
| (None, Some _) => (-1) | (CPPMethod _, _) => (-1)
| (None, None) => 0 | (_, CPPMethod _) => 1
| (Some mangled1, Some mangled2) => string_compare mangled1 mangled2 | (CPPConstructor mangled1, CPPConstructor mangled2) => mangled_compare mangled1 mangled2
| (CPPConstructor _, _) => (-1)
| (_, CPPConstructor _) => 1
| (ObjCClassMethod, ObjCClassMethod) => 0
| (ObjCClassMethod, _) => (-1)
| (_, ObjCClassMethod) => 1
| (ObjCInstanceMethod, ObjCInstanceMethod) => 0
| (ObjCInstanceMethod, _) => (-1)
| (_, ObjCInstanceMethod) => 1
| (ObjCInternalMethod, ObjCInternalMethod) => 0
}; };
@ -169,7 +177,7 @@ let c_function_mangled_compare mangled1 mangled2 =>
let c_meth_sig_compare osig1 osig2 => let c_meth_sig_compare osig1 osig2 =>
string_compare osig1.method_name osig2.method_name |> string_compare osig1.method_name osig2.method_name |>
next string_compare osig1.class_name osig2.class_name |> next string_compare osig1.class_name osig2.class_name |>
next c_function_mangled_compare osig1.mangled osig2.mangled; next objc_cpp_method_kind_compare osig1.kind osig2.kind;
/** Given a package.class_name string, it looks for the latest dot and split the string /** Given a package.class_name string, it looks for the latest dot and split the string
@ -190,10 +198,10 @@ let java class_name return_type method_name parameters 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 objc_cpp class_name method_name mangled => {class_name, method_name, mangled}; let objc_cpp class_name method_name kind => {class_name, method_name, kind};
let get_default_objc_class_method objc_class => { let get_default_objc_class_method objc_class => {
let objc_cpp = objc_cpp objc_class "__find_class_" (Some "internal"); let objc_cpp = objc_cpp objc_class "__find_class_" ObjCInternalMethod;
ObjC_Cpp objc_cpp ObjC_Cpp objc_cpp
}; };
@ -421,15 +429,22 @@ let java_is_vararg =
} }
| _ => false; | _ => false;
let is_obj_constructor method_name => method_name == "new" || string_is_prefix "init" method_name; let is_objc_constructor method_name => method_name == "new" || string_is_prefix "init" method_name;
let is_objc_kind =
fun
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod => true
| _ => false;
/** [is_constructor pname] returns true if [pname] is a constructor
TODO: add case for C++ */ /** [is_constructor pname] returns true if [pname] is a constructor */
let is_constructor = let is_constructor =
fun fun
| Java js => js.method_name == "<init>" | Java js => js.method_name == "<init>"
| ObjC_Cpp name => is_obj_constructor name.method_name | ObjC_Cpp {kind: CPPConstructor _} => true
| ObjC_Cpp {kind, method_name} when is_objc_kind kind => is_objc_constructor method_name
| _ => false; | _ => false;
let is_objc_dealloc method_name => method_name == "dealloc"; let is_objc_dealloc method_name => method_name == "dealloc";
@ -486,9 +501,28 @@ let c_method_to_string osig detail_level =>
| Non_verbose => osig.class_name ^ "_" ^ osig.method_name | Non_verbose => osig.class_name ^ "_" ^ osig.method_name
| Verbose => | Verbose =>
let m_str = let m_str =
switch osig.mangled { switch osig.kind {
| None => "" | CPPMethod m =>
| Some s => "{" ^ s ^ "}" "(" ^
(
switch m {
| None => ""
| Some s => s
}
) ^
")"
| CPPConstructor m =>
"{" ^
(
switch m {
| None => ""
| Some s => s
}
) ^
"}"
| ObjCClassMethod => "class"
| ObjCInstanceMethod => "instance"
| ObjCInternalMethod => "internal"
}; };
osig.class_name ^ "_" ^ osig.method_name ^ m_str osig.class_name ^ "_" ^ osig.method_name ^ m_str
}; };

@ -40,9 +40,12 @@ type method_kind =
| Static /* in Java, procedures called with invokestatic */ | Static /* in Java, procedures called with invokestatic */
| Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */; | Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */;
type objc_method_kind = type objc_cpp_method_kind =
| Instance_objc_method /* for instance methods in ObjC */ | CPPMethod of (option string) /** with mangling */
| Class_objc_method /* for class methods in ObjC */; | CPPConstructor of (option string) /** with mangling */
| ObjCInstanceMethod
| ObjCInternalMethod
| ObjCClassMethod;
/** Hash tables with proc names as keys. */ /** Hash tables with proc names as keys. */
@ -98,7 +101,7 @@ let is_c_method: t => bool;
/** Check if this is a constructor method in Objective-C. */ /** Check if this is a constructor method in Objective-C. */
let is_obj_constructor: string => bool; let is_objc_constructor: string => bool;
/** Check if this is a constructor. */ /** Check if this is a constructor. */
@ -134,12 +137,8 @@ let java_replace_return_type: java => java_type => java;
let mangled_objc_block: string => t; let mangled_objc_block: string => t;
/** Mangled string for method types. */
let mangled_of_objc_method_kind: objc_method_kind => option string;
/** 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 objc_cpp: string => string => option string => objc_cpp; let objc_cpp: string => string => objc_cpp_method_kind => objc_cpp;
let get_default_objc_class_method: string => t; let get_default_objc_class_method: string => t;
@ -149,7 +148,7 @@ let objc_cpp_get_class_name: objc_cpp => string;
/** Create ObjC method type from a bool is_instance. */ /** Create ObjC method type from a bool is_instance. */
let objc_method_kind_of_bool: bool => objc_method_kind; let objc_method_kind_of_bool: bool => objc_cpp_method_kind;
/** Return the class name of a java procedure name. */ /** Return the class name of a java procedure name. */

@ -1170,7 +1170,7 @@ let execute_objc_alloc_no_fail
SymExec.instrs tenv pdesc [alloc_instr] symb_state SymExec.instrs tenv pdesc [alloc_instr] symb_state
let mk_objc_class_method class_name method_name = let mk_objc_class_method class_name method_name =
let method_kind = Procname.mangled_of_objc_method_kind Procname.Class_objc_method in let method_kind = Procname.ObjCClassMethod in
(Procname.ObjC_Cpp (Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)) (Procname.objc_cpp class_name method_name method_kind))

@ -273,9 +273,8 @@ let java_method_to_procname java_method =
(* turn string specificiation of an objc method into a procname *) (* turn string specificiation of an objc method into a procname *)
let objc_method_to_procname objc_method = let objc_method_to_procname objc_method =
let method_kind = Procname.objc_method_kind_of_bool (not objc_method.is_static) in let method_kind = Procname.objc_method_kind_of_bool (not objc_method.is_static) in
let mangled = Procname.mangled_of_objc_method_kind method_kind in
Procname.ObjC_Cpp Procname.ObjC_Cpp
(Procname.objc_cpp objc_method.classname objc_method.method_name mangled) (Procname.objc_cpp objc_method.classname objc_method.method_name method_kind)
let taint_spec_to_taint_info taint_spec = let taint_spec_to_taint_info taint_spec =
let taint_source = let taint_source =

@ -233,7 +233,7 @@ let direct_atomic_property_access_warning method_decl stmt_info ivar_decl_ref =
Last two conditions avoids false positives *) Last two conditions avoids false positives *)
is_ivar_atomic (get_ivar_attributes d) is_ivar_atomic (get_ivar_attributes d)
&& not (is_method_property_accessor_of_ivar method_decl ivar_pointer) && not (is_method_property_accessor_of_ivar method_decl ivar_pointer)
&& not (Procname.is_obj_constructor method_name) && not (Procname.is_objc_constructor method_name)
&& not (Procname.is_objc_dealloc method_name) in && not (Procname.is_objc_dealloc method_name) in
if condition then if condition then
Some { Some {

@ -632,13 +632,17 @@ struct
Procname.C (Procname.c name mangled) Procname.C (Procname.c name mangled)
let mk_procname_from_objc_method class_name method_name method_kind = let mk_procname_from_objc_method class_name method_name method_kind =
let mangled = Procname.mangled_of_objc_method_kind method_kind in
Procname.ObjC_Cpp Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name mangled) (Procname.objc_cpp class_name method_name method_kind)
let mk_procname_from_cpp_method class_name method_name mangled_opt = let mk_procname_from_cpp_method class_name method_name ?meth_decl mangled =
let method_kind = match meth_decl with
| Some (Clang_ast_t.CXXConstructorDecl _) ->
Procname.CPPConstructor mangled
| _ ->
Procname.CPPMethod mangled in
Procname.ObjC_Cpp Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name mangled_opt) (Procname.objc_cpp class_name method_name method_kind)
let get_objc_method_name name_info mdi class_name = let get_objc_method_name name_info mdi class_name =
let method_name = name_info.Clang_ast_t.ni_name in let method_name = name_info.Clang_ast_t.ni_name in
@ -661,7 +665,7 @@ struct
let mangled = get_mangled_method_name fdi mdi in let mangled = get_mangled_method_name fdi mdi in
let method_name = Ast_utils.get_unqualified_name name_info in let method_name = Ast_utils.get_unqualified_name name_info in
let class_name = Ast_utils.get_class_name_from_member name_info in let class_name = Ast_utils.get_class_name_from_member name_info in
mk_procname_from_cpp_method class_name method_name mangled mk_procname_from_cpp_method class_name method_name ~meth_decl mangled
| ObjCMethodDecl (_, name_info, mdi) -> | ObjCMethodDecl (_, name_info, mdi) ->
let class_name = Ast_utils.get_class_name_from_member name_info in let class_name = Ast_utils.get_class_name_from_member name_info in
get_objc_method_name name_info mdi class_name get_objc_method_name name_info mdi class_name

@ -199,7 +199,7 @@ sig
val replicate: int -> 'a -> 'a list val replicate: int -> 'a -> 'a list
val mk_procname_from_objc_method : string -> string -> Procname.objc_method_kind -> Procname.t val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t
val mk_procname_from_function : string -> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) val mk_procname_from_function : string -> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info)
option -> Config.clang_lang -> Procname.t option -> Config.clang_lang -> Procname.t
@ -207,7 +207,8 @@ sig
val get_mangled_method_name : Clang_ast_t.function_decl_info -> val get_mangled_method_name : Clang_ast_t.function_decl_info ->
Clang_ast_t.cxx_method_decl_info -> string option Clang_ast_t.cxx_method_decl_info -> string option
val mk_procname_from_cpp_method : string -> string -> string option-> Procname.t val mk_procname_from_cpp_method :
string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t
val procname_of_decl : Clang_ast_t.decl -> Procname.t val procname_of_decl : Clang_ast_t.decl -> Procname.t

@ -145,7 +145,7 @@ let get_predefined_ms_stringWithUTF8String class_name method_name mk_procname la
&& method_name = CFrontend_config.string_with_utf8_m in && method_name = CFrontend_config.string_with_utf8_m in
let id_type = Ast_expressions.create_id_type in let id_type = Ast_expressions.create_id_type in
let args = [(Mangled.from_string "x", Ast_expressions.create_char_star_type)] in let args = [(Mangled.from_string "x", Ast_expressions.create_char_star_type)] in
get_predefined_ms_method condition class_name method_name Procname.Class_objc_method get_predefined_ms_method condition class_name method_name Procname.ObjCClassMethod
mk_procname lang args id_type [] None mk_procname lang args id_type [] None
let get_predefined_ms_retain_release method_name mk_procname lang = let get_predefined_ms_retain_release method_name mk_procname lang =
@ -156,7 +156,7 @@ let get_predefined_ms_retain_release method_name mk_procname lang =
let class_name = CFrontend_config.nsobject_cl in let class_name = CFrontend_config.nsobject_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
let args = [(Mangled.from_string CFrontend_config.self, class_type)] in let args = [(Mangled.from_string CFrontend_config.self, class_type)] in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method get_predefined_ms_method condition class_name method_name Procname.ObjCInstanceMethod
mk_procname lang args return_type [] (get_builtinname method_name) mk_procname lang args return_type [] (get_builtinname method_name)
let get_predefined_ms_autoreleasepool_init class_name method_name mk_procname lang = let get_predefined_ms_autoreleasepool_init class_name method_name mk_procname lang =
@ -164,7 +164,7 @@ let get_predefined_ms_autoreleasepool_init class_name method_name mk_procname la
method_name = CFrontend_config.init method_name = CFrontend_config.init
&& class_name = CFrontend_config.nsautorelease_pool_cl in && class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method get_predefined_ms_method condition class_name method_name Procname.ObjCInstanceMethod
mk_procname lang [(Mangled.from_string CFrontend_config.self, class_type)] mk_procname lang [(Mangled.from_string CFrontend_config.self, class_type)]
Ast_expressions.create_void_type [] None Ast_expressions.create_void_type [] None
@ -174,7 +174,7 @@ let get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procna
&& class_name = CFrontend_config.nsautorelease_pool_cl in && class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
let args = [(Mangled.from_string CFrontend_config.self, class_type)] in let args = [(Mangled.from_string CFrontend_config.self, class_type)] in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method get_predefined_ms_method condition class_name method_name Procname.ObjCInstanceMethod
mk_procname lang args Ast_expressions.create_void_type mk_procname lang args Ast_expressions.create_void_type
[] (Some ModelBuiltins.__objc_release_autorelease_pool) [] (Some ModelBuiltins.__objc_release_autorelease_pool)
@ -182,7 +182,7 @@ let get_predefined_ms_is_kind_of_class class_name method_name mk_procname lang =
let condition = method_name = CFrontend_config.is_kind_of_class in let condition = method_name = CFrontend_config.is_kind_of_class in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
let args = [(Mangled.from_string CFrontend_config.self, class_type)] in let args = [(Mangled.from_string CFrontend_config.self, class_type)] in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method get_predefined_ms_method condition class_name method_name Procname.ObjCInstanceMethod
mk_procname lang args Ast_expressions.create_BOOL_type mk_procname lang args Ast_expressions.create_BOOL_type
[] (Some ModelBuiltins.__instanceof) [] (Some ModelBuiltins.__instanceof)

@ -28,7 +28,7 @@ val is_modeled_builtin : string -> bool
val is_toll_free_bridging : Procname.t option -> bool val is_toll_free_bridging : Procname.t option -> bool
val get_predefined_model_method_signature : string -> string -> val get_predefined_model_method_signature : string -> string ->
(string -> string -> Procname.objc_method_kind -> Procname.t) -> (string -> string -> Procname.objc_cpp_method_kind -> Procname.t) ->
Config.clang_lang -> CMethod_signature.method_signature option Config.clang_lang -> CMethod_signature.method_signature option
val is_dispatch_function_name : string -> (string * int) option val is_dispatch_function_name : string -> (string * int) option

@ -332,7 +332,9 @@ let objc_new_trans trans_state loc stmt_info cls_name function_type =
let init_ret_id = Ident.create_fresh Ident.knormal in let init_ret_id = Ident.create_fresh Ident.knormal in
let is_instance = true in let is_instance = true in
let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_instance; } in let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_instance; } in
let pname = General_utils.mk_procname_from_objc_method cls_name CFrontend_config.init Procname.Instance_objc_method in let pname =
General_utils.mk_procname_from_objc_method
cls_name CFrontend_config.init Procname.ObjCInstanceMethod in
CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None; CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None;
let args = [(alloc_ret_exp, alloc_ret_type)] in let args = [(alloc_ret_exp, alloc_ret_type)] in
let init_stmt_call = let init_stmt_call =

@ -103,7 +103,7 @@ let get_record_name_csu decl =
let get_record_name decl = snd (get_record_name_csu decl) let get_record_name decl = snd (get_record_name_csu decl)
let get_class_methods class_name decl_list = let get_class_methods class_name decl_list =
let process_method_decl = function let process_method_decl meth_decl = match meth_decl with
| Clang_ast_t.CXXMethodDecl (_, name_info, _, fdi, mdi) | Clang_ast_t.CXXMethodDecl (_, name_info, _, fdi, mdi)
| Clang_ast_t.CXXConstructorDecl (_, name_info, _, fdi, mdi) | Clang_ast_t.CXXConstructorDecl (_, name_info, _, fdi, mdi)
| Clang_ast_t.CXXConversionDecl (_, name_info, _, fdi, mdi) | Clang_ast_t.CXXConversionDecl (_, name_info, _, fdi, mdi)
@ -111,7 +111,8 @@ let get_class_methods class_name decl_list =
let method_name = name_info.Clang_ast_t.ni_name in let method_name = name_info.Clang_ast_t.ni_name in
Printing.log_out " ...Declaring method '%s'.\n" method_name; Printing.log_out " ...Declaring method '%s'.\n" method_name;
let mangled = General_utils.get_mangled_method_name fdi mdi in let mangled = General_utils.get_mangled_method_name fdi mdi in
let procname = General_utils.mk_procname_from_cpp_method class_name method_name mangled in let procname =
General_utils.mk_procname_from_cpp_method class_name method_name ~meth_decl mangled in
Some procname Some procname
| _ -> None in | _ -> None in
(* poor mans list_filter_map *) (* poor mans list_filter_map *)

Loading…
Cancel
Save