diff --git a/facebook-clang-plugins b/facebook-clang-plugins index 8133136d7..07c2aabb2 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit 8133136d734be727f8f0951c5a42b166b60cb1cd +Subproject commit 07c2aabb21fb201ac01b261095b665a53a00a9a1 diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 0e88a00ab..7229dd495 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -56,14 +56,25 @@ let rec translate_one_declaration tenv cg cfg parent_dec dec = let name = Ast_utils.get_qualified_name name_info in let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in ignore (ObjcCategory_decl.category_impl_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - CMethod_declImpl.process_methods tenv cg cfg curr_class decl_list + CMethod_declImpl.process_methods tenv cg cfg curr_class decl_list; + (match Ast_utils.get_decl_opt_with_decl_ref ocidi.Clang_ast_t.ocidi_category_decl with + | Some ObjCCategoryDecl(_, _, cat_decl_list, _, _) -> + let name = CContext.get_curr_class_name curr_class in + let decls = cat_decl_list @ decl_list in + CFrontend_errors.check_for_property_errors cfg cg tenv name decl_info decls + | _ -> ()) | ObjCImplementationDecl(decl_info, name_info, decl_list, decl_context_info, idi) -> let curr_class = ObjcInterface_decl.get_curr_class_impl idi in let type_ptr_to_sil_type = CTypes_decl.type_ptr_to_sil_type in ignore (ObjcInterface_decl.interface_impl_declaration type_ptr_to_sil_type tenv dec); CMethod_declImpl.process_methods tenv cg cfg curr_class decl_list; - CFrontend_errors.check_for_property_errors cfg cg tenv curr_class decl_info + (match Ast_utils.get_decl_opt_with_decl_ref idi.Clang_ast_t.oidi_class_interface with + | Some ObjCInterfaceDecl(_, _, cl_decl_list, _, _) -> + let name = CContext.get_curr_class_name curr_class in + let decls = cl_decl_list @ decl_list in + CFrontend_errors.check_for_property_errors cfg cg tenv name decl_info decls + | _ -> ()) | CXXMethodDecl (decl_info, name_info, type_ptr, function_decl_info, _) | CXXConstructorDecl (decl_info, name_info, type_ptr, function_decl_info, _) -> diff --git a/infer/src/clang/cFrontend_checkers.ml b/infer/src/clang/cFrontend_checkers.ml index 8d5c1fc47..90f9ea04d 100644 --- a/infer/src/clang/cFrontend_checkers.ml +++ b/infer/src/clang/cFrontend_checkers.ml @@ -14,14 +14,14 @@ open General_utils (* === Warnings on properties === *) (* Strong Delegate Warning: a property with name delegate should not be declared strong *) -let checker_strong_delegate_warning class_decl_info pname ptype = +let checker_strong_delegate_warning class_decl_info pname obj_c_property_decl_info = Printing.log_out "Checking for STRONG_DELEGATE property warning\n"; let delegate_regexp = Str.regexp_string_case_fold "delegate" in let pname_contains_delegate = try Str.search_forward delegate_regexp pname.Clang_ast_t.ni_name 0 >= 0 with Not_found -> false in let condition = pname_contains_delegate - && ObjcProperty_decl.is_strong_property ptype in + && ObjcProperty_decl.is_strong_property obj_c_property_decl_info in let warning_desc = { name = "STRONG_DELEGATE_WARNING"; description = "Property or ivar "^pname.Clang_ast_t.ni_name^" declared strong"; diff --git a/infer/src/clang/cFrontend_checkers.mli b/infer/src/clang/cFrontend_checkers.mli index 83d6ca9d3..f5caebf6a 100644 --- a/infer/src/clang/cFrontend_checkers.mli +++ b/infer/src/clang/cFrontend_checkers.mli @@ -12,8 +12,7 @@ (* Strong Delegate Warning: a property with name delegate should not be declared strong *) val checker_strong_delegate_warning : Clang_ast_t.decl_info -> Clang_ast_t.named_decl_info -> - ObjcProperty_decl.property_type -> - (bool * CFrontend_utils.General_utils.warning_desc) + Clang_ast_t.obj_c_property_decl_info -> (bool * CFrontend_utils.General_utils.warning_desc) (* Direct Atomic Property access: a property declared atomic should not be accesses directly via its iva *) diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index 0595b6788..be4d9d0d6 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -36,18 +36,22 @@ let log_frontend_warning pdesc warn_desc = Reporting.log_error_from_errlog errlog exn ~loc:(Some loc) (* Call all checkers on properties of class c *) -let check_for_property_errors cfg cg tenv c decl_info = - let class_name = CContext.get_curr_class_name c in - let do_one_property (pname, property) = +let rec check_for_property_errors cfg cg tenv class_name class_decl_info decl_list = + let open Clang_ast_t in + let do_one_property decl_info pname_info pdi = IList.iter (fun checker -> - let (condition, warning_desc) = checker decl_info pname property in + let (condition, warning_desc) = checker class_decl_info pname_info pdi in if condition then let proc_desc = CMethod_trans.get_method_for_frontend_checks cfg cg tenv class_name decl_info in log_frontend_warning proc_desc warning_desc) property_checkers_list in - let properties = ObjcProperty_decl.find_properties_class c in - Printing.log_out "Retrieved all properties of the class...\n"; - IList.iter do_one_property properties + match decl_list with + | [] -> () + | ObjCPropertyDecl (decl_info, pname_info, pdi) :: rest -> + do_one_property decl_info pname_info pdi; + check_for_property_errors cfg cg tenv class_name class_decl_info rest + | _ :: rest -> + check_for_property_errors cfg cg tenv class_name class_decl_info rest (* Call checkers on a specific access of an ivar *) let check_for_ivar_errors context stmt_info obj_c_ivar_ref_expr_info = diff --git a/infer/src/clang/cFrontend_errors.mli b/infer/src/clang/cFrontend_errors.mli index 6e9f7dfe2..3c54dbd91 100644 --- a/infer/src/clang/cFrontend_errors.mli +++ b/infer/src/clang/cFrontend_errors.mli @@ -12,8 +12,8 @@ (* Checks for warnings on properties of class c *) -val check_for_property_errors : Cfg.cfg -> Cg.t -> Sil.tenv -> CContext.curr_class -> - Clang_ast_t.decl_info -> unit +val check_for_property_errors : Cfg.cfg -> Cg.t -> Sil.tenv -> string -> Clang_ast_t.decl_info -> + Clang_ast_t.decl list -> unit (* Call checkers on a specific access of an ivar *) val check_for_ivar_errors : diff --git a/infer/src/clang/objcProperty_decl.ml b/infer/src/clang/objcProperty_decl.ml index dab67756b..882ff6de3 100644 --- a/infer/src/clang/objcProperty_decl.ml +++ b/infer/src/clang/objcProperty_decl.ml @@ -200,8 +200,8 @@ let check_for_property curr_class method_name meth_decl body = check_property_accessor curr_class method_name true; check_property_accessor curr_class method_name false -let is_strong_property property_type = - let _, attrs, _, _, _, _ = property_type in +let is_strong_property obj_c_property_decl_info = + let attrs = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in IList.exists (fun a -> match a with | `Strong -> true | _ -> false) attrs diff --git a/infer/src/clang/objcProperty_decl.mli b/infer/src/clang/objcProperty_decl.mli index bb082bad0..d34e4feaf 100644 --- a/infer/src/clang/objcProperty_decl.mli +++ b/infer/src/clang/objcProperty_decl.mli @@ -64,4 +64,4 @@ val find_properties_class : CContext.curr_class -> (Clang_ast_t.named_decl_info * property_type) list (* Given a property type returns whether the property is strong *) -val is_strong_property : property_type -> bool +val is_strong_property : Clang_ast_t.obj_c_property_decl_info -> bool