[clang] Specialize also c functions with blocks as parameters

Reviewed By: jberdine

Differential Revision: D6273764

fbshipit-source-id: eab549f
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent 23101f4e57
commit b9a56a6c52

@ -580,14 +580,24 @@ let specialize_with_block_args callee_pdesc pname_with_block_args block_args =
in in
List.unzip new_formals_blocks_captured_vars_with_annots List.unzip new_formals_blocks_captured_vars_with_annots
in in
let source_file_captured =
let pname = Procdesc.get_proc_name callee_pdesc in
match Attributes.find_file_capturing_procedure pname with
| Some (source_file, _) ->
source_file
| None ->
Logging.die InternalError
"specialize_with_block_args ahould only be called with defined procedures, but we cannot find the captured file of procname %a"
Typ.Procname.pp pname
in
let resolved_attributes = let resolved_attributes =
{ callee_attributes with { callee_attributes with
proc_name= pname_with_block_args proc_name= pname_with_block_args
; is_defined= true ; is_defined= true
; err_log= Errlog.empty () ; err_log= Errlog.empty ()
; source_file_captured= callee_attributes.loc.Location.file
; formals= new_formals_blocks_captured_vars ; formals= new_formals_blocks_captured_vars
; method_annotation= (fst callee_attributes.method_annotation, extended_formals_annots) } ; method_annotation= (fst callee_attributes.method_annotation, extended_formals_annots)
; source_file_captured }
in in
Attributes.store resolved_attributes ; Attributes.store resolved_attributes ;
let resolved_pdesc = let resolved_pdesc =

@ -441,7 +441,7 @@ let add_with_block_parameters_flag instr =
match instr with match instr with
| Call (ret_id, Exp.Const Const.Cfun name, arg_ts, loc, cf) -> | Call (ret_id, Exp.Const Const.Cfun name, arg_ts, loc, cf) ->
if List.exists ~f:(fun (exp, _) -> Exp.is_objc_block_closure exp) arg_ts if List.exists ~f:(fun (exp, _) -> Exp.is_objc_block_closure exp) arg_ts
&& Typ.Procname.is_objc_method name && (Typ.Procname.is_objc_method name || Typ.Procname.is_c_function name)
(* to be extended to other methods *) (* to be extended to other methods *)
then then
let cf' = {cf with cf_with_block_parameters= true} in let cf' = {cf with cf_with_block_parameters= true} in

@ -670,6 +670,8 @@ module Procname = struct
let is_c_method = function ObjC_Cpp _ -> true | _ -> false let is_c_method = function ObjC_Cpp _ -> true | _ -> false
let is_c_function = function C _ -> true | _ -> false
let is_obj_c_pp = function ObjC_Cpp _ | C _ -> true | _ -> false let is_obj_c_pp = function ObjC_Cpp _ | C _ -> true | _ -> false
let is_constexpr = function ObjC_Cpp {kind= CPPConstructor (_, true)} -> true | _ -> false let is_constexpr = function ObjC_Cpp {kind= CPPConstructor (_, true)} -> true | _ -> false

@ -360,6 +360,9 @@ module Procname : sig
val is_c_method : t -> bool val is_c_method : t -> bool
(** Check if this is an Objective-C/C++ method name. *) (** Check if this is an Objective-C/C++ method name. *)
val is_c_function : t -> bool
(** Check if this is a C function name. *)
val is_obj_c_pp : t -> bool val is_obj_c_pp : t -> bool
(** Check if this is an Objective-C/C++ method name or C-style function. *) (** Check if this is an Objective-C/C++ method name or C-style function. *)

@ -23,3 +23,12 @@ typedef void (^MyBlock)(int x);
and:(nullable NSString*)name; and:(nullable NSString*)name;
@end @end
void c_function(_Nonnull MyBlock block1,
_Nonnull MyBlock block2,
NSString* _Nonnull name) {
block1(22);
int my_var = 11;
block2(33);
int my_other_var = 12;
};

@ -73,4 +73,31 @@
return *p; // and not here return *p; // and not here
} }
} }
- (int)calling_c_function_with_block_parameters {
int h = 10;
int z = 10;
c_function(
^(int i) {
self->x = i;
},
^(int i) {
self->y = h + z;
},
@"Hi");
return self->y;
}
+ (int)calling_c_function_with_block_parameters_sets_fields_correctly {
B* b = [B new];
[b calling_c_function_with_block_parameters];
if (b->x + b->y == 42) {
int* p = 0;
return *p; // NPE here, because we know that the values x and y
// are set correctly by calling blocks
} else {
int* p = 0;
return *p; // and not here
}
}
@end @end

@ -1,3 +1,4 @@
build_systems/codetoanalyze/objc_getters_setters/B.m, B_calling_c_function_with_block_parameters_sets_fields_correctly, 5, NULL_DEREFERENCE, [start of procedure calling_c_function_with_block_parameters_sets_fields_correctly,start of procedure calling_c_function_with_block_parameters,start of procedure c_function(),start of procedure block,return from a call to objc_blockB_calling_c_function_with_block_parameters_3,start of procedure block,return from a call to objc_blockB_calling_c_function_with_block_parameters_4,return from a call to c_function_objc_blockB_calling_c_function_with_block_parameters_3_objc_blockB_calling_c_function_with_block_parameters_4,return from a call to B_calling_c_function_with_block_parameters,Condition is true]
build_systems/codetoanalyze/objc_getters_setters/B.m, B_calling_method_with_block_parameters_sets_fields_correctly, 5, NULL_DEREFERENCE, [start of procedure calling_method_with_block_parameters_sets_fields_correctly,start of procedure calling_method_with_block_parameters,start of procedure foo:and:and_also:and:,start of procedure block,return from a call to objc_blockB_calling_method_with_block_parameters_1,start of procedure block,return from a call to objc_blockB_calling_method_with_block_parameters_2,return from a call to A_foo:and:and_also:and:_objc_blockB_calling_method_with_block_parameters_1_objc_blockB_calling_method_with_block_parameters_2,return from a call to B_calling_method_with_block_parameters,Condition is true] build_systems/codetoanalyze/objc_getters_setters/B.m, B_calling_method_with_block_parameters_sets_fields_correctly, 5, NULL_DEREFERENCE, [start of procedure calling_method_with_block_parameters_sets_fields_correctly,start of procedure calling_method_with_block_parameters,start of procedure foo:and:and_also:and:,start of procedure block,return from a call to objc_blockB_calling_method_with_block_parameters_1,start of procedure block,return from a call to objc_blockB_calling_method_with_block_parameters_2,return from a call to A_foo:and:and_also:and:_objc_blockB_calling_method_with_block_parameters_1_objc_blockB_calling_method_with_block_parameters_2,return from a call to B_calling_method_with_block_parameters,Condition is true]
build_systems/codetoanalyze/objc_getters_setters/B.m, B_npe_no_bad_footprint_in_getter:, 3, NULL_DEREFERENCE, [start of procedure npe_no_bad_footprint_in_getter:] build_systems/codetoanalyze/objc_getters_setters/B.m, B_npe_no_bad_footprint_in_getter:, 3, NULL_DEREFERENCE, [start of procedure npe_no_bad_footprint_in_getter:]
build_systems/codetoanalyze/objc_getters_setters/B.m, B_npe_no_bad_footprint_in_setter:andMetadata:, 3, NULL_DEREFERENCE, [start of procedure npe_no_bad_footprint_in_setter:andMetadata:] build_systems/codetoanalyze/objc_getters_setters/B.m, B_npe_no_bad_footprint_in_setter:andMetadata:, 3, NULL_DEREFERENCE, [start of procedure npe_no_bad_footprint_in_setter:andMetadata:]

Loading…
Cancel
Save