summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
diff options
context:
space:
mode:
authorKristof Umann <kristof.umann@ericsson.com>2019-09-03 15:22:43 +0000
committerKristof Umann <kristof.umann@ericsson.com>2019-09-03 15:22:43 +0000
commit3b18b050b8fc132ee09e2457f0bb98386fe181f8 (patch)
tree58138a4580c10d61b44af84fba36f3e095085b9c /clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
parentde524038436c647d0ebae88cad16b542a0d2210a (diff)
downloadbcm5719-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.cpp33
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) {
OpenPOWER on IntegriCloud