Using the link from method decl to property to determine whether the method is accessor

Summary:
public Using the new information from the plugin that links method decls in objc with their
properties if they are getters. Setters to be done in next diff.

Reviewed By: ddino

Differential Revision: D2729511

fb-gh-sync-id: dc58894
master
Dulma Rodriguez 9 years ago committed by facebook-github-bot-7
parent 3b919179bc
commit 9c9504ba51

@ -20,7 +20,7 @@ type method_signature = {
_is_generated : bool;
_language : CFrontend_config.lang;
_pointer_to_parent : Clang_ast_t.pointer option;
mutable _objc_accessor : ProcAttributes.objc_accessor_type option;
_pointer_to_property_opt : Clang_ast_t.pointer option; (* If set then method is a getter/setter *)
}
let ms_get_name ms =
@ -53,13 +53,17 @@ let ms_get_lang ms =
let ms_get_pointer_to_parent ms =
ms._pointer_to_parent
let ms_objc_accessor ms =
ms._objc_accessor
let ms_get_pointer_to_property_opt ms =
ms._pointer_to_property_opt
let ms_set_objc_accessor ms objc_accessor =
ms._objc_accessor <- objc_accessor
(* A method is a getter if it has a link to a property and *)
(* it has 1 argument (this includes self) *)
let ms_is_getter ms =
Option.is_some ms._pointer_to_property_opt &&
IList.length ms._args == 1
let make_ms procname args ret_type attributes loc is_instance is_generated lang pointer_to_parent =
let make_ms procname args ret_type attributes loc is_instance is_generated lang pointer_to_parent
pointer_to_property_opt =
let meth_signature = {
_name = procname;
_args = args;
@ -70,7 +74,7 @@ let make_ms procname args ret_type attributes loc is_instance is_generated lang
_is_generated = is_generated;
_language = lang;
_pointer_to_parent = pointer_to_parent;
_objc_accessor = None
_pointer_to_property_opt = pointer_to_property_opt;
} in
meth_signature

@ -31,16 +31,16 @@ val ms_get_lang : method_signature -> CFrontend_config.lang
val ms_get_pointer_to_parent : method_signature -> Clang_ast_t.pointer option
val ms_get_pointer_to_property_opt : method_signature -> Clang_ast_t.pointer option
val ms_is_getter : method_signature -> bool
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
-> Clang_ast_t.pointer option -> method_signature
-> Clang_ast_t.pointer option -> Clang_ast_t.pointer option -> method_signature
val replace_name_ms : method_signature -> Procname.t -> method_signature
val ms_to_string : method_signature -> string
val ms_is_generated : method_signature -> bool
val ms_objc_accessor : method_signature -> ProcAttributes.objc_accessor_type option
val ms_set_objc_accessor : method_signature -> ProcAttributes.objc_accessor_type option -> unit

@ -87,7 +87,7 @@ let get_return_type function_method_decl_info =
| 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 parent_pointer =
is_generated parent_pointer pointer_to_property_opt =
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
@ -96,7 +96,7 @@ let build_method_signature decl_info procname function_method_decl_info is_anony
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 parent_pointer
lang parent_pointer pointer_to_property_opt
let get_assume_not_null_calls param_decls =
let do_one_param decl = match decl with
@ -120,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 None in
let ms = build_method_signature decl_info procname func_decl false false None None in
let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in
ms, fdi.Clang_ast_t.fdi_body, extra_instrs
| CXXMethodDecl (decl_info, name_info, tp, fdi, mdi), _
@ -130,7 +130,8 @@ let method_signature_of_decl meth_decl block_data_opt =
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 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 ms = build_method_signature decl_info procname method_decl false false parent_pointer
None in
let non_null_instrs = get_assume_not_null_calls 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)
@ -143,13 +144,17 @@ let method_signature_of_decl meth_decl block_data_opt =
let method_decl = ObjC_Meth_decl_info (mdi, class_name) in
let is_generated = Ast_utils.is_generated name_info 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 pointer_to_property_opt =
match mdi.Clang_ast_t.omdi_property_decl with
| Some decl_ref -> Some decl_ref.Clang_ast_t.dr_decl_pointer
| None -> None in
let ms = build_method_signature decl_info procname method_decl false is_generated
parent_pointer pointer_to_property_opt in
let extra_instrs = get_assume_not_null_calls 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 None in
let ms = build_method_signature decl_info procname func_decl true false None None in
let extra_instrs = get_assume_not_null_calls bdi.bdi_parameters in
ms, bdi.bdi_body, extra_instrs
| _ -> raise Invalid_declaration
@ -235,6 +240,18 @@ let get_objc_method_data obj_c_message_expr_info =
| `Class _
| `SuperClass -> (selector, pointer, MCStatic)
let get_objc_property_accessor ms =
let open Clang_ast_t in
let pointer_to_property_opt = CMethod_signature.ms_get_pointer_to_property_opt ms in
match Ast_utils.get_decl_opt pointer_to_property_opt with
| Some ObjCPropertyDecl (decl_info, named_decl_info, obj_c_property_decl_info) ->
let field_name_str = Ast_utils.generated_ivar_name named_decl_info in
let field_name = General_utils.mk_class_field_name field_name_str in
if CMethod_signature.ms_is_getter ms then
Some (ProcAttributes.Objc_getter field_name)
else None (* Setter TODO *)
| _ -> None
let get_formal_parameters tenv ms =
let rec defined_parameters pl =
match pl with
@ -324,7 +341,7 @@ let create_local_procdesc cfg tenv ms fbody captured is_objc_inst_method =
let proc_attributes =
{ (ProcAttributes.default proc_name Config.C_CPP) with
ProcAttributes.captured = captured';
ProcAttributes.objc_accessor = CMethod_signature.ms_objc_accessor ms;
ProcAttributes.objc_accessor = get_objc_property_accessor ms;
formals;
func_attributes = attributes;
is_defined = defined;
@ -407,7 +424,7 @@ let get_method_for_frontend_checks cfg cg tenv class_name decl_info =
| Some pdesc -> pdesc
| None ->
let ms = CMethod_signature.make_ms proc_name [] (Clang_ast_types.pointer_to_type_ptr "-1")
[] source_range false false CFrontend_config.OBJC None in
[] source_range false false CFrontend_config.OBJC None None in
let body = [Clang_ast_t.CompoundStmt (stmt_info, [])] in
ignore (create_local_procdesc cfg tenv ms body [] false);
let pdesc = Option.get (Cfg.Procdesc.find_from_name cfg proc_name) in

@ -35,7 +35,7 @@ struct
(* 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 property_accessor_opt =
let get_callee_objc_method context obj_c_message_expr_info act_params =
let open CContext in
let (selector, method_pointer_opt, mc_type) =
CMethod_trans.get_objc_method_data obj_c_message_expr_info in
@ -62,10 +62,9 @@ struct
CMethod_signature.ms_get_name ms, CMethod_trans.MCNoVirtual
| None, Some ms ->
if not (M.process_getter_setter context procname) then
(CMethod_signature.ms_set_objc_accessor ms property_accessor_opt;
ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv
(ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv
ms [] [] is_instance));
if Option.is_some property_accessor_opt then
if CMethod_signature.ms_is_getter ms then
procname, CMethod_trans.MCNoVirtual
else
procname, mc_type
@ -833,8 +832,7 @@ struct
obj_c_message_expr_info, 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
property_accessor_opt =
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
@ -854,7 +852,7 @@ struct
| 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
subexpr_exprs property_accessor_opt in
subexpr_exprs in
let res_trans_add_self = Self.add_self_parameter_for_super_instance context procname sil_loc
obj_c_message_expr_info in
let res_trans_subexpr_list = res_trans_add_self :: res_trans_subexpr_list in
@ -1603,20 +1601,6 @@ struct
| stmt :: _ -> instruction trans_state' stmt
| _ -> assert false in
match stmt_list with
| [ObjCPropertyRefExpr (_, _, _, oprei); _;
ObjCMessageExpr (si, stmts, info, ocmei)] ->
let property_accessor_opt =
match oprei.Clang_ast_t.oprei_kind with
| `PropertyRef decl_ref ->
(let create_field_name property_name =
General_utils.mk_class_field_name (Ast_utils.generated_ivar_name property_name) in
let field_name_opt = Option.map create_field_name decl_ref.Clang_ast_t.dr_name in
match field_name_opt with
| Some field_name when oprei.Clang_ast_t.oprei_is_messaging_getter ->
Some (ProcAttributes.Objc_getter field_name)
| _ -> None)
| _ -> None in
objCMessageExpr_trans trans_state si ocmei stmts info property_accessor_opt
| syntactic_form :: semantic_form ->
do_semantic_elements semantic_form
| _ -> assert false
@ -1911,7 +1895,6 @@ struct
block_enumeration_trans trans_state stmt_info stmt_list expr_info
else
objCMessageExpr_trans trans_state stmt_info obj_c_message_expr_info stmt_list expr_info
None
| CompoundStmt (stmt_info, stmt_list) ->
(* No node for this statement. We just collect its statement list*)

@ -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 None in
(Ast_expressions.dummy_source_range ()) false false lang None None in
Some ms
else None

@ -31,7 +31,7 @@ digraph iCFG {
4 -> 3 ;
3 [label="3: Message Call: description \n n$0=*&self:class ExceptionExample * [line 26]\n n$1=_fun_ExceptionExample_description(n$0:class ExceptionExample *) virtual [line 26]\n REMOVE_TEMPS(n$0,n$1); [line 26]\n NULLIFY(&self,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"]
3 [label="3: Message Call: description \n n$0=*&self:class ExceptionExample * [line 26]\n n$1=_fun_ExceptionExample_description(n$0:class ExceptionExample *) [line 26]\n REMOVE_TEMPS(n$0,n$1); [line 26]\n NULLIFY(&self,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"]
3 -> 2 ;

@ -7,7 +7,7 @@ digraph iCFG {
20 -> 15 ;
19 [label="19: BinaryOperatorStmt: AddAssign \n n$13=*&item:class NSArray * [line 29]\n n$14=_fun_NSArray_count(n$13:class NSArray *) virtual [line 29]\n n$15=*&size:int [line 29]\n *&size:int =(n$15 + n$14) [line 29]\n REMOVE_TEMPS(n$13,n$14,n$15); [line 29]\n NULLIFY(&item,false); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"]
19 [label="19: BinaryOperatorStmt: AddAssign \n n$13=*&item:class NSArray * [line 29]\n n$14=_fun_NSArray_count(n$13:class NSArray *) [line 29]\n n$15=*&size:int [line 29]\n *&size:int =(n$15 + n$14) [line 29]\n REMOVE_TEMPS(n$13,n$14,n$15); [line 29]\n NULLIFY(&item,false); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"]
19 -> 15 ;
@ -47,7 +47,7 @@ digraph iCFG {
10 -> 4 ;
9 [label="9: BinaryOperatorStmt: AddAssign \n n$4=*&item:class NSArray * [line 20]\n n$5=_fun_NSArray_count(n$4:class NSArray *) virtual [line 20]\n n$6=*&size:int [line 20]\n *&size:int =(n$6 + n$5) [line 20]\n REMOVE_TEMPS(n$4,n$5,n$6); [line 20]\n NULLIFY(&item,false); [line 20]\n " shape="box"]
9 [label="9: BinaryOperatorStmt: AddAssign \n n$4=*&item:class NSArray * [line 20]\n n$5=_fun_NSArray_count(n$4:class NSArray *) [line 20]\n n$6=*&size:int [line 20]\n *&size:int =(n$6 + n$5) [line 20]\n REMOVE_TEMPS(n$4,n$5,n$6); [line 20]\n NULLIFY(&item,false); [line 20]\n " shape="box"]
9 -> 8 ;

Loading…
Cancel
Save