From 9738f9821e6cbf875f0f0bcf1744d53b6fc4bb00 Mon Sep 17 00:00:00 2001 From: Daiva Naudziuniene Date: Mon, 11 Jun 2018 03:40:47 -0700 Subject: [PATCH] [frontend] Translating ToVoid cast Summary: We were missing reads of `a` if it was used in void cast, i.e. `(void) a;` This caused dead store false positives: we were not using `exp` that was the result of translating `a`. This diff creates a call to built-in skip function with `exp` as its argument, which causes the analyses to see reads of `exp`. Reviewed By: mbouaziz Differential Revision: D8332092 fbshipit-source-id: f3b0e10 --- infer/src/clang/cTrans_utils.ml | 10 ++++++++++ infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index cdc43d177..8b08691c0 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -480,6 +480,16 @@ let cast_operation cast_kind ((exp, typ) as exp_typ) cast_typ sil_loc = (instrs, (deref_exp, cast_typ)) | `NullToPointer -> if Exp.is_zero exp then ([], (Exp.null, cast_typ)) else ([], (exp, cast_typ)) + | `ToVoid -> + (* If exp is not used later, i.e. as in `(void) exp;` we miss reads *) + (* We create a call to skip function passing the exp as a parameter *) + let skip_builtin = Exp.Const (Const.Cfun BuiltinDecl.__infer_skip) in + let args = [(exp, typ)] in + let no_id = Ident.create_none () in + let call_instr = + Sil.Call ((no_id, cast_typ), skip_builtin, args, sil_loc, CallFlags.default) + in + ([call_instr], (exp, cast_typ)) | _ -> L.(debug Capture Verbose) "@\nWARNING: Missing translation for Cast Kind %s. The construct has been ignored...@\n" diff --git a/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp b/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp index 18da78707..921d94212 100644 --- a/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp +++ b/infer/tests/codetoanalyze/cpp/liveness/dead_stores.cpp @@ -338,6 +338,11 @@ struct NoDestructor {}; void dead_struct_no_destructor_bad() { NoDestructor dead; } +void no_destructor_void_read_ok() { + NoDestructor dead; + (void)dead; +} + struct NoDestructorDefinition { ~NoDestructorDefinition(); };