Marking getters/setters as builtins only inside the definition of the class

Reviewed By: ddino

Differential Revision: D3292534

fbshipit-source-id: 23fc4ec
master
Dulma Churchill 9 years ago committed by Facebook Github Bot 6
parent 6e75c1e33f
commit 9b1bd712b5

@ -106,21 +106,3 @@ let is_ivar_atomic ivar fields =
with Not_found -> ( with Not_found -> (
Printing.log_out "NOT Found field ivar = '%s' " (Ident.fieldname_to_string ivar); Printing.log_out "NOT Found field ivar = '%s' " (Ident.fieldname_to_string ivar);
false) false)
let get_property_corresponding_ivar tenv type_ptr_to_sil_type class_name property_decl =
let open Clang_ast_t in
match property_decl with
| ObjCPropertyDecl (_, named_decl_info, obj_c_property_decl_info) ->
(let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
match Ast_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
| Some ObjCIvarDecl (_, named_decl_info, _, _, _) ->
General_utils.mk_class_field_name named_decl_info
| _ -> (* Ivar is not known, so add a default one to the tenv *)
let type_ptr = obj_c_property_decl_info.Clang_ast_t.opdi_type_ptr in
let field_name_str = Ast_utils.generated_ivar_name named_decl_info in
let prop_attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in
let field_name, typ, attr = build_sil_field type_ptr_to_sil_type tenv
field_name_str type_ptr prop_attributes in
ignore (add_missing_fields tenv class_name Csu.Objc [(field_name, typ, attr)]);
field_name)
| _ -> assert false

@ -26,6 +26,3 @@ val build_sil_field : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.na
val add_missing_fields : Tenv.t -> string -> Csu.class_kind -> field_type list -> unit val add_missing_fields : Tenv.t -> string -> Csu.class_kind -> field_type list -> unit
val is_ivar_atomic : Ident.fieldname -> Sil.struct_fields -> bool val is_ivar_atomic : Ident.fieldname -> Sil.struct_fields -> bool
val get_property_corresponding_ivar : Tenv.t -> Ast_utils.type_ptr_to_sil_type -> string ->
Clang_ast_t.decl -> Ident.fieldname

@ -92,6 +92,36 @@ struct
None extra_instrs None extra_instrs
| None -> () | None -> ()
let process_property_implementation obj_c_property_impl_decl_info =
let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in
match Ast_utils.get_decl_opt_with_decl_ref property_decl_opt with
| Some ObjCPropertyDecl (_, _, obj_c_property_decl_info) ->
let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
(match Ast_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
| Some ObjCIvarDecl (_, named_decl_info, _, _, _) ->
let field_name = General_utils.mk_class_field_name named_decl_info in
let process_accessor pointer ~getter =
(match Ast_utils.get_decl_opt_with_decl_ref pointer with
| Some ObjCMethodDecl (decl_info, name_info, mdi) ->
let source_range = decl_info.Clang_ast_t.di_source_range in
let loc = CLocation.get_sil_location_from_range source_range true in
let property_accessor =
if getter then
Some (ProcAttributes.Objc_getter field_name)
else
Some (ProcAttributes.Objc_setter field_name) in
let class_name = Ast_utils.get_class_name_from_member name_info in
let procname = CMethod_trans.get_objc_method_name name_info mdi class_name in
let attrs = { (ProcAttributes.default procname Config.Clang) with
loc = loc;
objc_accessor = property_accessor; } in
AttributesTable.store_attributes attrs
| _ -> ()) in
process_accessor obj_c_property_decl_info.Clang_ast_t.opdi_getter_method ~getter:true;
process_accessor obj_c_property_decl_info.Clang_ast_t.opdi_setter_method ~getter:false
| _ -> ())
| _ -> ()
let process_one_method_decl tenv cg cfg curr_class dec = let process_one_method_decl tenv cg cfg curr_class dec =
let open Clang_ast_t in let open Clang_ast_t in
match dec with match dec with
@ -99,7 +129,9 @@ struct
process_method_decl tenv cg cfg curr_class dec ~is_objc:false process_method_decl tenv cg cfg curr_class dec ~is_objc:false
| ObjCMethodDecl _ -> | ObjCMethodDecl _ ->
process_method_decl tenv cg cfg curr_class dec ~is_objc:true process_method_decl tenv cg cfg curr_class dec ~is_objc:true
| ObjCPropertyImplDecl _ | EmptyDecl _ | ObjCPropertyImplDecl (_, obj_c_property_impl_decl_info) ->
process_property_implementation obj_c_property_impl_decl_info
| EmptyDecl _
| ObjCIvarDecl _ | ObjCPropertyDecl _ -> () | ObjCIvarDecl _ | ObjCPropertyDecl _ -> ()
| _ -> | _ ->
Printing.log_stats Printing.log_stats

@ -150,6 +150,12 @@ let get_init_list_instrs method_decl_info =
let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in
IList.map create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers IList.map create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers
let get_objc_method_name name_info mdi class_name =
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
General_utils.mk_procname_from_objc_method class_name method_name method_kind
let method_signature_of_decl tenv meth_decl block_data_opt = let method_signature_of_decl tenv meth_decl block_data_opt =
let open Clang_ast_t in let open Clang_ast_t in
match meth_decl, block_data_opt with match meth_decl, block_data_opt with
@ -176,11 +182,8 @@ let method_signature_of_decl tenv meth_decl block_data_opt =
let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *) 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) ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs)
| ObjCMethodDecl (decl_info, name_info, mdi), _ -> | ObjCMethodDecl (decl_info, name_info, mdi), _ ->
let method_name = name_info.ni_name 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
let is_instance = mdi.omdi_is_instance_method in let procname = get_objc_method_name name_info mdi class_name in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
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 method_decl = ObjC_Meth_decl_info (mdi, class_name) in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
let pointer_to_property_opt = let pointer_to_property_opt =
@ -284,20 +287,12 @@ let get_objc_method_data obj_c_message_expr_info =
| `Class _ | `Class _
| `SuperClass -> (selector, pointer, MCStatic) | `SuperClass -> (selector, pointer, MCStatic)
let get_objc_property_accessor tenv ms = let skip_property_accessor ms =
let open Clang_ast_t in let open Clang_ast_t in
let pointer_to_property_opt = CMethod_signature.ms_get_pointer_to_property_opt ms 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, CMethod_signature.ms_get_name ms with match Ast_utils.get_decl_opt pointer_to_property_opt with
| Some (ObjCPropertyDecl _ as d), Procname.ObjC_Cpp objc_cpp -> | Some (ObjCPropertyDecl _ as d) -> true
let class_name = Procname.objc_cpp_get_class_name objc_cpp in | _ -> false
let field_name = CField_decl.get_property_corresponding_ivar tenv
CTypes_decl.type_ptr_to_sil_type class_name d in
if CMethod_signature.ms_is_getter ms then
Some (ProcAttributes.Objc_getter field_name)
else if CMethod_signature.ms_is_setter ms then
Some (ProcAttributes.Objc_setter field_name)
else None
| _ -> None
let get_formal_parameters tenv ms = let get_formal_parameters tenv ms =
let rec defined_parameters pl = let rec defined_parameters pl =
@ -379,30 +374,31 @@ let create_local_procdesc cfg tenv ms fbody captured is_objc_inst_method =
let loc_exit = CLocation.get_sil_location_from_range source_range false in let loc_exit = CLocation.get_sil_location_from_range source_range false in
let ret_type = get_return_type tenv ms in let ret_type = get_return_type tenv ms in
let captured' = IList.map (fun (var, t) -> (Pvar.get_name var, t)) captured in let captured' = IList.map (fun (var, t) -> (Pvar.get_name var, t)) captured in
let procdesc = if skip_property_accessor ms then ()
let proc_attributes = else
{ (ProcAttributes.default proc_name Config.Clang) with let procdesc =
ProcAttributes.captured = captured'; let proc_attributes =
ProcAttributes.objc_accessor = get_objc_property_accessor tenv ms; { (ProcAttributes.default proc_name Config.Clang) with
formals; ProcAttributes.captured = captured';
func_attributes = attributes; formals;
is_defined = defined; func_attributes = attributes;
is_objc_instance_method = is_objc_inst_method; is_defined = defined;
is_cpp_instance_method = is_cpp_inst_method; is_objc_instance_method = is_objc_inst_method;
loc = loc_start; is_cpp_instance_method = is_cpp_inst_method;
method_annotation; loc = loc_start;
ret_type; method_annotation;
} in ret_type;
Cfg.Procdesc.create cfg proc_attributes in } in
if defined then Cfg.Procdesc.create cfg proc_attributes in
(if !Config.arc_mode then if defined then
Cfg.Procdesc.set_flag procdesc Mleak_buckets.objc_arc_flag "true"; (if !Config.arc_mode then
let start_kind = Cfg.Node.Start_node procdesc in Cfg.Procdesc.set_flag procdesc Mleak_buckets.objc_arc_flag "true";
let start_node = Cfg.Node.create cfg loc_start start_kind [] procdesc in let start_kind = Cfg.Node.Start_node procdesc in
let exit_kind = Cfg.Node.Exit_node procdesc in let start_node = Cfg.Node.create cfg loc_start start_kind [] procdesc in
let exit_node = Cfg.Node.create cfg loc_exit exit_kind [] procdesc in let exit_kind = Cfg.Node.Exit_node procdesc in
Cfg.Procdesc.set_start_node procdesc start_node; let exit_node = Cfg.Node.create cfg loc_exit exit_kind [] procdesc in
Cfg.Procdesc.set_exit_node procdesc exit_node) in Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node) in
if should_create_procdesc cfg proc_name defined then if should_create_procdesc cfg proc_name defined then
(create_new_procdesc (); true) (create_new_procdesc (); true)
else false else false

@ -55,3 +55,6 @@ val get_method_for_frontend_checks : Cfg.cfg -> Cg.t -> Location.t -> Cfg.Procde
val add_default_method_for_class : string -> Clang_ast_t.decl_info -> unit val add_default_method_for_class : string -> Clang_ast_t.decl_info -> unit
val get_procname_from_cpp_lambda : CContext.t -> Clang_ast_t.decl -> Procname.t val get_procname_from_cpp_lambda : CContext.t -> Clang_ast_t.decl -> Procname.t
val get_objc_method_name : Clang_ast_t.named_decl_info -> Clang_ast_t.obj_c_method_decl_info ->
string -> Procname.t

@ -17,26 +17,41 @@
@property(nonatomic, strong) BB* b; @property(nonatomic, strong) BB* b;
@end @end
@implementation AA
@end
@interface BBStrong : NSObject @interface BBStrong : NSObject
@property(nonatomic, strong) AA* a; @property(nonatomic, strong) AA* a;
@end @end
@implementation BBStrong
@end
@interface BBUnsafeUnretained : NSObject @interface BBUnsafeUnretained : NSObject
@property(nonatomic, unsafe_unretained) AA* a; @property(nonatomic, unsafe_unretained) AA* a;
@end @end
@implementation BBUnsafeUnretained
@end
@interface BBWeak : NSObject @interface BBWeak : NSObject
@property(nonatomic, weak) AA* a; @property(nonatomic, weak) AA* a;
@end @end
@implementation BBWeak
@end
@interface BBAssign : NSObject @interface BBAssign : NSObject
@property(nonatomic, assign) AA* a; @property(nonatomic, assign) AA* a;
@end @end
@implementation BBAssign
@end
int strongcycle() { int strongcycle() {
AA* a_obj = [AA alloc]; AA* a_obj = [AA alloc];

@ -57,7 +57,6 @@ public class GetterBuiltinTest {
DIVIDE_BY_ZERO, DIVIDE_BY_ZERO,
FILE, FILE,
new String[]{ new String[]{
"should_have_div0",
} }
) )
); );

Loading…
Cancel
Save