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 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 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. */
@ -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. */
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 =>
if is_instance {
Instance_objc_method
ObjCInstanceMethod
} else {
Class_objc_method
ObjCClassMethod
};
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 method_kind_compare j1.kind j2.kind;
let c_function_mangled_compare mangled1 mangled2 =>
switch (mangled1, mangled2) {
| (Some _, None) => 1
| (None, Some _) => (-1)
| (None, None) => 0
| (Some mangled1, Some mangled2) => string_compare mangled1 mangled2
let objc_cpp_method_kind_compare k1 k2 =>
switch (k1, k2) {
| (CPPMethod mangled1, CPPMethod mangled2) => mangled_compare mangled1 mangled2
| (CPPMethod _, _) => (-1)
| (_, CPPMethod _) => 1
| (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 =>
string_compare osig1.method_name osig2.method_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
@ -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. */
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 objc_cpp = objc_cpp objc_class "__find_class_" (Some "internal");
let objc_cpp = objc_cpp objc_class "__find_class_" ObjCInternalMethod;
ObjC_Cpp objc_cpp
};
@ -421,15 +429,22 @@ let java_is_vararg =
}
| _ => 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 =
fun
| 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;
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
| Verbose =>
let m_str =
switch osig.mangled {
| None => ""
| Some s => "{" ^ s ^ "}"
switch osig.kind {
| CPPMethod m =>
"(" ^
(
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
};

@ -40,9 +40,12 @@ type method_kind =
| Static /* in Java, procedures called with invokestatic */
| Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */;
type objc_method_kind =
| Instance_objc_method /* for instance methods in ObjC */
| Class_objc_method /* for class methods in ObjC */;
type objc_cpp_method_kind =
| CPPMethod of (option string) /** with mangling */
| CPPConstructor of (option string) /** with mangling */
| ObjCInstanceMethod
| ObjCInternalMethod
| ObjCClassMethod;
/** 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. */
let is_obj_constructor: string => bool;
let is_objc_constructor: string => bool;
/** 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;
/** 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. */
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;
@ -149,7 +148,7 @@ let objc_cpp_get_class_name: objc_cpp => string;
/** 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. */

@ -1170,7 +1170,7 @@ let execute_objc_alloc_no_fail
SymExec.instrs tenv pdesc [alloc_instr] symb_state
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 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 *)
let objc_method_to_procname objc_method =
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 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_source =

@ -233,7 +233,7 @@ let direct_atomic_property_access_warning method_decl stmt_info ivar_decl_ref =
Last two conditions avoids false positives *)
is_ivar_atomic (get_ivar_attributes d)
&& 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
if condition then
Some {

@ -632,13 +632,17 @@ struct
Procname.C (Procname.c name mangled)
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 class_name method_name mangled)
let mk_procname_from_cpp_method class_name method_name mangled_opt =
(Procname.objc_cpp class_name method_name method_kind)
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 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 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 method_name = Ast_utils.get_unqualified_name 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) ->
let class_name = Ast_utils.get_class_name_from_member name_info in
get_objc_method_name name_info mdi class_name

@ -199,7 +199,7 @@ sig
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)
option -> Config.clang_lang -> Procname.t
@ -207,7 +207,8 @@ sig
val get_mangled_method_name : Clang_ast_t.function_decl_info ->
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

@ -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
let id_type = Ast_expressions.create_id_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
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_type = Ast_expressions.create_class_type (class_name, `OBJC) 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)
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
&& class_name = CFrontend_config.nsautorelease_pool_cl 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)]
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
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) 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
[] (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 class_type = Ast_expressions.create_class_type (class_name, `OBJC) 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
[] (Some ModelBuiltins.__instanceof)

@ -28,7 +28,7 @@ val is_modeled_builtin : string -> bool
val is_toll_free_bridging : Procname.t option -> bool
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
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 is_instance = true 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;
let args = [(alloc_ret_exp, alloc_ret_type)] in
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_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.CXXConstructorDecl (_, 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
Printing.log_out " ...Declaring method '%s'.\n" method_name;
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
| _ -> None in
(* poor mans list_filter_map *)

Loading…
Cancel
Save