[frontend] Record lambda's captured variables in `operator()` procdesc

Summary: Lambda is called using `operator()`. We need to know the information of captured variables when `operator()` procedure is being analysed. This diff records lambda captured variables in `operator()` procdesc. The complication arises from the fact that procdesc for `operator()` is created before translating lambda expression or during the translation of lambda expression where captured variables are translated. To solve this issue, we update existing `operator()` procdesc attributes with captured variable information when we translate lambda expression.

Reviewed By: jvillard

Differential Revision: D22374495

fbshipit-source-id: 44909adea
master
Daiva Naudziuniene 5 years ago committed by Facebook GitHub Bot
parent 831741c5eb
commit 1c5e47d91e

@ -121,13 +121,19 @@ let get_objc_method_data obj_c_message_expr_info =
(selector, MCStatic)
let should_create_procdesc cfg procname ~defined ~set_objc_accessor_attr =
let should_create_procdesc ?(captured_vars = []) cfg procname ~defined ~set_objc_accessor_attr =
match Procname.Hash.find cfg procname with
| previous_procdesc ->
let is_defined_previous = Procdesc.is_defined previous_procdesc in
if (defined || set_objc_accessor_attr) && not is_defined_previous then (
Procname.Hash.remove cfg procname ;
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
| exception Caml.Not_found ->
true
@ -189,8 +195,8 @@ let find_sentinel_attribute attrs =
(** Creates a procedure description. *)
let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg tenv ms fbody
captured =
let create_local_procdesc ?(set_objc_accessor_attr = false) ?(update_lambda_captured = false)
trans_unit_ctx cfg tenv ms fbody captured =
let defined = not (List.is_empty fbody) in
let proc_name = ms.CMethodSignature.name in
let clang_method_kind = ms.CMethodSignature.method_kind in
@ -205,6 +211,9 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg t
| `Public ->
PredSymb.Protected
in
let captured_mangled =
List.map ~f:(fun (var, t, mode) -> (Pvar.get_name var, t, mode)) captured
in
let create_new_procdesc () =
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
@ -216,10 +225,10 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg t
let formals =
List.map ~f:(fun ({name; typ} : CMethodSignature.param_type) -> (name, typ)) all_params
in
let captured_mangled =
List.map ~f:(fun (var, t, mode) -> (Pvar.get_name var, t, mode)) captured
in
(* Captured variables for blocks are treated as parameters *)
(* Captured variables for blocks are treated as parameters
Captured variables will not be added to formals for lambdas' `operator()` as procdesc for
`operator()` is created before captured variables are translated
*)
let captured_as_formals = List.map ~f:(fun (var, t, _) -> (var, t)) captured_mangled in
let formals = captured_as_formals @ formals in
let const_formals =
@ -269,7 +278,8 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg t
Procdesc.set_start_node procdesc start_node ;
Procdesc.set_exit_node procdesc exit_node )
in
if should_create_procdesc cfg proc_name ~defined ~set_objc_accessor_attr then (
let captured_vars = if update_lambda_captured then captured_mangled else [] in
if should_create_procdesc cfg proc_name ~defined ~set_objc_accessor_attr ~captured_vars then (
create_new_procdesc () ;
true )
else false
@ -294,13 +304,14 @@ let create_external_procdesc trans_unit_ctx cfg proc_name clang_method_kind type
ignore (Cfg.create_proc_desc cfg proc_attributes)
let create_procdesc_with_pointer context pointer class_name_opt name =
let create_procdesc_with_pointer ?(captured_vars = []) context pointer class_name_opt name =
let open CContext in
match method_signature_of_pointer context.tenv pointer with
| Some callee_ms ->
ignore
(create_local_procdesc context.translation_unit_context context.cfg context.tenv callee_ms
[] []) ;
[] captured_vars
~update_lambda_captured:(not (List.is_empty captured_vars))) ;
callee_ms.CMethodSignature.name
| None ->
let callee_name, method_kind =
@ -317,13 +328,13 @@ let create_procdesc_with_pointer context pointer class_name_opt name =
callee_name
let get_procname_from_cpp_lambda context dec =
let get_procname_from_cpp_lambda context dec captured_vars =
match dec with
| Clang_ast_t.CXXRecordDecl (_, _, _, _, _, _, _, cxx_rdi) -> (
match cxx_rdi.xrdi_lambda_call_operator with
| Some dr ->
let name_info, decl_ptr, _ = CAst_utils.get_info_from_decl_ref dr in
create_procdesc_with_pointer context decl_ptr None name_info.ni_name
create_procdesc_with_pointer context decl_ptr None name_info.ni_name ~captured_vars
| _ ->
assert false )
| _ ->

@ -19,13 +19,19 @@ type method_call_type = MCVirtual | MCNoVirtual | MCStatic [@@deriving compare]
val equal_method_call_type : method_call_type -> method_call_type -> bool
val should_create_procdesc :
Cfg.t -> Procname.t -> defined:bool -> set_objc_accessor_attr:bool -> bool
?captured_vars:(Mangled.t * Typ.typ * Pvar.capture_mode) list
-> Cfg.t
-> Procname.t
-> defined:bool
-> set_objc_accessor_attr:bool
-> bool
(** Return if a procdesc should be added or not. It returns [false] when the same name of procdesc
was added previously. [defined] represents if the function body is non-empty.
[set_objc_accessor_attr] represents if the function is a getter/setter in Obj-C. *)
val create_local_procdesc :
?set_objc_accessor_attr:bool
-> ?update_lambda_captured:bool
-> CFrontend_config.translation_unit_context
-> Cfg.t
-> Tenv.t
@ -55,8 +61,14 @@ val method_signature_of_pointer : Tenv.t -> Clang_ast_t.pointer -> CMethodSignat
val get_method_name_from_clang : Tenv.t -> CMethodSignature.t option -> Procname.t option
val create_procdesc_with_pointer :
CContext.t -> Clang_ast_t.pointer -> Typ.Name.t option -> string -> Procname.t
?captured_vars:(Pvar.t * Typ.t * Pvar.capture_mode) list
-> CContext.t
-> Clang_ast_t.pointer
-> Typ.Name.t option
-> string
-> Procname.t
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 -> (Pvar.t * Typ.t * Pvar.capture_mode) list -> Procname.t
val get_captures_from_cpp_lambda : Clang_ast_t.decl -> Clang_ast_t.lambda_capture_info list

@ -2860,7 +2860,6 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let context = trans_state.context in
call_translation context lei_lambda_decl ;
let procname = Procdesc.get_proc_name context.procdesc in
let lambda_pname = CMethod_trans.get_procname_from_cpp_lambda context lei_lambda_decl in
let typ = CType_decl.qual_type_to_sil_type context.tenv qual_type in
let get_captured_pvar_typ decl_ref =
CVar_decl.sil_var_of_captured_var context stmt_info.Clang_ast_t.si_source_range procname
@ -2936,6 +2935,12 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let trans_results, captured_vars =
List.fold_right ~f:translate_captured ~init:([], []) lei_captures
in
let captured_var_names =
List.map ~f:(fun (_, var, typ, mode) -> (var, typ, mode)) captured_vars
in
let lambda_pname =
CMethod_trans.get_procname_from_cpp_lambda context lei_lambda_decl captured_var_names
in
let closure = Exp.Closure {name= lambda_pname; captured_vars} in
collect_trans_results context.procdesc ~return:(closure, typ) trans_results

@ -302,7 +302,7 @@ digraph cfg {
"#lambda_shared_lambda_lambda1.cpp:24:12#fooOK#{12805486487749307717|constexpr}.5e8e5a47f663bbae0aeb80a4152608e7_2" [label="2: Exit fooOK::lambda_shared_lambda_lambda1.cpp:24:12:: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:31:10#normal_capture#(3336792892144266867).563aa24976a73c4ea364dbb5afa3f73f_1" [label="1: Start normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::operator()\nFormals: this:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:31:10#normal_capture#(3336792892144266867).563aa24976a73c4ea364dbb5afa3f73f_1" [label="1: Start normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::operator()\nFormals: this:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10*\nLocals: \nCaptured: [by value]x:int [by value]y:int \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:31:10#normal_capture#(3336792892144266867).563aa24976a73c4ea364dbb5afa3f73f_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:31:10#normal_capture#(3336792892144266867).563aa24976a73c4ea364dbb5afa3f73f_3" ;
@ -313,7 +313,7 @@ digraph cfg {
"operator()#lambda_shared_lambda_lambda1.cpp:31:10#normal_capture#(3336792892144266867).563aa24976a73c4ea364dbb5afa3f73f_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:31:10#normal_capture#(3336792892144266867).563aa24976a73c4ea364dbb5afa3f73f_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:36:3#capture_by_ref#(17277454583786497390).328aa336808e9a777a5cd630eb1ef54f_1" [label="1: Start capture_by_ref::lambda_shared_lambda_lambda1.cpp:36:3::operator()\nFormals: this:capture_by_ref::lambda_shared_lambda_lambda1.cpp:36:3*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:36:3#capture_by_ref#(17277454583786497390).328aa336808e9a777a5cd630eb1ef54f_1" [label="1: Start capture_by_ref::lambda_shared_lambda_lambda1.cpp:36:3::operator()\nFormals: this:capture_by_ref::lambda_shared_lambda_lambda1.cpp:36:3*\nLocals: \nCaptured: [by ref]x:int \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:36:3#capture_by_ref#(17277454583786497390).328aa336808e9a777a5cd630eb1ef54f_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:36:3#capture_by_ref#(17277454583786497390).328aa336808e9a777a5cd630eb1ef54f_3" ;
@ -324,7 +324,7 @@ digraph cfg {
"operator()#lambda_shared_lambda_lambda1.cpp:36:3#capture_by_ref#(17277454583786497390).328aa336808e9a777a5cd630eb1ef54f_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:36:3#capture_by_ref#(17277454583786497390).328aa336808e9a777a5cd630eb1ef54f_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:41:10#init_capture1#(11958159405823124536).c1401fcf3820489850f4deb3dab109ac_1" [label="1: Start init_capture1::lambda_shared_lambda_lambda1.cpp:41:10::operator()\nFormals: this:init_capture1::lambda_shared_lambda_lambda1.cpp:41:10*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:41:10#init_capture1#(11958159405823124536).c1401fcf3820489850f4deb3dab109ac_1" [label="1: Start init_capture1::lambda_shared_lambda_lambda1.cpp:41:10::operator()\nFormals: this:init_capture1::lambda_shared_lambda_lambda1.cpp:41:10*\nLocals: \nCaptured: [by value]i:int \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:41:10#init_capture1#(11958159405823124536).c1401fcf3820489850f4deb3dab109ac_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:41:10#init_capture1#(11958159405823124536).c1401fcf3820489850f4deb3dab109ac_3" ;
@ -335,7 +335,7 @@ digraph cfg {
"operator()#lambda_shared_lambda_lambda1.cpp:41:10#init_capture1#(11958159405823124536).c1401fcf3820489850f4deb3dab109ac_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:41:10#init_capture1#(11958159405823124536).c1401fcf3820489850f4deb3dab109ac_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:46:10#init_capture2#(10943089228143620310).415a6350451062f52188b6cc908fbf46_1" [label="1: Start init_capture2::lambda_shared_lambda_lambda1.cpp:46:10::operator()\nFormals: this:init_capture2::lambda_shared_lambda_lambda1.cpp:46:10*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:46:10#init_capture2#(10943089228143620310).415a6350451062f52188b6cc908fbf46_1" [label="1: Start init_capture2::lambda_shared_lambda_lambda1.cpp:46:10::operator()\nFormals: this:init_capture2::lambda_shared_lambda_lambda1.cpp:46:10*\nLocals: \nCaptured: [by value]a:int [by value]b:int [by value]c:int \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:46:10#init_capture2#(10943089228143620310).415a6350451062f52188b6cc908fbf46_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:46:10#init_capture2#(10943089228143620310).415a6350451062f52188b6cc908fbf46_3" ;
@ -346,7 +346,7 @@ digraph cfg {
"operator()#lambda_shared_lambda_lambda1.cpp:46:10#init_capture2#(10943089228143620310).415a6350451062f52188b6cc908fbf46_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:46:10#init_capture2#(10943089228143620310).415a6350451062f52188b6cc908fbf46_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:51:19#capture_this_explicit#Capture#(1084455887557995828.1d62aec1dfb3de86dac2a9a51e124083_1" [label="1: Start Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:51:19::operator()\nFormals: this:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:51:19*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:51:19#capture_this_explicit#Capture#(1084455887557995828.1d62aec1dfb3de86dac2a9a51e124083_1" [label="1: Start Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:51:19::operator()\nFormals: this:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:51:19*\nLocals: \nCaptured: [by ref]this:Capture* \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:51:19#capture_this_explicit#Capture#(1084455887557995828.1d62aec1dfb3de86dac2a9a51e124083_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:51:19#capture_this_explicit#Capture#(1084455887557995828.1d62aec1dfb3de86dac2a9a51e124083_3" ;
@ -368,7 +368,7 @@ digraph cfg {
"#lambda_shared_lambda_lambda1.cpp:51:19#capture_this_explicit#Capture#{15581681824770184595|constexp.7bc69d386faff7f8ffc9dc392a5988cf_3" -> "#lambda_shared_lambda_lambda1.cpp:51:19#capture_this_explicit#Capture#{15581681824770184595|constexp.7bc69d386faff7f8ffc9dc392a5988cf_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:55:19#capture_star_this#Capture#(11891233366713773989).2f1caaa7509ffca98027857cb192891f_1" [label="1: Start Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::operator()\nFormals: this:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:55:19#capture_star_this#Capture#(11891233366713773989).2f1caaa7509ffca98027857cb192891f_1" [label="1: Start Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::operator()\nFormals: this:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19*\nLocals: \nCaptured: [by value]this:Capture* \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:55:19#capture_star_this#Capture#(11891233366713773989).2f1caaa7509ffca98027857cb192891f_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:55:19#capture_star_this#Capture#(11891233366713773989).2f1caaa7509ffca98027857cb192891f_2" ;
@ -386,7 +386,7 @@ digraph cfg {
"#lambda_shared_lambda_lambda1.cpp:55:19#capture_star_this#Capture#{9456129203468966420|constexpr}.524c805f606049237b74db978143df13_3" -> "#lambda_shared_lambda_lambda1.cpp:55:19#capture_star_this#Capture#{9456129203468966420|constexpr}.524c805f606049237b74db978143df13_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:61:19#capture_this_with_equal#Capture#(91082432562742530.b72f197de8f4f60c1d815523b52f3221_1" [label="1: Start Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:61:19::operator()\nFormals: this:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:61:19*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:61:19#capture_this_with_equal#Capture#(91082432562742530.b72f197de8f4f60c1d815523b52f3221_1" [label="1: Start Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:61:19::operator()\nFormals: this:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:61:19*\nLocals: \nCaptured: [by ref]this:Capture* \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:61:19#capture_this_with_equal#Capture#(91082432562742530.b72f197de8f4f60c1d815523b52f3221_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:61:19#capture_this_with_equal#Capture#(91082432562742530.b72f197de8f4f60c1d815523b52f3221_3" ;
@ -408,7 +408,7 @@ digraph cfg {
"#lambda_shared_lambda_lambda1.cpp:61:19#capture_this_with_equal#Capture#{16013381636753347826|conste.5c764d68be3baa1f6ef1128e1dbea59f_3" -> "#lambda_shared_lambda_lambda1.cpp:61:19#capture_this_with_equal#Capture#{16013381636753347826|conste.5c764d68be3baa1f6ef1128e1dbea59f_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:65:19#capture_this_with_auto#Capture#(476955214552649307.449a23f73c844f26ba0d7a54aef5727e_1" [label="1: Start Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:65:19::operator()\nFormals: this:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:65:19*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:65:19#capture_this_with_auto#Capture#(476955214552649307.449a23f73c844f26ba0d7a54aef5727e_1" [label="1: Start Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:65:19::operator()\nFormals: this:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:65:19*\nLocals: \nCaptured: [by ref]this:Capture* \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:65:19#capture_this_with_auto#Capture#(476955214552649307.449a23f73c844f26ba0d7a54aef5727e_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:65:19#capture_this_with_auto#Capture#(476955214552649307.449a23f73c844f26ba0d7a54aef5727e_3" ;
@ -430,7 +430,7 @@ digraph cfg {
"#lambda_shared_lambda_lambda1.cpp:65:19#capture_this_with_auto#Capture#{10854495330849287568|constex.920289afd6e5ecdf220f6692ec06788a_3" -> "#lambda_shared_lambda_lambda1.cpp:65:19#capture_this_with_auto#Capture#{10854495330849287568|constex.920289afd6e5ecdf220f6692ec06788a_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:77:12#struct_capture#(3957024350029978205).24bdda6ed01a44c4f20e0211a02e4440_1" [label="1: Start struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::operator()\nFormals: this:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12*\nLocals: \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:77:12#struct_capture#(3957024350029978205).24bdda6ed01a44c4f20e0211a02e4440_1" [label="1: Start struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::operator()\nFormals: this:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12*\nLocals: \nCaptured: [by value]x:SomeStruct [by value]y:SomeStruct \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:77:12#struct_capture#(3957024350029978205).24bdda6ed01a44c4f20e0211a02e4440_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:77:12#struct_capture#(3957024350029978205).24bdda6ed01a44c4f20e0211a02e4440_3" ;

Loading…
Cancel
Save