@ -121,19 +121,13 @@ let get_objc_method_data obj_c_message_expr_info =
( selector , MCStatic )
( selector , MCStatic )
let should_create_procdesc ? ( captured_vars = [] ) cfg procname ~ defined ~ set_objc_accessor_attr =
let should_create_procdesc cfg procname ~ defined ~ set_objc_accessor_attr =
match Procname . Hash . find cfg procname with
match Procname . Hash . find cfg procname with
| previous_procdesc ->
| previous_procdesc ->
let is_defined_previous = Procdesc . is_defined previous_procdesc in
let is_defined_previous = Procdesc . is_defined previous_procdesc in
if ( defined | | set_objc_accessor_attr ) && not is_defined_previous then (
if ( defined | | set_objc_accessor_attr ) && not is_defined_previous then (
Procname . Hash . remove cfg procname ;
Procname . Hash . remove cfg procname ;
true )
true )
else if is_defined_previous && not ( List . is_empty captured_vars ) then (
let new_attributes =
{ ( Procdesc . get_attributes previous_procdesc ) with captured = captured_vars }
in
Procdesc . set_attributes previous_procdesc new_attributes ;
false )
else false
else false
| exception Caml . Not_found ->
| exception Caml . Not_found ->
true
true
@ -195,8 +189,8 @@ let find_sentinel_attribute attrs =
(* * Creates a procedure description. *)
(* * Creates a procedure description. *)
let create_local_procdesc ? ( set_objc_accessor_attr = false ) ? ( update _lambda_captured = false )
let create_local_procdesc ? ( set_objc_accessor_attr = false ) ? ( record _lambda_captured = false )
trans_unit_ctx cfg tenv ms fbody captured =
? ( is_cpp_lambda_call_operator = false ) trans_unit_ctx cfg tenv ms fbody captured =
let defined = not ( List . is_empty fbody ) in
let defined = not ( List . is_empty fbody ) in
let proc_name = ms . CMethodSignature . name in
let proc_name = ms . CMethodSignature . name in
let clang_method_kind = ms . CMethodSignature . method_kind in
let clang_method_kind = ms . CMethodSignature . method_kind in
@ -214,6 +208,17 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) ?(update_lambda_capt
let captured_mangled =
let captured_mangled =
List . map ~ f : ( fun ( var , t , mode ) -> ( Pvar . get_name var , t , mode ) ) captured
List . map ~ f : ( fun ( var , t , mode ) -> ( Pvar . get_name var , t , mode ) ) captured
in
in
(* Retrieve captured variables from procdesc created when translating captured variables in lambda expression *)
(* We want to do this before `should_create_procdesc` is called as it can remove previous procdesc *)
let captured_mangled_not_formals =
if is_cpp_lambda_call_operator then
match Procname . Hash . find cfg proc_name with
| procdesc_prev ->
Procdesc . get_captured procdesc_prev
| exception Caml . Not_found ->
captured_mangled
else captured_mangled
in
let create_new_procdesc () =
let create_new_procdesc () =
let all_params = Option . to_list ms . CMethodSignature . class_param @ ms . CMethodSignature . params in
let all_params = Option . to_list ms . CMethodSignature . class_param @ ms . CMethodSignature . params in
let has_added_return_param = ms . CMethodSignature . has_added_return_param in
let has_added_return_param = ms . CMethodSignature . has_added_return_param in
@ -225,11 +230,11 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) ?(update_lambda_capt
let formals =
let formals =
List . map ~ f : ( fun ( { name ; typ } : CMethodSignature . param_type ) -> ( name , typ ) ) all_params
List . map ~ f : ( fun ( { name ; typ } : CMethodSignature . param_type ) -> ( name , typ ) ) all_params
in
in
(* Captured variables for blocks are treated as parameters
(* Captured variables for blocks are treated as parameters , but not for cpp lambdas *)
Captured variables will not be added to formals for lambdas' ` operator () ` as procdesc for
let captured_as_formals =
` operator () ` is created before captured variables are translated
if is_cpp_lambda_call_operator then []
* )
else List . map ~ f : ( fun ( var , t , _ ) -> ( var , t ) ) captured_mangled
let captured_as_formals = List . map ~ f : ( fun ( var , t , _ ) -> ( var , t ) ) captured_mangled in
in
let formals = captured_as_formals @ formals in
let formals = captured_as_formals @ formals in
let const_formals =
let const_formals =
get_const_params_indices ~ shift : ( List . length captured_as_formals ) all_params
get_const_params_indices ~ shift : ( List . length captured_as_formals ) all_params
@ -253,7 +258,7 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) ?(update_lambda_capt
let procdesc =
let procdesc =
let proc_attributes =
let proc_attributes =
{ ( ProcAttributes . default translation_unit proc_name ) with
{ ( ProcAttributes . default translation_unit proc_name ) with
ProcAttributes . captured = captured_mangled
ProcAttributes . captured = captured_mangled _not_formals
; formals
; formals
; const_formals
; const_formals
; has_added_return_param
; has_added_return_param
@ -278,11 +283,23 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) ?(update_lambda_capt
Procdesc . set_start_node procdesc start_node ;
Procdesc . set_start_node procdesc start_node ;
Procdesc . set_exit_node procdesc exit_node )
Procdesc . set_exit_node procdesc exit_node )
in
in
let captured_vars = if update_lambda_captured then captured_mangled else [] in
if should_create_procdesc cfg proc_name ~ defined ~ set_objc_accessor_attr then (
if should_create_procdesc cfg proc_name ~ defined ~ set_objc_accessor_attr ~ captured_vars then (
create_new_procdesc () ;
create_new_procdesc () ;
true )
true )
else false
else (
(* If we do not create procdesc when captured variables are translated,
then we want to record captured variables in the previously created procdesc * )
ignore
( if record_lambda_captured then
match Procname . Hash . find cfg proc_name with
| procdesc_prev ->
let new_attributes =
{ ( Procdesc . get_attributes procdesc_prev ) with captured = captured_mangled }
in
Procdesc . set_attributes procdesc_prev new_attributes
| exception Caml . Not_found ->
() ) ;
false )
(* * Create a procdesc for objc methods whose signature cannot be found. *)
(* * Create a procdesc for objc methods whose signature cannot be found. *)
@ -311,7 +328,7 @@ let create_procdesc_with_pointer ?(captured_vars = []) context pointer class_nam
ignore
ignore
( create_local_procdesc context . translation_unit_context context . cfg context . tenv callee_ms
( create_local_procdesc context . translation_unit_context context . cfg context . tenv callee_ms
[] captured_vars
[] captured_vars
~ update _lambda_captured: ( not ( List . is_empty captured_vars ) ) ) ;
~ record _lambda_captured: ( not ( List . is_empty captured_vars ) ) ) ;
callee_ms . CMethodSignature . name
callee_ms . CMethodSignature . name
| None ->
| None ->
let callee_name , method_kind =
let callee_name , method_kind =