[dead stores] config file for custom scope guard types

Reviewed By: da319

Differential Revision: D6517706

fbshipit-source-id: 3b6f805
master
Sam Blackshear 7 years ago committed by Facebook Github Bot
parent 432fa4913c
commit 647e1cd62d

@ -975,6 +975,12 @@ and cxx_infer_headers =
"Include C++ header models during compilation. Infer swaps some C++ headers for its own in order to get a better model of, eg, the standard library. This can sometimes cause compilation failures." "Include C++ header models during compilation. Infer swaps some C++ headers for its own in order to get a better model of, eg, the standard library. This can sometimes cause compilation failures."
and cxx_scope_guards =
CLOpt.mk_json ~long:"cxx-scope-guards"
~in_help:CLOpt.([(Analyze, manual_clang)])
"Specify scope guard classes that can be read only by destructors without being reported as dead stores."
and cxx = and cxx =
CLOpt.mk_bool ~long:"cxx" ~default:true CLOpt.mk_bool ~long:"cxx" ~default:true
~in_help:CLOpt.([(Capture, manual_clang)]) ~in_help:CLOpt.([(Capture, manual_clang)])
@ -2347,6 +2353,8 @@ and cxx = !cxx
and cxx_infer_headers = !cxx_infer_headers and cxx_infer_headers = !cxx_infer_headers
and cxx_scope_guards = !cxx_scope_guards
and debug_level_analysis = !debug_level_analysis and debug_level_analysis = !debug_level_analysis
and debug_level_capture = !debug_level_capture and debug_level_capture = !debug_level_capture

@ -356,6 +356,8 @@ val cxx : bool
val cxx_infer_headers : bool val cxx_infer_headers : bool
val cxx_scope_guards : Yojson.Basic.json
val debug_level_analysis : int val debug_level_analysis : int
val debug_level_capture : int val debug_level_capture : int

@ -85,6 +85,37 @@ end
module CFG = ProcCfg.OneInstrPerNode (ProcCfg.Backward (ProcCfg.Exceptional)) module CFG = ProcCfg.OneInstrPerNode (ProcCfg.Backward (ProcCfg.Exceptional))
module Analyzer = AbstractInterpreter.Make (CFG) (TransferFunctions) module Analyzer = AbstractInterpreter.Make (CFG) (TransferFunctions)
(* It's fine to have a dead store on a type that uses the "scope guard" pattern. These types
are only read in their destructors, and this is expected/ok.
(e.g., https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h). *)
let matcher_scope_guard =
let of_json init = function
| `List scope_guards ->
List.fold scope_guards ~f:(fun acc json -> Yojson.Basic.Util.to_string json :: acc) ~init
| _ ->
init
in
let default_scope_guards =
[ (* C++ *)
"folly::RWSpinLock::ReadHolder"
; "folly::RWSpinLock::WriteHolder"
; "folly::ScopeGuard"
; "folly::SharedMutex::ReadHolder"
; "folly::SharedMutex::WriteHolder"
; "folly::SharedMutexReadPriority::ReadHolder"
; "folly::SharedMutexReadPriority::WriteHolder"
; "folly::SharedMutexWritePriority::ReadHolder"
; "folly::SharedMutexWritePriority::WriteHolder"
; "folly::SpinLockGuard"
; "std::lock_guard"
; "std::scoped_lock"
; "std::unique_lock" (* Obj-C *)
; "CKComponentScope" ]
in
of_json default_scope_guards Config.cxx_scope_guards
|> QualifiedCppName.Match.of_fuzzy_qual_names
let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary = let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary =
let cfg = CFG.from_pdesc proc_desc in let cfg = CFG.from_pdesc proc_desc in
let invariant_map = let invariant_map =
@ -101,28 +132,6 @@ let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary =
| _ -> | _ ->
false false
in in
let matcher_scope_guard =
QualifiedCppName.Match.of_fuzzy_qual_names
[ (* C++ *)
"faiss::ScopeDeleter"
; "folly::RWSpinLock::ReadHolder"
; "folly::RWSpinLock::WriteHolder"
; "folly::ScopeGuard"
; "folly::SharedMutex::ReadHolder"
; "folly::SharedMutex::WriteHolder"
; "folly::SharedMutexReadPriority::ReadHolder"
; "folly::SharedMutexReadPriority::WriteHolder"
; "folly::SharedMutexWritePriority::ReadHolder"
; "folly::SharedMutexWritePriority::WriteHolder"
; "folly::SpinLockGuard"
; "std::lock_guard"
; "std::scoped_lock"
; "std::unique_lock" (* Obj-C *)
; "CKComponentScope" ]
in
(* It's fine to have a dead store on a type that uses the "scope guard" pattern. These types
are only read in their destructors, and this is expected/ok.
(e.g., https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h). *)
let rec is_scope_guard = function let rec is_scope_guard = function
| {Typ.desc= Tstruct name} -> | {Typ.desc= Tstruct name} ->
QualifiedCppName.Match.match_qualifiers matcher_scope_guard (Typ.Name.qual_name name) QualifiedCppName.Match.match_qualifiers matcher_scope_guard (Typ.Name.qual_name name)
@ -169,3 +178,4 @@ let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary =
in in
List.iter (CFG.nodes cfg) ~f:report_on_node ; List.iter (CFG.nodes cfg) ~f:report_on_node ;
summary summary

@ -0,0 +1,5 @@
{
"cxx-scope-guards": [
"infer::ScopeGuard"
]
}

@ -11,6 +11,10 @@
#include <new> #include <new>
#include <thread> #include <thread>
namespace infer {
class ScopeGuard {};
}; // namespace infer
namespace folly { namespace folly {
class ScopeGuard {}; class ScopeGuard {};
@ -301,6 +305,8 @@ void read_holder_ok() { folly::SharedMutex::ReadHolder guard; }
void write_holder_ok() { folly::SharedMutex::WriteHolder guard; } void write_holder_ok() { folly::SharedMutex::WriteHolder guard; }
void custom_scope_guard_ok() { infer::ScopeGuard guard; }
struct S { struct S {
~S() {} ~S() {}
}; };

@ -6,7 +6,7 @@ codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::dead_then_live_bad, 1,
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]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::init_capture_no_call_bad, 1, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::init_capture_no_call_bad, 1, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::init_capture_reassign_bad, 1, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::init_capture_reassign_bad, 1, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::lambda_bad::lambda_dead_stores.cpp:160:11_operator(), 1, DEAD_STORE, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::lambda_bad::lambda_dead_stores.cpp:164: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_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_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] codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::plus_plus3_bad, 2, DEAD_STORE, [Write of unused value]

Loading…
Cancel
Save