From 25d9f940fe27b0935c35a1cad42875d84a8386ec Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Tue, 1 Aug 2017 14:46:50 -0700 Subject: [PATCH] [dead stores] fix FPs due to capture by ref Reviewed By: jeremydubreil Differential Revision: D5534605 fbshipit-source-id: e8048a5 --- infer/src/checkers/liveness.ml | 15 +++++++++- .../cpp/liveness/dead_stores.cpp | 30 ++++++++++++++++++- .../codetoanalyze/cpp/liveness/issues.exp | 2 +- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/infer/src/checkers/liveness.ml b/infer/src/checkers/liveness.ml index 7c5171409..4b3180723 100644 --- a/infer/src/checkers/liveness.ml +++ b/infer/src/checkers/liveness.ml @@ -64,11 +64,24 @@ let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary = let invariant_map = Analyzer.exec_cfg cfg (ProcData.make_default proc_desc tenv) ~initial:Domain.empty ~debug:true in + let procname = Procdesc.get_proc_name proc_desc in + let is_cpp_lambda = + match Typ.Procname.get_method procname with "operator()" -> true | _ -> false + in + let is_captured_var pvar = + let pvar_name = Pvar.get_name pvar in + let pvar_matches (name, _) = Mangled.equal name pvar_name in + (* var is captured if the procedure is a lambda and the var is not in the locals or formals *) + is_cpp_lambda + && not + ( List.exists ~f:pvar_matches (Procdesc.get_locals proc_desc) + || List.exists ~f:pvar_matches (Procdesc.get_formals proc_desc) ) + in let report_dead_store live_vars = function | Sil.Store (Lvar pvar, _, _, loc) when not ( Pvar.is_frontend_tmp pvar || Pvar.is_return pvar || Pvar.is_global pvar - || Domain.mem (Var.of_pvar pvar) live_vars ) + || Domain.mem (Var.of_pvar pvar) live_vars || is_captured_var pvar ) -> let issue_id = Localise.to_issue_id Localise.dead_store in let message = F.asprintf "The value written to %a is never used" (Pvar.pp Pp.text) pvar in let ltr = [Errlog.make_trace_element 0 loc "Write of unused value" []] in diff --git a/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp b/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp index 7c9ee8a3b..1f18d91a4 100644 --- a/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp +++ b/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp @@ -124,6 +124,15 @@ int plus_plus_loop_ok(int n) { return i; } +void lambda_bad() { + int x = []() { + int y = 1; + y = 2; + return y; + }(); + return x; +} + void capture1_ok() { int x = 1; [x]() { return x; }(); @@ -133,12 +142,31 @@ void capture2_ok(int x) { [x]() { return x; }(); } -int FP_capture_by_ref_ok() { +int capture_by_ref1_ok() { int x = 0; [&x]() { x++; }(); return x; } +int capture_by_ref2_ok() { + int x = 0; + int y = 0; + [&]() { + x = x + y; + y = x; + }(); + return x + y; +} + +int FN_capture_by_ref_reuseBad() { + int x = 0; + [&x]() { + x = 1; // dead, but we won't report + x = 2; + }(); + return x; +} + void init_capture_ok() { [i = 0]() { return i; }; } diff --git a/infer/tests/codetoanalyze/cpp/liveness/issues.exp b/infer/tests/codetoanalyze/cpp/liveness/issues.exp index b88fe2923..980121935 100644 --- a/infer/tests/codetoanalyze/cpp/liveness/issues.exp +++ b/infer/tests/codetoanalyze/cpp/liveness/issues.exp @@ -1,8 +1,8 @@ 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_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::lambda_bad::lambda_dead_stores.cpp:128:11_operator(), 1, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::plus_plus1_bad, 2, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::plus_plus2_bad, 2, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::plus_plus3_bad, 2, DEAD_STORE, [Write of unused value]