diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 01db5196a..647ac5c66 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -2671,16 +2671,35 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s CFrontend_config.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range "Capture-init statement without var decl" in - let translate_normal_capture pvar_typ (trans_results_acc, captured_vars_acc) = + let translate_normal_capture ~is_by_ref ((pvar, typ) as pvar_typ) + (trans_results_acc, captured_vars_acc) = let loc = CLocation.get_sil_location stmt_info context in - let id, instr = assign_captured_var loc pvar_typ in - let trans_results = {empty_res_trans with instrs= [instr]} in - ( trans_results :: trans_results_acc - , (Exp.Var id, fst pvar_typ, snd pvar_typ) :: captured_vars_acc ) + if is_by_ref then (trans_results_acc, (Exp.Lvar pvar, pvar, typ) :: captured_vars_acc) + else + let id, instr = assign_captured_var loc pvar_typ in + let trans_results = {empty_res_trans with instrs= [instr]} in + (trans_results :: trans_results_acc, (Exp.Var id, pvar, typ) :: captured_vars_acc) in let translate_captured - {Clang_ast_t.lci_captured_var; lci_init_captured_vardecl; lci_capture_this} - ((trans_results_acc, captured_vars_acc) as acc) = + { Clang_ast_t.lci_captured_var + ; lci_init_captured_vardecl + ; lci_capture_this + ; lci_capture_kind } ((trans_results_acc, captured_vars_acc) as acc) = + let is_by_ref = + (* see http://en.cppreference.com/w/cpp/language/lambda *) + match lci_capture_kind with + | `LCK_ByRef (* explicit with [&x] or implicit with [&] *) + | `LCK_This (* explicit with [this] or implicit with [&] *) + | `LCK_VLAType + (* capture a variable-length array by reference. we probably don't handle + this correctly elsewhere, but it's definitely not captured by value! *) -> + true + | `LCK_ByCopy (* explicit with [x] or implicit with [=] *) -> + (* [=] captures this by reference and everything else by value *) + lci_capture_this + | `LCK_StarThis (* [*this] is special syntax for capturing current object by value *) -> + false + in match (lci_captured_var, lci_init_captured_vardecl) with | Some captured_var_decl_ref, Some init_decl -> (* capture and init *) @@ -2690,12 +2709,12 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | Some captured_var_decl_ref, None -> (* just capture *) let pvar_typ = get_captured_pvar_typ captured_var_decl_ref in - translate_normal_capture pvar_typ acc + translate_normal_capture ~is_by_ref pvar_typ acc | None, None -> if lci_capture_this then (* captured [this] *) let this_typ = get_this_pvar_typ stmt_info context in - translate_normal_capture this_typ acc + translate_normal_capture ~is_by_ref this_typ acc else acc | None, Some _ -> CFrontend_config.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range diff --git a/infer/tests/codetoanalyze/cpp/shared/lambda/lambda1.cpp.dot b/infer/tests/codetoanalyze/cpp/shared/lambda/lambda1.cpp.dot index aeabe402f..272ed0a9f 100644 --- a/infer/tests/codetoanalyze/cpp/shared/lambda/lambda1.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/shared/lambda/lambda1.cpp.dot @@ -79,7 +79,7 @@ digraph cfg { "capture_by_ref#4375601249296069049.1d794578c048d96b25fb1e90dbaa8225_3" -> "capture_by_ref#4375601249296069049.1d794578c048d96b25fb1e90dbaa8225_2" ; -"capture_by_ref#4375601249296069049.1d794578c048d96b25fb1e90dbaa8225_4" [label="4: Call _fun_capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3_operator() \n n$1=*&x:int [line 38, column 3]\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(),(n$1 &x:int)):capture_by_ref::lambda_shared_lambda_lambda1.cpp:38:3) [line 38, column 3]\n " shape="box"] +"capture_by_ref#4375601249296069049.1d794578c048d96b25fb1e90dbaa8225_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, column 3]\n " shape="box"] "capture_by_ref#4375601249296069049.1d794578c048d96b25fb1e90dbaa8225_4" -> "capture_by_ref#4375601249296069049.1d794578c048d96b25fb1e90dbaa8225_3" ; @@ -140,7 +140,7 @@ digraph cfg { "capture_this_explicit#Capture#(13194085360619722149).2dba35a78268b10ad413414cc832a8f0_3" -> "capture_this_explicit#Capture#(13194085360619722149).2dba35a78268b10ad413414cc832a8f0_2" ; -"capture_this_explicit#Capture#(13194085360619722149).2dba35a78268b10ad413414cc832a8f0_4" [label="4: DeclStmt \n n$2=*&this:Capture* [line 55, column 19]\n *&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19=(_fun_Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19_operator(),(n$2 &this:Capture*)) [line 55, column 19]\n _fun_Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19_(&lambda:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19*,&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19&) [line 55, column 19]\n " shape="box"] +"capture_this_explicit#Capture#(13194085360619722149).2dba35a78268b10ad413414cc832a8f0_4" [label="4: DeclStmt \n *&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19=(_fun_Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19_operator(),&this) [line 55, column 19]\n _fun_Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19_(&lambda:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19*,&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_explicit::lambda_shared_lambda_lambda1.cpp:55:19&) [line 55, column 19]\n " shape="box"] "capture_this_explicit#Capture#(13194085360619722149).2dba35a78268b10ad413414cc832a8f0_4" -> "capture_this_explicit#Capture#(13194085360619722149).2dba35a78268b10ad413414cc832a8f0_3" ; @@ -170,7 +170,7 @@ digraph cfg { "capture_this_with_equal#Capture#(805776379555510952).ecd73e9a4e2bef0d060a242b61508f10_3" -> "capture_this_with_equal#Capture#(805776379555510952).ecd73e9a4e2bef0d060a242b61508f10_2" ; -"capture_this_with_equal#Capture#(805776379555510952).ecd73e9a4e2bef0d060a242b61508f10_4" [label="4: DeclStmt \n n$2=*&this:Capture* [line 65, column 19]\n *&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19=(_fun_Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19_operator(),(n$2 &this:Capture*)) [line 65, column 19]\n _fun_Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19_(&lambda:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19*,&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19&) [line 65, column 19]\n " shape="box"] +"capture_this_with_equal#Capture#(805776379555510952).ecd73e9a4e2bef0d060a242b61508f10_4" [label="4: DeclStmt \n *&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19=(_fun_Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19_operator(),&this) [line 65, column 19]\n _fun_Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19_(&lambda:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19*,&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_equal::lambda_shared_lambda_lambda1.cpp:65:19&) [line 65, column 19]\n " shape="box"] "capture_this_with_equal#Capture#(805776379555510952).ecd73e9a4e2bef0d060a242b61508f10_4" -> "capture_this_with_equal#Capture#(805776379555510952).ecd73e9a4e2bef0d060a242b61508f10_3" ; @@ -185,7 +185,7 @@ digraph cfg { "capture_this_with_auto#Capture#(15696525048884093218).38be242109186a45cc282c38962c68e2_3" -> "capture_this_with_auto#Capture#(15696525048884093218).38be242109186a45cc282c38962c68e2_2" ; -"capture_this_with_auto#Capture#(15696525048884093218).38be242109186a45cc282c38962c68e2_4" [label="4: DeclStmt \n n$2=*&this:Capture* [line 69, column 19]\n *&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19=(_fun_Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19_operator(),(n$2 &this:Capture*)) [line 69, column 19]\n _fun_Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19_(&lambda:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19*,&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19&) [line 69, column 19]\n " shape="box"] +"capture_this_with_auto#Capture#(15696525048884093218).38be242109186a45cc282c38962c68e2_4" [label="4: DeclStmt \n *&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19=(_fun_Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19_operator(),&this) [line 69, column 19]\n _fun_Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19_(&lambda:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19*,&0$?%__sil_tmpSIL_materialize_temp__n$1:Capture::capture_this_with_auto::lambda_shared_lambda_lambda1.cpp:69:19&) [line 69, column 19]\n " shape="box"] "capture_this_with_auto#Capture#(15696525048884093218).38be242109186a45cc282c38962c68e2_4" -> "capture_this_with_auto#Capture#(15696525048884093218).38be242109186a45cc282c38962c68e2_3" ;