[clang] translate vars captured by lambda

Reviewed By: jeremydubreil

Differential Revision: D5482634

fbshipit-source-id: 86afb05
master
Sam Blackshear 7 years ago committed by Facebook Github Bot
parent ff30afac8b
commit cb9c768c61

@ -2413,19 +2413,28 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
in in
stmt_res_trans :: rest_stmts_res_trans stmt_res_trans :: rest_stmts_res_trans
and lambdaExpr_trans trans_state expr_info decl = and lambdaExpr_trans trans_state expr_info {Clang_ast_t.lei_lambda_decl; lei_captures} =
let open CContext in let open CContext in
let qual_type = expr_info.Clang_ast_t.ei_qual_type in let qual_type = expr_info.Clang_ast_t.ei_qual_type in
let context = trans_state.context in let context = trans_state.context in
call_translation context decl ; call_translation context lei_lambda_decl ;
let procname = Procdesc.get_proc_name context.procdesc in let procname = Procdesc.get_proc_name context.procdesc in
let lambda_pname = CMethod_trans.get_procname_from_cpp_lambda context decl 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 typ = CType_decl.qual_type_to_sil_type context.tenv qual_type in
(* We need to set the explicit dependency between the newly created lambda and the *) (* We need to set the explicit dependency between the newly created lambda and the *)
(* defining procedure. We add an edge in the call graph.*) (* defining procedure. We add an edge in the call graph.*)
Cg.add_edge context.cg procname lambda_pname ; Cg.add_edge context.cg procname lambda_pname ;
let captured_vars = [] in let captured_vars =
(* TODO *) List.fold_right
~f:(fun {Clang_ast_t.lci_captured_var} acc ->
match lci_captured_var with
| Some decl_ref
-> CVar_decl.sil_var_of_captured_var decl_ref context procname :: acc
| None
-> acc)
~init:[] lei_captures
|> List.map ~f:(fun (pvar, typ) -> (Exp.Lvar pvar, pvar, typ))
in
let closure = Exp.Closure {name= lambda_pname; captured_vars} in let closure = Exp.Closure {name= lambda_pname; captured_vars} in
{empty_res_trans with exps= [(closure, typ)]} {empty_res_trans with exps= [(closure, typ)]}
@ -2927,8 +2936,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
-> cxxStdInitializerListExpr_trans trans_state stmt_info stmts expr_info -> cxxStdInitializerListExpr_trans trans_state stmt_info stmts expr_info
| LambdaExpr (_, _, expr_info, lambda_expr_info) | LambdaExpr (_, _, expr_info, lambda_expr_info)
-> let trans_state' = {trans_state with priority= Free} in -> let trans_state' = {trans_state with priority= Free} in
let decl = lambda_expr_info.Clang_ast_t.lei_lambda_decl in lambdaExpr_trans trans_state' expr_info lambda_expr_info
lambdaExpr_trans trans_state' expr_info decl
| AttributedStmt (_, stmts, attrs) | AttributedStmt (_, stmts, attrs)
-> attributedStmt_trans trans_state stmts attrs -> attributedStmt_trans trans_state stmts attrs
| TypeTraitExpr (_, _, expr_info, type_trait_info) | TypeTraitExpr (_, _, expr_info, type_trait_info)

@ -89,23 +89,23 @@ let compute_autorelease_pool_vars context stmts =
in in
Exp.Map.bindings (do_stmts Exp.Map.empty stmts) Exp.Map.bindings (do_stmts Exp.Map.empty stmts)
let sil_var_of_captured_var decl_ref context procname =
match decl_ref with
| {Clang_ast_t.dr_qual_type= Some qual_type}
-> ( sil_var_of_decl_ref context decl_ref procname
, CType_decl.qual_type_to_sil_type context.CContext.tenv qual_type )
| _
-> assert false
(* Returns a list of captured variables as sil variables. *) (* Returns a list of captured variables as sil variables. *)
let captured_vars_from_block_info context cvl = let captured_vars_from_block_info context cvl =
let procname = Procdesc.get_proc_name context.CContext.procdesc in let procname = Procdesc.get_proc_name context.CContext.procdesc in
let sil_var_of_captured_var cv vars = let sil_var_of_captured_var {Clang_ast_t.bcv_variable} vars_acc =
match cv.Clang_ast_t.bcv_variable with match bcv_variable with
| Some dr -> ( | Some ({Clang_ast_t.dr_name= Some {Clang_ast_t.ni_name}} as decl_ref)
match (dr.Clang_ast_t.dr_name, dr.Clang_ast_t.dr_qual_type) with -> if String.equal ni_name CFrontend_config.self && not (CContext.is_objc_instance context)
| Some name_info, Some qual_type then vars_acc
-> let n = name_info.Clang_ast_t.ni_name in else sil_var_of_captured_var decl_ref context procname :: vars_acc
if String.equal n CFrontend_config.self && not (CContext.is_objc_instance context) then
vars
else
let pvar = sil_var_of_decl_ref context dr procname in
let typ = CType_decl.qual_type_to_sil_type context.CContext.tenv qual_type in
(pvar, typ) :: vars
| _
-> assert false )
| _ | _
-> assert false -> assert false
in in

@ -21,5 +21,8 @@ val add_var_to_locals : Procdesc.t -> Clang_ast_t.decl -> Typ.t -> Pvar.t -> uni
val compute_autorelease_pool_vars : CContext.t -> Clang_ast_t.stmt list -> (Exp.t * Typ.t) list val compute_autorelease_pool_vars : CContext.t -> Clang_ast_t.stmt list -> (Exp.t * Typ.t) list
val sil_var_of_captured_var :
Clang_ast_t.decl_ref -> CContext.t -> Typ.Procname.t -> Pvar.t * Typ.typ
val captured_vars_from_block_info : val captured_vars_from_block_info :
CContext.t -> Clang_ast_t.block_captured_variable list -> (Pvar.t * Typ.t) list CContext.t -> Clang_ast_t.block_captured_variable list -> (Pvar.t * Typ.t) list

@ -46,6 +46,15 @@ int plus_plus3_bad() {
return i++; return i++;
} }
void FN_capture_no_read_bad() {
int x = 0;
[x]() { return; }();
}
void FN_init_capture_no_read_bad() {
[i = 0]() { return; };
}
int return_ok() { int return_ok() {
int x = 5; int x = 5;
return x; return x;
@ -98,7 +107,9 @@ int* assign_pointer2_ok() {
return ptr; return ptr;
} }
void by_ref_ok(int& ref) { ref = 7; } void by_ref1_ok(int& ref) { ref = 7; }
void by_ref2_ok(int& ref) { ref++; }
int plus_plus_ok() { int plus_plus_ok() {
int x = 0; int x = 0;
@ -113,6 +124,25 @@ int plus_plus_loop_ok(int n) {
return i; return i;
} }
void capture1_ok() {
int x = 1;
[x]() { return x; }();
}
void capture2_ok(int x) {
[x]() { return x; }();
}
int FP_capture_by_ref_ok() {
int x = 0;
[&x]() { x++; }();
return x;
}
void init_capture_ok() {
[i = 0]() { return i; };
}
char* global; char* global;
void FP_assign_array_tricky_ok() { void FP_assign_array_tricky_ok() {

@ -1,4 +1,5 @@
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::FP_assign_array_tricky_ok, 3, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::FP_assign_array_tricky_ok, 3, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::FP_capture_by_ref_ok::lambda_dead_stores.cpp:138:3_operator(), 0, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::dead_pointer_bad, 2, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::dead_pointer_bad, 2, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::dead_then_live_bad, 1, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::dead_then_live_bad, 1, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::easy_bad, 0, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::easy_bad, 0, DEAD_STORE, [Write of unused value]

@ -27,6 +27,18 @@ int fooOK() {
return 5 / (4 - y(3)); return 5 / (4 - y(3));
} }
int normal_capture() {
int x = 1;
int y = 2;
return [x, y]() { return x + y; }();
}
int capture_by_ref() {
int x = 0;
[&x]() { x++; }();
return x;
}
void init_capture() { void init_capture() {
[i = 0]() { i; }; [i = 0]() { i; };
} }

@ -49,7 +49,45 @@ digraph iCFG {
"fooOK#_Z5fooOKv.17fb07f2bfe616303a58d2e25ed98781_4" -> "fooOK#_Z5fooOKv.17fb07f2bfe616303a58d2e25ed98781_3" ; "fooOK#_Z5fooOKv.17fb07f2bfe616303a58d2e25ed98781_4" -> "fooOK#_Z5fooOKv.17fb07f2bfe616303a58d2e25ed98781_3" ;
"init_capture#_Z12init_capturev.b56a308a8fe2b749cb39e3b566237ec2_1" [label="1: Start init_capture\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 30]\n " color=yellow style=filled] "normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_1" [label="1: Start normal_capture\nFormals: \nLocals: y:int x:int \n DECLARE_LOCALS(&return,&y,&x); [line 30]\n " color=yellow style=filled]
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_1" -> "normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_5" ;
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_2" [label="2: Exit normal_capture \n " color=yellow style=filled]
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_3" [label="3: Return Stmt \n n$0=_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:33:10_operator()((_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:33:10_operator(),&x,&y):normal_capture::lambda_shared_lambda_lambda1.cpp:33:10) [line 33]\n *&return:int=n$0 [line 33]\n " shape="box"]
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_3" -> "normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_2" ;
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_4" [label="4: DeclStmt \n *&y:int=2 [line 32]\n " shape="box"]
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_4" -> "normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_3" ;
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_5" [label="5: DeclStmt \n *&x:int=1 [line 31]\n " shape="box"]
"normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_5" -> "normal_capture#_Z14normal_capturev.9af9b723c040290ea713f2d1bc6c66e2_4" ;
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_1" [label="1: Start capture_by_ref\nFormals: \nLocals: x:int \n DECLARE_LOCALS(&return,&x); [line 36]\n " color=yellow style=filled]
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_1" -> "capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_5" ;
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_2" [label="2: Exit capture_by_ref \n " color=yellow style=filled]
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_3" [label="3: Return Stmt \n n$0=*&x:int [line 39]\n *&return:int=n$0 [line 39]\n " shape="box"]
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_3" -> "capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_2" ;
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_4" [label="4: Call _fun_capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3_operator() \n _fun_capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3_operator()((_fun_capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3_operator(),&x):capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3) [line 38]\n " shape="box"]
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_4" -> "capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_3" ;
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_5" [label="5: DeclStmt \n *&x:int=0 [line 37]\n " shape="box"]
"capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_5" -> "capture_by_ref#_Z14capture_by_refv.c683a8db53a834aa19283088dfffe460_4" ;
"init_capture#_Z12init_capturev.b56a308a8fe2b749cb39e3b566237ec2_1" [label="1: Start init_capture\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 42]\n " color=yellow style=filled]
"init_capture#_Z12init_capturev.b56a308a8fe2b749cb39e3b566237ec2_1" -> "init_capture#_Z12init_capturev.b56a308a8fe2b749cb39e3b566237ec2_2" ; "init_capture#_Z12init_capturev.b56a308a8fe2b749cb39e3b566237ec2_1" -> "init_capture#_Z12init_capturev.b56a308a8fe2b749cb39e3b566237ec2_2" ;
@ -132,11 +170,33 @@ digraph iCFG {
"operator()#lambda_shared_lambda_lambda1.cpp:26:12#fooOK#(_ZZ5fooOKvENK3$_3clEi).3d555a16319a7bb49d565b6ed9aa8c7f_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:26:12#fooOK#(_ZZ5fooOKvENK3$_3clEi).3d555a16319a7bb49d565b6ed9aa8c7f_2" ; "operator()#lambda_shared_lambda_lambda1.cpp:26:12#fooOK#(_ZZ5fooOKvENK3$_3clEi).3d555a16319a7bb49d565b6ed9aa8c7f_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:26:12#fooOK#(_ZZ5fooOKvENK3$_3clEi).3d555a16319a7bb49d565b6ed9aa8c7f_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:31:3#init_capture#(_ZZ12init_capturevENK3$_4clEv).1a4cfb9f400c66ee04ea1f7aeeef1d92_1" [label="1: Start init_capture::lambda_shared_lambda_lambda1.cpp:31:3_operator()\nFormals: this:init_capture::lambda_shared_lambda_lambda1.cpp:31:3*\nLocals: \n DECLARE_LOCALS(&return); [line 31]\n " color=yellow style=filled] "operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_1" [label="1: Start normal_capture::lambda_shared_lambda_lambda1.cpp:33:10_operator()\nFormals: this:normal_capture::lambda_shared_lambda_lambda1.cpp:33:10*\nLocals: \n DECLARE_LOCALS(&return); [line 33]\n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_3" ;
"operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_2" [label="2: Exit normal_capture::lambda_shared_lambda_lambda1.cpp:33:10_operator() \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_3" [label="3: Return Stmt \n n$0=*&x:int [line 33]\n n$1=*&y:int [line 33]\n *&return:int=(n$0 + n$1) [line 33]\n " shape="box"]
"operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:33:10#normal_capture#(_ZZ14normal_capturevENK3$_4clEv).d3f05aea738c7b3e4662812f831b95f4_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_1" [label="1: Start capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3_operator()\nFormals: this:capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3*\nLocals: \n DECLARE_LOCALS(&return); [line 38]\n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_3" ;
"operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_2" [label="2: Exit capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3_operator() \n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_3" [label="3: UnaryOperator \n n$0=*&x:int [line 38]\n *&x:int=(n$0 + 1) [line 38]\n " shape="box"]
"operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_3" -> "operator()#lambda_shared_lambda_lambda1.cpp:38:3#capture_by_ref#(_ZZ14capture_by_refvENK3$_5clEv).801ff4a46ab35f8d28f7ad0e26ae456e_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:43:3#init_capture#(_ZZ12init_capturevENK3$_6clEv).43d5b008ae982e3438cddd48c4a55f04_1" [label="1: Start init_capture::lambda_shared_lambda_lambda1.cpp:43:3_operator()\nFormals: this:init_capture::lambda_shared_lambda_lambda1.cpp:43:3*\nLocals: \n DECLARE_LOCALS(&return); [line 43]\n " color=yellow style=filled]
"operator()#lambda_shared_lambda_lambda1.cpp:31:3#init_capture#(_ZZ12init_capturevENK3$_4clEv).1a4cfb9f400c66ee04ea1f7aeeef1d92_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:31:3#init_capture#(_ZZ12init_capturevENK3$_4clEv).1a4cfb9f400c66ee04ea1f7aeeef1d92_2" ; "operator()#lambda_shared_lambda_lambda1.cpp:43:3#init_capture#(_ZZ12init_capturevENK3$_6clEv).43d5b008ae982e3438cddd48c4a55f04_1" -> "operator()#lambda_shared_lambda_lambda1.cpp:43:3#init_capture#(_ZZ12init_capturevENK3$_6clEv).43d5b008ae982e3438cddd48c4a55f04_2" ;
"operator()#lambda_shared_lambda_lambda1.cpp:31:3#init_capture#(_ZZ12init_capturevENK3$_4clEv).1a4cfb9f400c66ee04ea1f7aeeef1d92_2" [label="2: Exit init_capture::lambda_shared_lambda_lambda1.cpp:31:3_operator() \n " color=yellow style=filled] "operator()#lambda_shared_lambda_lambda1.cpp:43:3#init_capture#(_ZZ12init_capturevENK3$_6clEv).43d5b008ae982e3438cddd48c4a55f04_2" [label="2: Exit init_capture::lambda_shared_lambda_lambda1.cpp:43:3_operator() \n " color=yellow style=filled]
} }

Loading…
Cancel
Save