[SelfInBlock] Add the procname to the is_no_escape_block flag to improve the error message of the weakSelf In Noescape block check

Summary: After looking at some reports with blocks inside blocks, it seemed more obvious that adding which method we are talking about makes more clear which block we are talking about.

Reviewed By: mityal

Differential Revision: D19789285

fbshipit-source-id: 20e0e6804
master
Dulma Churchill 5 years ago committed by Facebook Github Bot
parent 6076e22f18
commit 682f8c5355

@ -48,8 +48,9 @@ type t =
; is_bridge_method: bool (** the procedure is a bridge method *) ; is_bridge_method: bool (** the procedure is a bridge method *)
; is_defined: bool (** true if the procedure is defined, and not just declared *) ; is_defined: bool (** true if the procedure is defined, and not just declared *)
; is_java_synchronized_method: bool (** the procedure is a Java synchronized method *) ; is_java_synchronized_method: bool (** the procedure is a Java synchronized method *)
; is_no_escape_block: bool ; passed_as_noescape_block_to: Procname.t option
(** The procedure is an Objective-C block that has the NS_NOESCAPE attribute *) (** Present if the procedure is an Objective-C block that has been passed to the given
method in a position annotated with the NS_NOESCAPE attribute. *)
; is_no_return: bool (** the procedure is known not to return *) ; is_no_return: bool (** the procedure is known not to return *)
; is_specialized: bool (** the procedure is a clone specialized for dynamic dispatch handling *) ; is_specialized: bool (** the procedure is a clone specialized for dynamic dispatch handling *)
; is_synthetic_method: bool (** the procedure is a synthetic method *) ; is_synthetic_method: bool (** the procedure is a synthetic method *)
@ -76,7 +77,7 @@ let default translation_unit proc_name =
; is_bridge_method= false ; is_bridge_method= false
; is_defined= false ; is_defined= false
; is_java_synchronized_method= false ; is_java_synchronized_method= false
; is_no_escape_block= false ; passed_as_noescape_block_to= None
; is_no_return= false ; is_no_return= false
; is_specialized= false ; is_specialized= false
; is_synthetic_method= false ; is_synthetic_method= false
@ -108,7 +109,7 @@ let pp f
; is_bridge_method ; is_bridge_method
; is_defined ; is_defined
; is_java_synchronized_method ; is_java_synchronized_method
; is_no_escape_block ; passed_as_noescape_block_to
; is_no_return ; is_no_return
; is_specialized ; is_specialized
; is_synthetic_method ; is_synthetic_method
@ -149,7 +150,7 @@ let pp f
pp_bool_default ~default:default.is_defined "is_defined" is_defined f () ; pp_bool_default ~default:default.is_defined "is_defined" is_defined f () ;
pp_bool_default ~default:default.is_java_synchronized_method "is_java_synchronized_method" pp_bool_default ~default:default.is_java_synchronized_method "is_java_synchronized_method"
is_java_synchronized_method f () ; is_java_synchronized_method f () ;
pp_bool_default ~default:default.is_no_escape_block "is_no_escape_block" is_no_escape_block f () ; F.fprintf f "; passed_as_noescape_block_to %a" (Pp.option Procname.pp) passed_as_noescape_block_to ;
pp_bool_default ~default:default.is_no_return "is_no_return" is_no_return f () ; pp_bool_default ~default:default.is_no_return "is_no_return" is_no_return f () ;
pp_bool_default ~default:default.is_specialized "is_specialized" is_specialized f () ; pp_bool_default ~default:default.is_specialized "is_specialized" is_specialized f () ;
pp_bool_default ~default:default.is_synthetic_method "is_synthetic_method" is_synthetic_method f pp_bool_default ~default:default.is_synthetic_method "is_synthetic_method" is_synthetic_method f

@ -32,9 +32,9 @@ type t =
; is_bridge_method: bool (** the procedure is a bridge method *) ; is_bridge_method: bool (** the procedure is a bridge method *)
; is_defined: bool (** true if the procedure is defined, and not just declared *) ; is_defined: bool (** true if the procedure is defined, and not just declared *)
; is_java_synchronized_method: bool (** the procedure is a Java synchronized method *) ; is_java_synchronized_method: bool (** the procedure is a Java synchronized method *)
; is_no_escape_block: bool ; passed_as_noescape_block_to: Procname.t option
(** The procedure is an Objective-C block that is passed to a method in a position annotated (** Present if the procedure is an Objective-C block that has been passed to the given
with NS_NOESCAPE *) method in a position annotated with the NS_NOESCAPE attribute. *)
; is_no_return: bool (** the procedure is known not to return *) ; is_no_return: bool (** the procedure is known not to return *)
; is_specialized: bool (** the procedure is a clone specialized for dynamic dispatch handling *) ; is_specialized: bool (** the procedure is a clone specialized for dynamic dispatch handling *)
; is_synthetic_method: bool (** the procedure is a synthetic method *) ; is_synthetic_method: bool (** the procedure is a synthetic method *)

@ -409,12 +409,13 @@ let report_mix_self_weakself_issues summary domain (weakSelf : DomainData.t) (se
Reporting.log_error summary ~ltr ~loc:self.loc IssueType.mixed_self_weakself message Reporting.log_error summary ~ltr ~loc:self.loc IssueType.mixed_self_weakself message
let report_weakself_in_no_escape_block_issues summary domain (weakSelf : DomainData.t) = let report_weakself_in_no_escape_block_issues summary domain (weakSelf : DomainData.t) procname =
let message = let message =
F.asprintf F.asprintf
"This block uses `%a` at %a. This is probably not needed since the block is passed to a \ "This block uses `%a` at %a. This is probably not needed since the block is passed to the \
method in a position annotated with NS_NOESCAPE. Use `self` instead." method `%s` in a position annotated with NS_NOESCAPE. Use `self` instead."
(Pvar.pp Pp.text) weakSelf.pvar Location.pp weakSelf.loc (Pvar.pp Pp.text) weakSelf.pvar Location.pp weakSelf.loc
(Procname.to_simplified_string procname)
in in
let ltr = make_trace_use_self_weakself domain in let ltr = make_trace_use_self_weakself domain in
Reporting.log_error summary ~ltr ~loc:weakSelf.loc IssueType.weak_self_in_noescape_block message Reporting.log_error summary ~ltr ~loc:weakSelf.loc IssueType.weak_self_in_noescape_block message
@ -455,8 +456,11 @@ let report_issues summary domain attributes =
report_captured_strongself_issue domain summary domain_data ; report_captured_strongself_issue domain summary domain_data ;
(weakSelfList, selfList) (weakSelfList, selfList)
| DomainData.WEAK_SELF -> | DomainData.WEAK_SELF ->
if attributes.ProcAttributes.is_no_escape_block then ( match attributes.ProcAttributes.passed_as_noescape_block_to with
report_weakself_in_no_escape_block_issues summary domain domain_data ; | Some procname ->
report_weakself_in_no_escape_block_issues summary domain domain_data procname
| None ->
() ) ;
(domain_data :: weakSelfList, selfList) (domain_data :: weakSelfList, selfList)
| DomainData.SELF -> | DomainData.SELF ->
(weakSelfList, domain_data :: selfList) (weakSelfList, domain_data :: selfList)

@ -156,7 +156,7 @@ module BuildMethodSignature = struct
let method_signature_of_decl qual_type_to_sil_type tenv method_decl ?block_return_type let method_signature_of_decl qual_type_to_sil_type tenv method_decl ?block_return_type
?(is_no_escape_block = false) procname = ?(passed_as_noescape_block_to = None) procname =
let decl_info = Clang_ast_proj.get_decl_tuple method_decl in let decl_info = Clang_ast_proj.get_decl_tuple method_decl in
let loc = decl_info.Clang_ast_t.di_source_range in let loc = decl_info.Clang_ast_t.di_source_range in
let ret_type, return_param_typ, ret_typ_annot, has_added_return_param = let ret_type, return_param_typ, ret_typ_annot, has_added_return_param =
@ -182,7 +182,7 @@ module BuildMethodSignature = struct
; loc ; loc
; method_kind ; method_kind
; is_cpp_virtual ; is_cpp_virtual
; is_no_escape_block ; passed_as_noescape_block_to
; is_no_return ; is_no_return
; is_variadic ; is_variadic
; pointer_to_parent ; pointer_to_parent
@ -191,12 +191,12 @@ module BuildMethodSignature = struct
let method_signature_body_of_decl qual_type_to_sil_type tenv method_decl ?block_return_type let method_signature_body_of_decl qual_type_to_sil_type tenv method_decl ?block_return_type
?is_no_escape_block procname = ?passed_as_noescape_block_to procname =
let body = CMethodProperties.get_method_body method_decl in let body = CMethodProperties.get_method_body method_decl in
let init_list_instrs = CMethodProperties.get_init_list_instrs method_decl in let init_list_instrs = CMethodProperties.get_init_list_instrs method_decl in
let ms = let ms =
method_signature_of_decl qual_type_to_sil_type tenv method_decl ?block_return_type method_signature_of_decl qual_type_to_sil_type tenv method_decl ?block_return_type
?is_no_escape_block procname ?passed_as_noescape_block_to procname
in in
(ms, body, init_list_instrs) (ms, body, init_list_instrs)
end end

@ -53,7 +53,7 @@ val method_signature_of_decl :
Tenv.t Tenv.t
-> Clang_ast_t.decl -> Clang_ast_t.decl
-> ?block_return_type:Clang_ast_t.qual_type -> ?block_return_type:Clang_ast_t.qual_type
-> ?is_no_escape_block:bool -> ?passed_as_noescape_block_to:Procname.t option
-> Procname.t -> Procname.t
-> CMethodSignature.t -> CMethodSignature.t
@ -61,7 +61,7 @@ val method_signature_body_of_decl :
Tenv.t Tenv.t
-> Clang_ast_t.decl -> Clang_ast_t.decl
-> ?block_return_type:Clang_ast_t.qual_type -> ?block_return_type:Clang_ast_t.qual_type
-> ?is_no_escape_block:bool -> ?passed_as_noescape_block_to:Procname.t option
-> Procname.t -> Procname.t
-> CMethodSignature.t -> CMethodSignature.t
* Clang_ast_t.stmt option * Clang_ast_t.stmt option

@ -75,16 +75,16 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron
| None -> | None ->
([], None) ([], None)
in in
let is_no_escape_block, procname, block_return_type = let passed_as_noescape_block_to, procname, block_return_type =
match block_data_opt with match block_data_opt with
| Some {CModule_type.is_no_escape_block_arg; procname; return_type} -> | Some {CModule_type.passed_as_noescape_block_to; procname; return_type} ->
(is_no_escape_block_arg, procname, Some return_type) (passed_as_noescape_block_to, procname, Some return_type)
| _ -> | _ ->
(false, CType_decl.CProcname.from_decl ~tenv func_decl, None) (None, CType_decl.CProcname.from_decl ~tenv func_decl, None)
in in
let ms, body_opt, extra_instrs = let ms, body_opt, extra_instrs =
CType_decl.method_signature_body_of_decl tenv func_decl ?block_return_type CType_decl.method_signature_body_of_decl tenv func_decl ?block_return_type
~is_no_escape_block procname ~passed_as_noescape_block_to procname
in in
match body_opt with match body_opt with
| Some body -> | Some body ->

@ -35,7 +35,7 @@ type t =
; loc: Clang_ast_t.source_range ; loc: Clang_ast_t.source_range
; method_kind: ClangMethodKind.t ; method_kind: ClangMethodKind.t
; is_cpp_virtual: bool ; is_cpp_virtual: bool
; is_no_escape_block: bool ; passed_as_noescape_block_to: Procname.t option
; is_no_return: bool ; is_no_return: bool
; is_variadic: bool ; is_variadic: bool
; pointer_to_parent: Clang_ast_t.pointer option ; pointer_to_parent: Clang_ast_t.pointer option
@ -56,7 +56,7 @@ let is_setter {pointer_to_property_opt; params} =
let mk name class_param params ret_type ?(has_added_return_param = false) attributes loc method_kind let mk name class_param params ret_type ?(has_added_return_param = false) attributes loc method_kind
?(is_cpp_virtual = false) ?(is_no_escape_block = false) ?(is_no_return = false) ?(is_cpp_virtual = false) ?(passed_as_noescape_block_to = None) ?(is_no_return = false)
?(is_variadic = false) pointer_to_parent pointer_to_property_opt return_param_typ access = ?(is_variadic = false) pointer_to_parent pointer_to_property_opt return_param_typ access =
{ name { name
; access ; access
@ -68,7 +68,7 @@ let mk name class_param params ret_type ?(has_added_return_param = false) attrib
; loc ; loc
; method_kind ; method_kind
; is_cpp_virtual ; is_cpp_virtual
; is_no_escape_block ; passed_as_noescape_block_to
; is_no_return ; is_no_return
; is_variadic ; is_variadic
; pointer_to_parent ; pointer_to_parent
@ -81,8 +81,8 @@ let pp fmt ms =
F.fprintf fmt "%a, %a (is_no_escape_block=%b)" Mangled.pp name (Typ.pp Pp.text) typ F.fprintf fmt "%a, %a (is_no_escape_block=%b)" Mangled.pp name (Typ.pp Pp.text) typ
is_no_escape_block_arg is_no_escape_block_arg
in in
Format.fprintf fmt "Method %a [%a]->%a %a(is_no_escape_block=%b)" Format.fprintf fmt "Method %a [%a]->%a %a(passed_as_noescape_block_to=%a)"
(Pp.of_string ~f:Procname.to_string) (Pp.of_string ~f:Procname.to_string)
ms.name (Pp.comma_seq pp_param) ms.params (Typ.pp Pp.text) (fst ms.ret_type) ms.name (Pp.comma_seq pp_param) ms.params (Typ.pp Pp.text) (fst ms.ret_type)
(Pp.of_string ~f:Clang_ast_j.string_of_source_range) (Pp.of_string ~f:Clang_ast_j.string_of_source_range)
ms.loc ms.is_no_escape_block ms.loc (Pp.option Procname.pp) ms.passed_as_noescape_block_to

@ -28,7 +28,7 @@ type t =
; loc: Clang_ast_t.source_range ; loc: Clang_ast_t.source_range
; method_kind: ClangMethodKind.t ; method_kind: ClangMethodKind.t
; is_cpp_virtual: bool ; is_cpp_virtual: bool
; is_no_escape_block: bool ; passed_as_noescape_block_to: Procname.t option
; is_no_return: bool ; is_no_return: bool
; is_variadic: bool ; is_variadic: bool
; pointer_to_parent: Clang_ast_t.pointer option ; pointer_to_parent: Clang_ast_t.pointer option
@ -50,7 +50,7 @@ val mk :
-> Clang_ast_t.source_range -> Clang_ast_t.source_range
-> ClangMethodKind.t -> ClangMethodKind.t
-> ?is_cpp_virtual:bool -> ?is_cpp_virtual:bool
-> ?is_no_escape_block:bool -> ?passed_as_noescape_block_to:Procname.t option
-> ?is_no_return:bool -> ?is_no_return:bool
-> ?is_variadic:bool -> ?is_variadic:bool
-> Clang_ast_t.pointer option -> Clang_ast_t.pointer option

@ -245,7 +245,7 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg t
; access ; access
; is_defined= defined ; is_defined= defined
; is_biabduction_model= Config.biabduction_models_mode ; is_biabduction_model= Config.biabduction_models_mode
; is_no_escape_block= ms.CMethodSignature.is_no_escape_block ; passed_as_noescape_block_to= ms.CMethodSignature.passed_as_noescape_block_to
; is_no_return= ms.CMethodSignature.is_no_return ; is_no_return= ms.CMethodSignature.is_no_return
; is_variadic= ms.CMethodSignature.is_variadic ; is_variadic= ms.CMethodSignature.is_variadic
; sentinel_attr= find_sentinel_attribute ms.CMethodSignature.attributes ; sentinel_attr= find_sentinel_attribute ms.CMethodSignature.attributes

@ -10,7 +10,7 @@ open! IStd
type block_data = type block_data =
{ captured_vars: (Pvar.t * Typ.t) list { captured_vars: (Pvar.t * Typ.t) list
; context: CContext.t ; context: CContext.t
; is_no_escape_block_arg: bool ; passed_as_noescape_block_to: Procname.t option
; procname: Procname.t ; procname: Procname.t
; return_type: Clang_ast_t.qual_type } ; return_type: Clang_ast_t.qual_type }

@ -1253,14 +1253,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let find_arg j _ = Int.equal i j in let find_arg j _ = Int.equal i j in
List.findi ~f:find_arg callee_ms.CMethodSignature.params List.findi ~f:find_arg callee_ms.CMethodSignature.params
in in
let is_no_escape_block_arg = let passed_as_noescape_block_to =
match ms_param_type_i with match ms_param_type_i with
| Some (_, {CMethodSignature.is_no_escape_block_arg}) -> | Some (_, {CMethodSignature.is_no_escape_block_arg}) ->
is_no_escape_block_arg if is_no_escape_block_arg then Some callee_ms.CMethodSignature.name else None
| None -> | None ->
false None
in in
{trans_state_param with is_no_escape_block_arg} {trans_state_param with passed_as_noescape_block_to}
| _ -> | _ ->
trans_state_param trans_state_param
in in
@ -2798,10 +2798,11 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
CVar_decl.captured_vars_from_block_info context stmt_info.Clang_ast_t.si_source_range CVar_decl.captured_vars_from_block_info context stmt_info.Clang_ast_t.si_source_range
block_decl_info.Clang_ast_t.bdi_captured_variables block_decl_info.Clang_ast_t.bdi_captured_variables
in in
let is_no_escape_block_arg = trans_state.is_no_escape_block_arg in let passed_as_noescape_block_to = trans_state.passed_as_noescape_block_to in
let res = closure_trans procname captured_vars context stmt_info expr_info in let res = closure_trans procname captured_vars context stmt_info expr_info in
let block_data = let block_data =
Some {CModule_type.captured_vars; context; is_no_escape_block_arg; procname; return_type} Some
{CModule_type.captured_vars; context; passed_as_noescape_block_to; procname; return_type}
in in
F.function_decl context.translation_unit_context context.tenv context.cfg decl block_data ; F.function_decl context.translation_unit_context context.tenv context.cfg decl block_data ;
res res

@ -127,9 +127,9 @@ type trans_state =
; var_exp_typ: (Exp.t * Typ.t) option ; var_exp_typ: (Exp.t * Typ.t) option
; opaque_exp: (Exp.t * Typ.t) option ; opaque_exp: (Exp.t * Typ.t) option
; is_fst_arg_objc_instance_method_call: bool ; is_fst_arg_objc_instance_method_call: bool
; is_no_escape_block_arg: bool ; passed_as_noescape_block_to: Procname.t option
(** Current to-be-translated instruction is being passed as argument in a position annotated (** Current to-be-translated instruction is being passed as argument to the given method in
with NS_NOESCAPE *) } a position annotated with NS_NOESCAPE *) }
let default_trans_state context = let default_trans_state context =
{ context { context
@ -139,7 +139,7 @@ let default_trans_state context =
; var_exp_typ= None ; var_exp_typ= None
; opaque_exp= None ; opaque_exp= None
; is_fst_arg_objc_instance_method_call= false ; is_fst_arg_objc_instance_method_call= false
; is_no_escape_block_arg= false } ; passed_as_noescape_block_to= None }
type control = type control =

@ -27,7 +27,7 @@ type trans_state =
; var_exp_typ: (Exp.t * Typ.t) option ; var_exp_typ: (Exp.t * Typ.t) option
; opaque_exp: (Exp.t * Typ.t) option ; opaque_exp: (Exp.t * Typ.t) option
; is_fst_arg_objc_instance_method_call: bool ; is_fst_arg_objc_instance_method_call: bool
; is_no_escape_block_arg: bool } ; passed_as_noescape_block_to: Procname.t option }
val default_trans_state : CContext.t -> trans_state val default_trans_state : CContext.t -> trans_state

Loading…
Cancel
Save