Using clang's method resolution if possible

Summary: public
Using clang's method resolution. This means that, in method calls, clang gives you a pointer to the declaration of the method.
In some cases though, clang doesn't find the right method. For example, when it finds a method in a category, we
need to make it into a method in the corresponding class, because that's how we treat categories in Infer. Moreover,
when it finds a method in a protocol, that is not useful for us, since the implementation will be in some class. Finally,
sometimes the call is on an object of type id, in which case clang doesn't know what is the correct declaration. In
those cases,  we fall back to what we were doing before of approximating the method resolution. We also refactor
 some of the code.

Reviewed By: akotulski

Differential Revision: D2679766

fb-gh-sync-id: b79bb85
master
Dulma Rodriguez 9 years ago committed by facebook-github-bot-1
parent 867e7804af
commit 0441919a42

@ -214,11 +214,11 @@ let make_obj_c_message_expr_info_instance sel = {
omei_decl_pointer = None; (* TODO look into it *)
}
let make_obj_c_message_expr_info_class selector tp = {
let make_obj_c_message_expr_info_class selector tp pointer = {
Clang_ast_t.omei_selector = selector;
omei_receiver_kind = `Class (create_class_type tp);
omei_is_definition_found = false;
omei_decl_pointer = None (* TODO look into it *)
omei_decl_pointer = pointer
}
let make_decl_ref k decl_ptr name is_hidden tp_opt = {

@ -83,7 +83,8 @@ val make_decl_ref_exp_var : named_decl_info * type_ptr * pointer -> decl_kind ->
val make_binary_stmt : stmt -> stmt -> stmt_info -> expr_info -> binary_operator_info -> stmt
val make_obj_c_message_expr_info_class : string -> string -> obj_c_message_expr_info
val make_obj_c_message_expr_info_class : string -> string -> pointer option ->
obj_c_message_expr_info
val make_obj_c_message_expr_info_instance : string -> obj_c_message_expr_info

@ -292,6 +292,11 @@ struct
Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.pointer_decl_index)
with Not_found -> Printing.log_stats "decl with pointer %s not found\n" decl_ptr; None
let get_decl_opt decl_ptr_opt =
match decl_ptr_opt with
| Some decl_ptr -> get_decl decl_ptr
| None -> None
let update_sil_types_map type_ptr sil_type =
CFrontend_config.sil_types_map :=
Clang_ast_types.TypePointerMap.add type_ptr sil_type !CFrontend_config.sil_types_map

@ -77,6 +77,8 @@ sig
val get_decl : Clang_ast_t.pointer -> Clang_ast_t.decl option
val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option
val update_sil_types_map : Clang_ast_t.type_ptr -> Sil.typ -> unit
val update_enum_map : Clang_ast_t.pointer -> Sil.exp -> unit

@ -11,7 +11,7 @@
(** return type, location and whether its an instance method. *)
type method_signature = {
_name : Procname.t;
mutable _name : Procname.t;
_args : (string * Clang_ast_t.type_ptr) list;
_ret_type : Clang_ast_t.type_ptr;
_attributes : Clang_ast_t.attribute list;
@ -19,11 +19,15 @@ type method_signature = {
_is_instance : bool;
_is_generated : bool;
_language : CFrontend_config.lang;
_pointer_to_parent : Clang_ast_t.pointer option
}
let ms_get_name ms =
ms._name
let ms_set_name ms name =
ms._name <- name
let ms_get_args ms =
ms._args
@ -45,7 +49,10 @@ let ms_is_generated ms =
let ms_get_lang ms =
ms._language
let make_ms procname args ret_type attributes loc is_instance is_generated lang =
let ms_get_pointer_to_parent ms =
ms._pointer_to_parent
let make_ms procname args ret_type attributes loc is_instance is_generated lang pointer_to_parent =
let meth_signature = {
_name = procname;
_args = args;
@ -55,6 +62,7 @@ let make_ms procname args ret_type attributes loc is_instance is_generated lang
_is_instance = is_instance;
_is_generated = is_generated;
_language = lang;
_pointer_to_parent = pointer_to_parent;
} in
meth_signature

@ -14,6 +14,8 @@ type method_signature
val ms_get_name : method_signature -> Procname.t
val ms_set_name : method_signature -> Procname.t -> unit
val ms_get_args : method_signature ->
(string * Clang_ast_t.type_ptr) list
@ -27,9 +29,11 @@ val ms_is_instance : method_signature -> bool
val ms_get_lang : method_signature -> CFrontend_config.lang
val ms_get_pointer_to_parent : method_signature -> Clang_ast_t.pointer option
val make_ms : Procname.t -> (string * Clang_ast_t.type_ptr) list ->
Clang_ast_t.type_ptr -> Clang_ast_t.attribute list -> Clang_ast_t.source_range -> bool ->
bool -> CFrontend_config.lang -> method_signature
bool -> CFrontend_config.lang -> Clang_ast_t.pointer option -> method_signature
val replace_name_ms : method_signature -> Procname.t -> method_signature

@ -86,7 +86,8 @@ let get_return_type function_method_decl_info =
| Block_decl_info (_, typ, _) -> CTypes.return_type_of_function_type typ
| ObjC_Meth_decl_info (method_decl_info, _) -> method_decl_info.Clang_ast_t.omdi_result_type
let build_method_signature decl_info procname function_method_decl_info is_anonym_block is_generated =
let build_method_signature decl_info procname function_method_decl_info is_anonym_block is_generated
parent_pointer =
let source_range = decl_info.Clang_ast_t.di_source_range in
let tp = get_return_type function_method_decl_info in
let is_instance_method = is_instance_method function_method_decl_info in
@ -94,7 +95,7 @@ let build_method_signature decl_info procname function_method_decl_info is_anony
let attributes = decl_info.Clang_ast_t.di_attributes in
let lang = get_language function_method_decl_info in
CMethod_signature.make_ms procname parameters tp attributes source_range is_instance_method
is_generated lang
is_generated lang parent_pointer
let get_assume_not_null_calls ms param_decls =
let attributes = CMethod_signature.ms_get_attributes ms in
@ -119,7 +120,7 @@ let method_signature_of_decl meth_decl block_data_opt =
let func_decl = Func_decl_info (fdi, tp, language) in
let function_info = Some (decl_info, fdi) in
let procname = General_utils.mk_procname_from_function name function_info tp language in
let ms = build_method_signature decl_info procname func_decl false false in
let ms = build_method_signature decl_info procname func_decl false false None in
let extra_instrs = get_assume_not_null_calls ms fdi.Clang_ast_t.fdi_parameters in
ms, fdi.Clang_ast_t.fdi_body, extra_instrs
| CXXMethodDecl (decl_info, name_info, tp, fdi, mdi), _
@ -128,7 +129,8 @@ let method_signature_of_decl meth_decl block_data_opt =
let class_name = Ast_utils.get_class_name_from_member name_info in
let procname = General_utils.mk_procname_from_cpp_method class_name method_name tp in
let method_decl = Cpp_Meth_decl_info (fdi, mdi, class_name, tp) in
let ms = build_method_signature decl_info procname method_decl false false in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
let ms = build_method_signature decl_info procname method_decl false false parent_pointer in
let non_null_instrs = get_assume_not_null_calls ms fdi.Clang_ast_t.fdi_parameters in
let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *)
ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs)
@ -140,12 +142,14 @@ let method_signature_of_decl meth_decl block_data_opt =
let procname = General_utils.mk_procname_from_objc_method class_name method_name method_kind in
let method_decl = ObjC_Meth_decl_info (mdi, class_name) in
let is_generated = Ast_utils.is_generated name_info in
let ms = build_method_signature decl_info procname method_decl false is_generated in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
let ms = build_method_signature decl_info procname method_decl false is_generated
parent_pointer in
let extra_instrs = get_assume_not_null_calls ms mdi.omdi_parameters in
ms, mdi.omdi_body, extra_instrs
| BlockDecl (decl_info, bdi), Some (outer_context, tp, procname, _) ->
let func_decl = Block_decl_info (bdi, tp, outer_context) in
let ms = build_method_signature decl_info procname func_decl true false in
let ms = build_method_signature decl_info procname func_decl true false None in
let extra_instrs = get_assume_not_null_calls ms bdi.bdi_parameters in
ms, bdi.bdi_body, extra_instrs
| _ -> raise Invalid_declaration
@ -159,6 +163,24 @@ let method_signature_of_pointer pointer =
| None -> None
with Invalid_declaration -> None
let get_method_name_from_clang tenv ms_opt =
match ms_opt with
| Some ms ->
(match Ast_utils.get_decl_opt (CMethod_signature.ms_get_pointer_to_parent ms) with
| Some decl ->
if ObjcProtocol_decl.is_protocol decl then None
else
(ignore (CTypes_decl.add_types_from_decl_to_tenv tenv decl);
match ObjcCategory_decl.get_base_class_name_from_category decl with
| Some class_name ->
let procname = CMethod_signature.ms_get_name ms in
let new_procname = Procname.c_method_replace_class procname class_name in
CMethod_signature.ms_set_name ms new_procname;
Some ms
| None -> Some ms)
| None -> Some ms)
| None -> None
let get_superclass_curr_class context =
let retrive_super cname super_opt =
let iname = Sil.TN_csu (Sil.Class, Mangled.from_string cname) in
@ -179,25 +201,39 @@ let get_superclass_curr_class context =
| CContext.ContextNoCls
| CContext.ContextProtocol _ -> assert false
let get_class_selector_instance context obj_c_message_expr_info act_params =
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in
(* Gets the class name from a method signature found by clang, if search is successful *)
let get_class_name_method_call_from_clang obj_c_message_expr_info =
match obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with
| Some pointer ->
(match method_signature_of_pointer pointer with
| Some ms ->
let class_name = Procname.c_get_class (CMethod_signature.ms_get_name ms) in
Some class_name
| None -> None)
| None -> None
(* Get class name from a method call accorsing to the info given by the receiver kind *)
let get_class_name_method_call_from_receiver_kind context obj_c_message_expr_info act_params =
match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with
| `Class tp ->
let sil_type = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv tp in
((CTypes.classname_of_type sil_type), selector, pointer, MCStatic)
(CTypes.classname_of_type sil_type)
| `Instance ->
(match act_params with
| (instance_obj, Sil.Tptr(t, _)):: _
| (instance_obj, t):: _ ->
(CTypes.classname_of_type t, selector, pointer, MCVirtual)
| (instance_obj, t):: _ -> CTypes.classname_of_type t
| _ -> assert false)
| `SuperInstance ->
let superclass = get_superclass_curr_class context in
(superclass, selector, pointer, MCNoVirtual)
| `SuperClass ->
let superclass = get_superclass_curr_class context in
(superclass, selector, pointer, MCStatic)
| `SuperInstance ->get_superclass_curr_class context
| `SuperClass -> get_superclass_curr_class context
let get_objc_method_data obj_c_message_expr_info =
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in
match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with
| `Instance -> (selector, pointer, MCVirtual)
| `SuperInstance -> (selector, pointer, MCNoVirtual)
| `Class _
| `SuperClass -> (selector, pointer, MCStatic)
let get_formal_parameters tenv ms =
let rec defined_parameters pl =

@ -25,8 +25,13 @@ val create_local_procdesc : Cfg.cfg -> Sil.tenv -> CMethod_signature.method_sign
val create_external_procdesc : Cfg.cfg -> Procname.t -> bool -> (Sil.typ * Sil.typ list) option -> unit
val get_class_selector_instance : CContext.t -> Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Sil.typ) list
-> (string * string * Clang_ast_t.pointer option * method_call_type)
val get_objc_method_data : Clang_ast_t.obj_c_message_expr_info ->
(string * Clang_ast_t.pointer option * method_call_type)
val get_class_name_method_call_from_receiver_kind : CContext.t ->
Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Sil.typ) list -> string
val get_class_name_method_call_from_clang : Clang_ast_t.obj_c_message_expr_info -> string option
val should_create_procdesc : Cfg.cfg -> Procname.t -> bool -> bool -> bool
@ -35,5 +40,8 @@ val method_signature_of_decl : Clang_ast_t.decl -> CModule_type.block_data optio
val method_signature_of_pointer : Clang_ast_t.pointer -> CMethod_signature.method_signature option
val get_method_name_from_clang : Sil.tenv -> CMethod_signature.method_signature option ->
CMethod_signature.method_signature option
val create_procdesc_with_pointer : CContext.t -> Clang_ast_t.pointer -> string option ->
string -> Clang_ast_t.type_ptr -> Procname.t

@ -31,33 +31,44 @@ module CTrans_funct(M: CModule_type.CMethod_declaration) : CTrans =
struct
(*Returns the procname and whether is instance, according to the selector *)
(* information and according to the method signature *)
(* information and according to the method signature with the following priority: *)
(* 1. method is a predefined model *)
(* 2. method is found by clang's resolution*)
(* 3. Method is found by our resolution *)
let get_callee_objc_method context obj_c_message_expr_info act_params =
let (class_name, method_name, method_pointer_opt, mc_type) =
CMethod_trans.get_class_selector_instance context obj_c_message_expr_info act_params in
let open CContext in
let (selector, method_pointer_opt, mc_type) =
CMethod_trans.get_objc_method_data obj_c_message_expr_info in
let is_instance = mc_type != CMethod_trans.MCStatic in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
let callee_pn = General_utils.mk_procname_from_objc_method class_name method_name method_kind in
let open CContext in
match CTrans_models.get_predefined_model_method_signature class_name method_name
General_utils.mk_procname_from_objc_method CFrontend_config.OBJC with
| Some ms ->
let ms_opt =
match method_pointer_opt with
| Some pointer -> CMethod_trans.method_signature_of_pointer pointer
| None -> None in
let procname =
match CMethod_trans.get_method_name_from_clang context.tenv ms_opt with
| Some ms -> CMethod_signature.ms_get_name ms
| None -> (* fall back to our method resolution if clang's fails *)
let class_name = CMethod_trans.get_class_name_method_call_from_receiver_kind context
obj_c_message_expr_info act_params in
General_utils.mk_procname_from_objc_method class_name selector method_kind in
let class_name = Procname.c_get_class procname in
let predefined_ms_opt =
CTrans_models.get_predefined_model_method_signature class_name selector
General_utils.mk_procname_from_objc_method CFrontend_config.OBJC in
match predefined_ms_opt, ms_opt with
| Some ms, _ ->
ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv ms [] [] is_instance);
CMethod_signature.ms_get_name ms, CMethod_trans.MCNoVirtual
| None ->
let found_method =
match method_pointer_opt with
| Some pointer ->
(match CMethod_trans.method_signature_of_pointer pointer with
| Some callee_ms ->
if not (M.process_getter_setter context callee_pn) then
(ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv callee_ms [] [] is_instance));
true
| None -> false)
| None -> false in
if not found_method then
CMethod_trans.create_external_procdesc context.cfg callee_pn is_instance None;
callee_pn, mc_type
| None, Some ms ->
if not (M.process_getter_setter context procname) then
(ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv
ms [] [] is_instance));
procname, mc_type
| _ ->
CMethod_trans.create_external_procdesc context.cfg procname is_instance None;
procname, mc_type
let add_autorelease_call context exp typ sil_loc =
let method_name = Procname.c_get_method (Cfg.Procdesc.get_proc_name context.CContext.procdesc) in
@ -817,71 +828,101 @@ struct
Sil.Tvoid
| _ -> assert false
and objCMessageExpr_trans_special_cases trans_state si obj_c_message_expr_info stmt_list
expr_info method_type trans_state_pri sil_loc act_params =
let context = trans_state.context in
let receiver_kind = obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind in
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
(* class method *)
if selector = CFrontend_config.class_method && CTypes.is_class method_type then
let class_name = CMethod_trans.get_class_name_method_call_from_receiver_kind context
obj_c_message_expr_info act_params in
raise (Self.SelfClassException class_name)
(* alloc or new *)
else if (selector = CFrontend_config.alloc) || (selector = CFrontend_config.new_str) then
match receiver_kind with
| `Class type_ptr ->
let class_opt =
CMethod_trans.get_class_name_method_call_from_clang obj_c_message_expr_info in
Some (new_or_alloc_trans trans_state_pri sil_loc si type_ptr class_opt selector)
| _ -> None
(* assertions *)
else if CTrans_models.is_handleFailureInMethod selector then
if Config.report_assertion_failure then
Some (CTrans_utils.trans_assertion_failure sil_loc context)
else Some (CTrans_utils.trans_assume_false sil_loc context trans_state.succ_nodes)
else None
(* If the first argument of the call is self in a static context, remove it as an argument *)
(* and change the call from instance to static *)
and objCMessageExpr_deal_with_static_self trans_state_param stmt_list obj_c_message_expr_info =
match stmt_list with
| stmt :: rest ->
let obj_c_message_expr_info, fst_res_trans =
try
let fst_res_trans = instruction trans_state_param stmt in
obj_c_message_expr_info, fst_res_trans
with Self.SelfClassException class_name ->
let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info_class selector class_name pointer in
obj_c_message_expr_info, empty_res_trans in
let instruction' =
exec_with_self_exception (exec_with_lvalue_as_reference instruction) in
let l = IList.map (instruction' trans_state_param) rest in
obj_c_message_expr_info, collect_res_trans (fst_res_trans :: l)
| [] -> obj_c_message_expr_info, empty_res_trans
and objCMessageExpr_trans trans_state si obj_c_message_expr_info stmt_list expr_info =
Printing.log_out " priority node free = '%s'\n@."
(string_of_bool (PriorityNode.is_priority_free trans_state));
let context = trans_state.context in
let parent_line_number = trans_state.parent_line_number in
let line_number = CLocation.get_line si parent_line_number in
let sil_loc = CLocation.get_sil_location si parent_line_number context in
let selector, receiver_kind = get_selector_receiver obj_c_message_expr_info in
let is_alloc_or_new = (selector = CFrontend_config.alloc) || (selector = CFrontend_config.new_str) in
Printing.log_out "\n!!!!!!! Calling with selector = '%s' " selector;
Printing.log_out " receiver_kind= '%s'\n\n" (Clang_ast_j.string_of_receiver_kind receiver_kind);
let method_type = CTypes_decl.get_type_from_expr_info expr_info context.CContext.tenv in
let ret_id = if Sil.typ_equal method_type Sil.Tvoid then []
let ret_id =
if Sil.typ_equal method_type Sil.Tvoid then []
else [Ident.create_fresh Ident.knormal] in
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state si in
let line_number = CLocation.get_line si parent_line_number in
let trans_state_param =
{ trans_state_pri with parent_line_number = line_number; succ_nodes = [] } in
let obj_c_message_expr_info, res_trans_par =
(match stmt_list with
| stmt :: rest ->
let obj_c_message_expr_info, fst_res_trans =
(try
let fst_res_trans = instruction trans_state_param stmt in
obj_c_message_expr_info, fst_res_trans
with Self.SelfClassException class_name ->
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class selector class_name in
obj_c_message_expr_info, empty_res_trans) in
let instruction' =
exec_with_self_exception (exec_with_lvalue_as_reference instruction) in
let l = IList.map (instruction' trans_state_param) rest in
obj_c_message_expr_info, collect_res_trans (fst_res_trans :: l)
| [] -> obj_c_message_expr_info, empty_res_trans) in
let (class_type, _, _, _) = CMethod_trans.get_class_selector_instance context obj_c_message_expr_info res_trans_par.exps in
if (selector = CFrontend_config.class_method && CTypes.is_class method_type) then
raise (Self.SelfClassException class_type)
else if is_alloc_or_new then
new_or_alloc_trans trans_state_pri sil_loc si class_type selector
else if (CTrans_models.is_handleFailureInMethod selector) then
if Config.report_assertion_failure then
CTrans_utils.trans_assertion_failure sil_loc context
else
CTrans_utils.trans_assume_false sil_loc context trans_state.succ_nodes
else
let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in
let callee_name, method_call_type = get_callee_objc_method context obj_c_message_expr_info res_trans_par.exps in
let res_trans_par = Self.add_self_parameter_for_super_instance context procname sil_loc
obj_c_message_expr_info res_trans_par in
let is_virtual = method_call_type = CMethod_trans.MCVirtual in
Cg.add_edge context.CContext.cg procname callee_name;
let call_flags = { Sil.cf_virtual = is_virtual; Sil.cf_noreturn = false; Sil.cf_is_objc_block = false; } in
let param_exps, instr_block_param, ids_block_param = extract_block_from_tuple procname res_trans_par.exps sil_loc in
let stmt_call = Sil.Call(ret_id, (Sil.Const (Sil.Cfun callee_name)), param_exps, sil_loc, call_flags) in
let nname = "Message Call: "^selector in
let res_trans_tmp = {
res_trans_par with
ids = ret_id @ res_trans_par.ids @ids_block_param ;
instrs = res_trans_par.instrs@instr_block_param@[stmt_call];
exps =[]
} in
let res_trans_to_parent = (
PriorityNode.compute_results_to_parent trans_state_pri sil_loc nname si res_trans_tmp) in
(match ret_id with
| [] -> { res_trans_to_parent with exps = [] }
| [ret_id'] -> { res_trans_to_parent with exps = [(Sil.Var ret_id', method_type)] }
| _ -> assert false) (* by construction of red_id, we cannot be in this case *)
objCMessageExpr_deal_with_static_self trans_state_param stmt_list obj_c_message_expr_info in
match objCMessageExpr_trans_special_cases trans_state si obj_c_message_expr_info stmt_list
expr_info method_type trans_state_pri sil_loc res_trans_par.exps with
| Some res -> res
| None ->
let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in
let callee_name, method_call_type =
get_callee_objc_method context obj_c_message_expr_info res_trans_par.exps in
let res_trans_par = Self.add_self_parameter_for_super_instance context procname sil_loc
obj_c_message_expr_info res_trans_par in
let is_virtual = method_call_type = CMethod_trans.MCVirtual in
Cg.add_edge context.CContext.cg procname callee_name;
let call_flags = {
Sil.cf_virtual = is_virtual;
Sil.cf_noreturn = false;
Sil.cf_is_objc_block = false; } in
let param_exps, instr_block_param, ids_block_param =
extract_block_from_tuple procname res_trans_par.exps sil_loc in
let stmt_call =
Sil.Call (ret_id, (Sil.Const (Sil.Cfun callee_name)), param_exps, sil_loc, call_flags) in
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
let nname = "Message Call: "^selector in
let res_trans_tmp = {
res_trans_par with
ids = ret_id @ res_trans_par.ids @ids_block_param ;
instrs = res_trans_par.instrs @ instr_block_param @ [stmt_call];
exps = []
} in
let res_trans_to_parent = (
PriorityNode.compute_results_to_parent trans_state_pri sil_loc nname si res_trans_tmp) in
match ret_id with
| [] -> { res_trans_to_parent with exps = [] }
| [ret_id'] -> { res_trans_to_parent with exps = [(Sil.Var ret_id', method_type)] }
| _ -> assert false (* by construction of red_id, we cannot be in this case *)
and dispatch_function_trans trans_state stmt_info stmt_list ei n =
Printing.log_out "\n Call to a dispatch function treated as special case...\n";
@ -1816,16 +1857,16 @@ struct
and objCBoxedExpr_trans trans_state info sel stmt_info stmts =
let typ = CTypes_decl.class_from_pointer_type trans_state.context.CContext.tenv info.Clang_ast_t.ei_type_ptr in
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class sel typ in
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class sel typ None in
let message_stmt = Clang_ast_t.ObjCMessageExpr (stmt_info, stmts, info, obj_c_message_expr_info) in
instruction trans_state message_stmt
and objCArrayLiteral_trans trans_state info stmt_info stmts =
let typ = CTypes_decl.class_from_pointer_type trans_state.context.CContext.tenv info.Clang_ast_t.ei_type_ptr in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.array_with_objects_count_m typ in
let meth = CFrontend_config.array_with_objects_count_m in
let obj_c_mes_expr_info = Ast_expressions.make_obj_c_message_expr_info_class meth typ None in
let stmts = stmts @ [Ast_expressions.create_nil stmt_info] in
let message_stmt = Clang_ast_t.ObjCMessageExpr (stmt_info, stmts, info, obj_c_message_expr_info) in
let message_stmt = Clang_ast_t.ObjCMessageExpr (stmt_info, stmts, info, obj_c_mes_expr_info) in
instruction trans_state message_stmt
and objCDictionaryLiteral_trans trans_state info stmt_info stmts =
@ -1833,7 +1874,7 @@ struct
let dictionary_literal_pname = SymExec.ModelBuiltins.__objc_dictionary_literal in
let dictionary_literal_s = Procname.c_get_method dictionary_literal_pname in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info_class dictionary_literal_s typ in
Ast_expressions.make_obj_c_message_expr_info_class dictionary_literal_s typ None in
let stmts = General_utils.swap_elements_list stmts in
let stmts = stmts @ [Ast_expressions.create_nil stmt_info] in
let message_stmt = Clang_ast_t.ObjCMessageExpr (stmt_info, stmts, info, obj_c_message_expr_info) in
@ -1843,9 +1884,9 @@ struct
let stmts = [Ast_expressions.create_implicit_cast_expr stmt_info stmts
Ast_expressions.create_char_star_type `ArrayToPointerDecay] in
let typ = CTypes_decl.class_from_pointer_type trans_state.context.CContext.tenv info.Clang_ast_t.ei_type_ptr in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.string_with_utf8_m typ in
let message_stmt = Clang_ast_t.ObjCMessageExpr (stmt_info, stmts, info, obj_c_message_expr_info) in
let meth = CFrontend_config.string_with_utf8_m in
let obj_c_mess_expr_info = Ast_expressions.make_obj_c_message_expr_info_class meth typ None in
let message_stmt = Clang_ast_t.ObjCMessageExpr (stmt_info, stmts, info, obj_c_mess_expr_info) in
instruction trans_state message_stmt
(** When objects are autoreleased, they get added a flag AUTORELEASE. All these objects will be

@ -127,7 +127,7 @@ let get_predefined_ms_method condition class_name method_name method_kind mk_pro
| Some procname -> procname
| None -> mk_procname class_name method_name method_kind in
let ms = CMethod_signature.make_ms procname arguments return_type attributes
(Ast_expressions.dummy_source_range ()) false false lang in
(Ast_expressions.dummy_source_range ()) false false lang None in
Some ms
else None

@ -317,8 +317,13 @@ let objc_new_trans trans_state loc stmt_info cls_name function_type =
PriorityNode.compute_results_to_parent trans_state loc "Call objC new" stmt_info res_trans_tmp in
{ res_trans with exps = [(Sil.Var init_ret_id, alloc_ret_type)]}
let new_or_alloc_trans trans_state loc stmt_info class_name selector =
let function_type = CTypes_decl.type_name_to_sil_type trans_state.context.CContext.tenv class_name in
let new_or_alloc_trans trans_state loc stmt_info type_ptr class_name_opt selector =
let tenv = trans_state.context.CContext.tenv in
let function_type = CTypes_decl.type_ptr_to_sil_type tenv type_ptr in
let class_name =
match class_name_opt with
| Some class_name -> class_name
| None -> CTypes.classname_of_type function_type in
if selector = CFrontend_config.alloc then
alloc_trans trans_state loc stmt_info function_type true
else if selector = CFrontend_config.new_str then

@ -106,8 +106,8 @@ val builtin_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info ->
val alloc_trans :
trans_state -> Location.t -> Clang_ast_t.stmt_info -> Sil.typ -> bool -> trans_result
val new_or_alloc_trans :
trans_state -> Location.t -> Clang_ast_t.stmt_info -> string -> string -> trans_result
val new_or_alloc_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info ->
Clang_ast_t.type_ptr -> string option -> string -> trans_result
val cpp_new_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info -> Sil.typ -> trans_result

@ -49,6 +49,23 @@ let add_category_implementation type_ptr_to_sil_type tenv category_decl_info =
let decl_ref_opt = category_decl_info.Clang_ast_t.odi_implementation in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
let get_base_class_name_from_category decl =
let open Clang_ast_t in
let base_class_pointer_opt =
match decl with
| ObjCCategoryDecl (decl_info, name_info, decl_list, decl_context_info, cdi) ->
cdi.Clang_ast_t.odi_class_interface
| ObjCCategoryImplDecl (decl_info, name_info, decl_list, decl_context_info, cii) ->
cii.Clang_ast_t.ocidi_class_interface
| _ -> None in
match base_class_pointer_opt with
| Some decl_ref ->
(match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
| Some ObjCInterfaceDecl (decl_info, name_info, decl_list, _, ocidi) ->
Some (Ast_utils.get_qualified_name name_info)
| _ -> None)
| None -> None
(* Add potential extra fields defined only in the category *)
(* to the corresponding class. Update the tenv accordingly.*)
let process_category type_ptr_to_sil_type tenv curr_class decl_info decl_list =

@ -23,3 +23,5 @@ val get_curr_class_from_category_decl : string -> Clang_ast_t.obj_c_category_dec
val get_curr_class_from_category_impl : string -> Clang_ast_t.obj_c_category_impl_decl_info ->
CContext.curr_class
val get_base_class_name_from_category : Clang_ast_t.decl -> string option

@ -38,3 +38,9 @@ let protocol_decl type_ptr_to_sil_type tenv decl =
add_protocol_super type_ptr_to_sil_type tenv obj_c_protocol_decl_info;
Sil.Tvar protocol_name
| _ -> assert false
let is_protocol decl =
let open Clang_ast_t in
match decl with
| ObjCProtocolDecl(decl_info, name_info, decl_list, _, obj_c_protocol_decl_info) -> true
| _ -> false

@ -13,3 +13,5 @@
open CFrontend_utils
val protocol_decl : Ast_utils.type_ptr_to_sil_type -> Sil.tenv -> Clang_ast_t.decl -> Sil.typ
val is_protocol : Clang_ast_t.decl -> bool

@ -1,5 +1,5 @@
digraph iCFG {
6 [label="6: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class EOCPerson ):unsigned long ) [line 14]\n n$2=_fun_EOCPerson_init(n$4:class EOCPerson *) virtual [line 14]\n *&person:class EOCPerson *=n$2 [line 14]\n REMOVE_TEMPS(n$2,n$4); [line 14]\n " shape="box"]
6 [label="6: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class EOCPerson ):unsigned long ) [line 14]\n n$2=_fun_NSObject_init(n$4:class EOCPerson *) virtual [line 14]\n *&person:class EOCPerson *=n$2 [line 14]\n REMOVE_TEMPS(n$2,n$4); [line 14]\n " shape="box"]
6 -> 5 ;

@ -1,5 +1,5 @@
digraph iCFG {
12 [label="12: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 45]\n n$3=_fun_A_init(n$2:class A *) virtual [line 45]\n *&a:struct objc_object *=n$3 [line 45]\n REMOVE_TEMPS(n$2,n$3); [line 45]\n NULLIFY(&a,false); [line 45]\n " shape="box"]
12 [label="12: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 45]\n n$3=_fun_NSObject_init(n$2:class A *) virtual [line 45]\n *&a:struct objc_object *=n$3 [line 45]\n REMOVE_TEMPS(n$2,n$3); [line 45]\n NULLIFY(&a,false); [line 45]\n " shape="box"]
12 -> 11 ;

@ -1,5 +1,5 @@
digraph iCFG {
41 [label="41: DeclStmt \n n$7=_fun___objc_alloc_no_fail(sizeof(class NSAutoreleasePool ):unsigned long ) [line 60]\n n$5=_fun_NSAutoreleasePool_init(n$7:class NSAutoreleasePool *) [line 60]\n *&pool:class NSAutoreleasePool *=n$5 [line 60]\n REMOVE_TEMPS(n$5,n$7); [line 60]\n " shape="box"]
41 [label="41: DeclStmt \n n$7=_fun___objc_alloc_no_fail(sizeof(class NSAutoreleasePool ):unsigned long ) [line 60]\n n$5=_fun_NSObject_init(n$7:class NSAutoreleasePool *) virtual [line 60]\n *&pool:class NSAutoreleasePool *=n$5 [line 60]\n REMOVE_TEMPS(n$5,n$7); [line 60]\n " shape="box"]
41 -> 40 ;
@ -104,7 +104,7 @@ digraph iCFG {
15 -> 25 ;
14 [label="14: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 30]\n n$2=_fun_A_init(n$4:class A *) virtual [line 30]\n *&s1:class A *=n$2 [line 30]\n REMOVE_TEMPS(n$2,n$4); [line 30]\n " shape="box"]
14 [label="14: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 30]\n n$2=_fun_NSObject_init(n$4:class A *) virtual [line 30]\n *&s1:class A *=n$2 [line 30]\n REMOVE_TEMPS(n$2,n$4); [line 30]\n " shape="box"]
14 -> 13 ;

@ -1,5 +1,5 @@
digraph iCFG {
5 [label="5: DeclStmt \n n$5=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 21]\n n$3=_fun_A_init(n$5:class A *) virtual [line 21]\n *&a:class A *=n$3 [line 21]\n REMOVE_TEMPS(n$3,n$5); [line 21]\n " shape="box"]
5 [label="5: DeclStmt \n n$5=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 21]\n n$3=_fun_NSObject_init(n$5:class A *) virtual [line 21]\n *&a:class A *=n$3 [line 21]\n REMOVE_TEMPS(n$3,n$5); [line 21]\n " shape="box"]
5 -> 4 ;

@ -23,7 +23,7 @@ digraph iCFG {
27 -> 30 ;
27 -> 31 ;
26 [label="26: DeclStmt \n n$5=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 62]\n n$3=_fun_A_init(n$5:class A *) virtual [line 62]\n *&a:class A *=n$3 [line 62]\n REMOVE_TEMPS(n$3,n$5); [line 62]\n " shape="box"]
26 [label="26: DeclStmt \n n$5=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 62]\n n$3=_fun_NSObject_init(n$5:class A *) virtual [line 62]\n *&a:class A *=n$3 [line 62]\n REMOVE_TEMPS(n$3,n$5); [line 62]\n " shape="box"]
26 -> 25 ;
@ -42,7 +42,7 @@ digraph iCFG {
22 -> 26 ;
21 [label="21: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 55]\n n$1=_fun_A_init(n$3:class A *) virtual [line 55]\n *&a:class A *=n$1 [line 55]\n REMOVE_TEMPS(n$1,n$3); [line 55]\n " shape="box"]
21 [label="21: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 55]\n n$1=_fun_NSObject_init(n$3:class A *) virtual [line 55]\n *&a:class A *=n$1 [line 55]\n REMOVE_TEMPS(n$1,n$3); [line 55]\n " shape="box"]
21 -> 20 ;
@ -98,7 +98,7 @@ digraph iCFG {
7 -> 10 ;
6 [label="6: DeclStmt \n n$6=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 26]\n n$4=_fun_A_init(n$6:class A *) virtual [line 26]\n *&a:class A *=n$4 [line 26]\n REMOVE_TEMPS(n$4,n$6); [line 26]\n " shape="box"]
6 [label="6: DeclStmt \n n$6=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 26]\n n$4=_fun_NSObject_init(n$6:class A *) virtual [line 26]\n *&a:class A *=n$4 [line 26]\n REMOVE_TEMPS(n$4,n$6); [line 26]\n " shape="box"]
6 -> 5 ;

@ -26,7 +26,7 @@ digraph iCFG {
9 -> 15 ;
8 [label="8: DeclStmt \n n$8=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 28]\n n$6=_fun_A_init(n$8:class A *) virtual [line 28]\n *&a:class A *=n$6 [line 28]\n REMOVE_TEMPS(n$6,n$8); [line 28]\n " shape="box"]
8 [label="8: DeclStmt \n n$8=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 28]\n n$6=_fun_NSObject_init(n$8:class A *) virtual [line 28]\n *&a:class A *=n$6 [line 28]\n REMOVE_TEMPS(n$6,n$8); [line 28]\n " shape="box"]
8 -> 7 ;
@ -41,7 +41,7 @@ digraph iCFG {
5 -> 8 ;
4 [label="4: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 23]\n n$1=_fun_A_init(n$3:class A *) virtual [line 23]\n *&a:class A *=n$1 [line 23]\n REMOVE_TEMPS(n$1,n$3); [line 23]\n " shape="box"]
4 [label="4: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 23]\n n$1=_fun_NSObject_init(n$3:class A *) virtual [line 23]\n *&a:class A *=n$1 [line 23]\n REMOVE_TEMPS(n$1,n$3); [line 23]\n " shape="box"]
4 -> 3 ;

@ -63,7 +63,7 @@ digraph iCFG {
4 -> 9 ;
3 [label="3: Return Stmt \n n$1=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 25]\n n$2=_fun_A_init(n$1:class A *) virtual [line 25]\n *&return:class A *=n$2 [line 25]\n n$3=_fun___set_autorelease_attribute(n$2:class A *) [line 25]\n REMOVE_TEMPS(n$1,n$2,n$3); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"]
3 [label="3: Return Stmt \n n$1=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 25]\n n$2=_fun_NSObject_init(n$1:class A *) virtual [line 25]\n *&return:class A *=n$2 [line 25]\n n$3=_fun___set_autorelease_attribute(n$2:class A *) [line 25]\n REMOVE_TEMPS(n$1,n$2,n$3); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"]
3 -> 2 ;

@ -3,7 +3,7 @@ digraph iCFG {
60 -> 55 ;
59 [label="59: BinaryOperatorStmt: Assign \n n$57=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 71]\n n$55=_fun_A_init(n$57:class A *) virtual [line 71]\n *&#GB$A_dispatch_barrier_example_a:class A *=n$55 [line 71]\n REMOVE_TEMPS(n$55,n$57); [line 71]\n " shape="box"]
59 [label="59: BinaryOperatorStmt: Assign \n n$57=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 71]\n n$55=_fun_NSObject_init(n$57:class A *) virtual [line 71]\n *&#GB$A_dispatch_barrier_example_a:class A *=n$55 [line 71]\n REMOVE_TEMPS(n$55,n$57); [line 71]\n " shape="box"]
59 -> 58 ;
@ -41,7 +41,7 @@ digraph iCFG {
50 -> 45 ;
49 [label="49: BinaryOperatorStmt: Assign \n n$47=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 62]\n n$45=_fun_A_init(n$47:class A *) virtual [line 62]\n *&#GB$A_dispatch_group_notify_example_a:class A *=n$45 [line 62]\n REMOVE_TEMPS(n$45,n$47); [line 62]\n " shape="box"]
49 [label="49: BinaryOperatorStmt: Assign \n n$47=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 62]\n n$45=_fun_NSObject_init(n$47:class A *) virtual [line 62]\n *&#GB$A_dispatch_group_notify_example_a:class A *=n$45 [line 62]\n REMOVE_TEMPS(n$45,n$47); [line 62]\n " shape="box"]
49 -> 48 ;
@ -79,7 +79,7 @@ digraph iCFG {
40 -> 35 ;
39 [label="39: BinaryOperatorStmt: Assign \n n$37=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 53]\n n$35=_fun_A_init(n$37:class A *) virtual [line 53]\n *&#GB$A_dispatch_group_example_a:class A *=n$35 [line 53]\n REMOVE_TEMPS(n$35,n$37); [line 53]\n " shape="box"]
39 [label="39: BinaryOperatorStmt: Assign \n n$37=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 53]\n n$35=_fun_NSObject_init(n$37:class A *) virtual [line 53]\n *&#GB$A_dispatch_group_example_a:class A *=n$35 [line 53]\n REMOVE_TEMPS(n$35,n$37); [line 53]\n " shape="box"]
39 -> 38 ;
@ -117,7 +117,7 @@ digraph iCFG {
30 -> 25 ;
29 [label="29: BinaryOperatorStmt: Assign \n n$27=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 44]\n n$25=_fun_A_init(n$27:class A *) virtual [line 44]\n *&#GB$A_dispatch_after_example_a:class A *=n$25 [line 44]\n REMOVE_TEMPS(n$25,n$27); [line 44]\n " shape="box"]
29 [label="29: BinaryOperatorStmt: Assign \n n$27=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 44]\n n$25=_fun_NSObject_init(n$27:class A *) virtual [line 44]\n *&#GB$A_dispatch_after_example_a:class A *=n$25 [line 44]\n REMOVE_TEMPS(n$25,n$27); [line 44]\n " shape="box"]
29 -> 28 ;
@ -155,7 +155,7 @@ digraph iCFG {
20 -> 15 ;
19 [label="19: BinaryOperatorStmt: Assign \n n$17=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 34]\n n$15=_fun_A_init(n$17:class A *) virtual [line 34]\n *&#GB$A_dispatch_async_example_a:class A *=n$15 [line 34]\n REMOVE_TEMPS(n$15,n$17); [line 34]\n " shape="box"]
19 [label="19: BinaryOperatorStmt: Assign \n n$17=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 34]\n n$15=_fun_NSObject_init(n$17:class A *) virtual [line 34]\n *&#GB$A_dispatch_async_example_a:class A *=n$15 [line 34]\n REMOVE_TEMPS(n$15,n$17); [line 34]\n " shape="box"]
19 -> 18 ;
@ -193,7 +193,7 @@ digraph iCFG {
10 -> 5 ;
9 [label="9: BinaryOperatorStmt: Assign \n n$7=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 25]\n n$5=_fun_A_init(n$7:class A *) virtual [line 25]\n *&#GB$A_dispatch_once_example_a:class A *=n$5 [line 25]\n REMOVE_TEMPS(n$5,n$7); [line 25]\n " shape="box"]
9 [label="9: BinaryOperatorStmt: Assign \n n$7=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 25]\n n$5=_fun_NSObject_init(n$7:class A *) virtual [line 25]\n *&#GB$A_dispatch_once_example_a:class A *=n$5 [line 25]\n REMOVE_TEMPS(n$5,n$7); [line 25]\n " shape="box"]
9 -> 8 ;

@ -1,5 +1,5 @@
digraph iCFG {
39 [label="39: DeclStmt \n n$7=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 39]\n n$5=_fun_A_init(n$7:class A *) virtual [line 39]\n *&a:class A *=n$5 [line 39]\n REMOVE_TEMPS(n$5,n$7); [line 39]\n " shape="box"]
39 [label="39: DeclStmt \n n$7=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 39]\n n$5=_fun_NSObject_init(n$7:class A *) virtual [line 39]\n *&a:class A *=n$5 [line 39]\n REMOVE_TEMPS(n$5,n$7); [line 39]\n " shape="box"]
39 -> 38 ;
@ -96,7 +96,7 @@ digraph iCFG {
11 -> 13 ;
10 [label="10: DeclStmt \n n$13=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$11=_fun_A_init(n$13:class A *) virtual [line 27]\n *&other:class A *=n$11 [line 27]\n REMOVE_TEMPS(n$11,n$13); [line 27]\n " shape="box"]
10 [label="10: DeclStmt \n n$13=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$11=_fun_NSObject_init(n$13:class A *) virtual [line 27]\n *&other:class A *=n$11 [line 27]\n REMOVE_TEMPS(n$11,n$13); [line 27]\n " shape="box"]
10 -> 5 ;

@ -1,5 +1,5 @@
digraph iCFG {
6 [label="6: DeclStmt \n n$6=_fun___objc_alloc_no_fail(sizeof(class Car ):unsigned long ) [line 13]\n n$4=_fun_Car_init(n$6:class Car *) virtual [line 13]\n *&honda:class Car *=n$4 [line 13]\n REMOVE_TEMPS(n$4,n$6); [line 13]\n " shape="box"]
6 [label="6: DeclStmt \n n$6=_fun___objc_alloc_no_fail(sizeof(class Car ):unsigned long ) [line 13]\n n$4=_fun_NSObject_init(n$6:class Car *) virtual [line 13]\n *&honda:class Car *=n$4 [line 13]\n REMOVE_TEMPS(n$4,n$6); [line 13]\n " shape="box"]
6 -> 5 ;

@ -42,7 +42,7 @@ digraph iCFG {
41 -> 43 ;
40 [label="40: Message Call: init \n n$19=*&self:class A * [line 88]\n n$18=_fun_C_init(n$19:class A *) [line 88]\n REMOVE_TEMPS(n$18,n$19); [line 88]\n NULLIFY(&self,false); [line 88]\n APPLY_ABSTRACTION; [line 88]\n " shape="box"]
40 [label="40: Message Call: init \n n$19=*&self:class A * [line 88]\n n$18=_fun_NSObject_init(n$19:class A *) [line 88]\n REMOVE_TEMPS(n$18,n$19); [line 88]\n NULLIFY(&self,false); [line 88]\n APPLY_ABSTRACTION; [line 88]\n " shape="box"]
40 -> 39 ;
@ -75,7 +75,7 @@ digraph iCFG {
32 -> 34 ;
31 [label="31: DeclStmt \n n$12=_fun___objc_alloc_no_fail(sizeof(class B ):unsigned long ) [line 75]\n n$13=_fun_B_init(n$12:class B *) virtual [line 75]\n *&b:class B *=n$13 [line 75]\n REMOVE_TEMPS(n$12,n$13); [line 75]\n NULLIFY(&b,false); [line 75]\n " shape="box"]
31 [label="31: DeclStmt \n n$12=_fun___objc_alloc_no_fail(sizeof(class B ):unsigned long ) [line 75]\n n$13=_fun_NSObject_init(n$12:class B *) virtual [line 75]\n *&b:class B *=n$13 [line 75]\n REMOVE_TEMPS(n$12,n$13); [line 75]\n NULLIFY(&b,false); [line 75]\n " shape="box"]
31 -> 30 ;

@ -1,5 +1,5 @@
digraph iCFG {
4 [label="4: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 13]\n n$0=_fun_A_init(n$2:class A *) virtual [line 13]\n *&a:class A *=n$0 [line 13]\n REMOVE_TEMPS(n$0,n$2); [line 13]\n NULLIFY(&a,false); [line 13]\n " shape="box"]
4 [label="4: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 13]\n n$0=_fun_NSObject_init(n$2:class A *) virtual [line 13]\n *&a:class A *=n$0 [line 13]\n REMOVE_TEMPS(n$0,n$2); [line 13]\n NULLIFY(&a,false); [line 13]\n " shape="box"]
4 -> 3 ;

@ -7,7 +7,7 @@ digraph iCFG {
7 -> 6 ;
6 [label="6: InitListExp \n n$1=*&c1:class C * [line 24]\n n$0=_fun_C_init(n$1:class C *) virtual [line 24]\n n$2=*&c1:class C * [line 24]\n n$3=*&c2:class C * [line 24]\n *&a[0]:class C *=n$0 [line 24]\n _fun___objc_retain(n$2:class C *) [line 24]\n *&a[1]:class C *=n$2 [line 24]\n _fun___objc_retain(n$3:class C *) [line 24]\n *&a[2]:class C *=n$3 [line 24]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 24]\n NULLIFY(&c1,false); [line 24]\n NULLIFY(&c2,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"]
6 [label="6: InitListExp \n n$1=*&c1:class C * [line 24]\n n$0=_fun_NSObject_init(n$1:class C *) virtual [line 24]\n n$2=*&c1:class C * [line 24]\n n$3=*&c2:class C * [line 24]\n *&a[0]:class C *=n$0 [line 24]\n _fun___objc_retain(n$2:class C *) [line 24]\n *&a[1]:class C *=n$2 [line 24]\n _fun___objc_retain(n$3:class C *) [line 24]\n *&a[2]:class C *=n$3 [line 24]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 24]\n NULLIFY(&c1,false); [line 24]\n NULLIFY(&c2,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"]
6 -> 5 ;

Loading…
Cancel
Save