diff options
author | Kristof Umann <kristof.umann@ericsson.com> | 2019-09-03 15:22:43 +0000 |
---|---|---|
committer | Kristof Umann <kristof.umann@ericsson.com> | 2019-09-03 15:22:43 +0000 |
commit | 3b18b050b8fc132ee09e2457f0bb98386fe181f8 (patch) | |
tree | 58138a4580c10d61b44af84fba36f3e095085b9c /clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | |
parent | de524038436c647d0ebae88cad16b542a0d2210a (diff) | |
download | bcm5719-llvm-3b18b050b8fc132ee09e2457f0bb98386fe181f8.tar.gz bcm5719-llvm-3b18b050b8fc132ee09e2457f0bb98386fe181f8.zip |
[analyzer] Add a checker option to detect nested dead stores
Enables the users to specify an optional flag which would warn for more dead
stores.
Previously it ignored if the dead store happened e.g. in an if condition.
if ((X = generate())) { // dead store to X
}
This patch introduces the `WarnForDeadNestedAssignments` option to the checker,
which is `false` by default - so this change would not affect any previous
users.
I have updated the code, tests and the docs as well. If I missed something, tell
me.
I also ran the analysis on Clang which generated 14 more reports compared to the
unmodified version. All of them seemed reasonable for me.
Related previous patches:
rGf224820b45c6847b91071da8d7ade59f373b96f3
Reviewers: NoQ, krememek, Szelethus, baloghadamsoftware
Reviewed By: Szelethus
Patch by Balázs Benics!
Differential Revision: https://reviews.llvm.org/D66733
llvm-svn: 370767
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index d5baa2bcba6..e4889c1cc14 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -130,6 +130,7 @@ class DeadStoreObs : public LiveVariables::Observer { std::unique_ptr<ReachableCode> reachableCode; const CFGBlock *currentBlock; std::unique_ptr<llvm::DenseSet<const VarDecl *>> InEH; + const bool WarnForDeadNestedAssignments; enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit }; @@ -137,9 +138,11 @@ public: DeadStoreObs(const CFG &cfg, ASTContext &ctx, BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac, ParentMap &parents, - llvm::SmallPtrSet<const VarDecl *, 20> &escaped) + llvm::SmallPtrSet<const VarDecl *, 20> &escaped, + bool warnForDeadNestedAssignments) : cfg(cfg), Ctx(ctx), BR(br), Checker(checker), AC(ac), Parents(parents), - Escaped(escaped), currentBlock(nullptr) {} + Escaped(escaped), currentBlock(nullptr), + WarnForDeadNestedAssignments(warnForDeadNestedAssignments) {} ~DeadStoreObs() override {} @@ -217,11 +220,16 @@ public: os << "Value stored to '" << *V << "' is never read"; break; + // eg.: f((x = foo())) case Enclosing: - // Don't report issues in this case, e.g.: "if (x = foo())", - // where 'x' is unused later. We have yet to see a case where - // this is a real bug. - return; + if (!WarnForDeadNestedAssignments) + return; + BugType = "Dead nested assignment"; + os << "Although the value stored to '" << *V + << "' is used in the enclosing expression, the value is never " + "actually read from '" + << *V << "'"; + break; } BR.EmitBasicReport(AC->getDecl(), Checker, BugType, "Dead store", os.str(), @@ -474,6 +482,8 @@ public: namespace { class DeadStoresChecker : public Checker<check::ASTCodeBody> { public: + bool WarnForDeadNestedAssignments = true; + void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { @@ -491,15 +501,20 @@ public: ParentMap &pmap = mgr.getParentMap(D); FindEscaped FS; cfg.VisitBlockStmts(FS); - DeadStoreObs A(cfg, BR.getContext(), BR, this, AC, pmap, FS.Escaped); + DeadStoreObs A(cfg, BR.getContext(), BR, this, AC, pmap, FS.Escaped, + WarnForDeadNestedAssignments); L->runOnAllBlocks(A); } } }; } -void ento::registerDeadStoresChecker(CheckerManager &mgr) { - mgr.registerChecker<DeadStoresChecker>(); +void ento::registerDeadStoresChecker(CheckerManager &Mgr) { + auto Chk = Mgr.registerChecker<DeadStoresChecker>(); + + const AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions(); + Chk->WarnForDeadNestedAssignments = + AnOpts.getCheckerBooleanOption(Chk, "WarnForDeadNestedAssignments"); } bool ento::shouldRegisterDeadStoresChecker(const LangOptions &LO) { |