[cfe-commits] r125415 - in /cfe/trunk: include/clang/Analysis/Analyses/LiveVariables.h include/clang/Analysis/FlowSensitive/DataflowSolver.h lib/Analysis/LiveVariables.cpp lib/Analysis/UninitializedValues.cpp lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp test/Analysis/dead-stores.c test/Analysis/unreachable-code-path.c
Ted Kremenek
kremenek at apple.com
Fri Feb 11 15:24:27 PST 2011
Author: kremenek
Date: Fri Feb 11 17:24:26 2011
New Revision: 125415
URL: http://llvm.org/viewvc/llvm-project?rev=125415&view=rev
Log:
Don't report dead stores on unreachable code paths. Fixes <rdar://problem/8405222>.
Modified:
cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h
cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h
cfe/trunk/lib/Analysis/LiveVariables.cpp
cfe/trunk/lib/Analysis/UninitializedValues.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
cfe/trunk/test/Analysis/dead-stores.c
cfe/trunk/test/Analysis/unreachable-code-path.c
Modified: cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h Fri Feb 11 17:24:26 2011
@@ -55,7 +55,8 @@
/// ObserveStmt - A callback invoked right before invoking the
/// liveness transfer function on the given statement.
- virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD,
+ virtual void ObserveStmt(Stmt* S, const CFGBlock *currentBlock,
+ const AnalysisDataTy& AD,
const ValTy& V) {}
virtual void ObserverKill(DeclRefExpr* DR) {}
Modified: cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h (original)
+++ cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h Fri Feb 11 17:24:26 2011
@@ -273,6 +273,8 @@
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
dataflow::forward_analysis_tag) {
+ TF.setCurrentBlock(B);
+
for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
CFGElement El = *I;
if (CFGStmt S = El.getAs<CFGStmt>())
@@ -285,6 +287,8 @@
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
dataflow::backward_analysis_tag) {
+ TF.setCurrentBlock(B);
+
TF.VisitTerminator(const_cast<CFGBlock*>(B));
for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
Modified: cfe/trunk/lib/Analysis/LiveVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/LiveVariables.cpp?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/LiveVariables.cpp (original)
+++ cfe/trunk/lib/Analysis/LiveVariables.cpp Fri Feb 11 17:24:26 2011
@@ -104,8 +104,9 @@
class TransferFuncs : public CFGRecStmtVisitor<TransferFuncs>{
LiveVariables::AnalysisDataTy& AD;
LiveVariables::ValTy LiveState;
+ const CFGBlock *currentBlock;
public:
- TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+ TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad), currentBlock(0) {}
LiveVariables::ValTy& getVal() { return LiveState; }
CFG& getCFG() { return AD.getCFG(); }
@@ -128,7 +129,10 @@
void SetTopValue(LiveVariables::ValTy& V) {
V = AD.AlwaysLive;
}
-
+
+ void setCurrentBlock(const CFGBlock *block) {
+ currentBlock = block;
+ }
};
void TransferFuncs::Visit(Stmt *S) {
@@ -136,7 +140,7 @@
if (S == getCurrentBlkStmt()) {
if (AD.Observer)
- AD.Observer->ObserveStmt(S,AD,LiveState);
+ AD.Observer->ObserveStmt(S, currentBlock, AD, LiveState);
if (getCFG().isBlkExpr(S))
LiveState(S, AD) = Dead;
@@ -146,7 +150,7 @@
else if (!getCFG().isBlkExpr(S)) {
if (AD.Observer)
- AD.Observer->ObserveStmt(S,AD,LiveState);
+ AD.Observer->ObserveStmt(S, currentBlock, AD, LiveState);
StmtVisitor<TransferFuncs,void>::Visit(S);
Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Fri Feb 11 17:24:26 2011
@@ -79,6 +79,8 @@
bool BlockStmt_VisitExpr(Expr* E);
void VisitTerminator(CFGBlock* B) { }
+
+ void setCurrentBlock(const CFGBlock *block) {}
};
static const bool Initialized = false;
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp Fri Feb 11 17:24:26 2011
@@ -28,26 +28,80 @@
namespace {
+// FIXME: Eventually migrate into its own file, and have it managed by
+// AnalysisManager.
+class ReachableCode {
+ const CFG &cfg;
+ llvm::BitVector reachable;
+public:
+ ReachableCode(const CFG &cfg)
+ : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
+
+ void computeReachableBlocks();
+
+ bool isReachable(const CFGBlock *block) const {
+ return reachable[block->getBlockID()];
+ }
+};
+}
+
+void ReachableCode::computeReachableBlocks() {
+ if (!cfg.getNumBlockIDs())
+ return;
+
+ llvm::SmallVector<const CFGBlock*, 10> worklist;
+ worklist.push_back(&cfg.getEntry());
+
+ while (!worklist.empty()) {
+ const CFGBlock *block = worklist.back();
+ worklist.pop_back();
+ llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
+ if (isReachable)
+ continue;
+ isReachable = true;
+ for (CFGBlock::const_succ_iterator i = block->succ_begin(),
+ e = block->succ_end(); i != e; ++i)
+ if (const CFGBlock *succ = *i)
+ worklist.push_back(succ);
+ }
+}
+
+namespace {
class DeadStoreObs : public LiveVariables::ObserverTy {
+ const CFG &cfg;
ASTContext &Ctx;
BugReporter& BR;
ParentMap& Parents;
llvm::SmallPtrSet<VarDecl*, 20> Escaped;
+ llvm::OwningPtr<ReachableCode> reachableCode;
+ const CFGBlock *currentBlock;
enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
public:
- DeadStoreObs(ASTContext &ctx, BugReporter& br, ParentMap& parents,
+ DeadStoreObs(const CFG &cfg, ASTContext &ctx,
+ BugReporter& br, ParentMap& parents,
llvm::SmallPtrSet<VarDecl*, 20> &escaped)
- : Ctx(ctx), BR(br), Parents(parents), Escaped(escaped) {}
+ : cfg(cfg), Ctx(ctx), BR(br), Parents(parents),
+ Escaped(escaped), currentBlock(0) {}
virtual ~DeadStoreObs() {}
void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
if (Escaped.count(V))
return;
+
+ // Compute reachable blocks within the CFG for trivial cases
+ // where a bogus dead store can be reported because itself is unreachable.
+ if (!reachableCode.get()) {
+ reachableCode.reset(new ReachableCode(cfg));
+ reachableCode->computeReachableBlocks();
+ }
+
+ if (!reachableCode->isReachable(currentBlock))
+ return;
- std::string name = V->getNameAsString();
+ const std::string &name = V->getNameAsString();
const char* BugType = 0;
std::string msg;
@@ -127,10 +181,12 @@
return false;
}
- virtual void ObserveStmt(Stmt* S,
+ virtual void ObserveStmt(Stmt* S, const CFGBlock *block,
const LiveVariables::AnalysisDataTy& AD,
const LiveVariables::ValTy& Live) {
+ currentBlock = block;
+
// Skip statements in macros.
if (S->getLocStart().isMacroID())
return;
@@ -284,6 +340,6 @@
BugReporter& BR) {
FindEscaped FS(&cfg);
FS.getCFG().VisitBlockStmts(FS);
- DeadStoreObs A(BR.getContext(), BR, pmap, FS.Escaped);
+ DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped);
L.runOnAllBlocks(cfg, &A);
}
Modified: cfe/trunk/test/Analysis/dead-stores.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.c?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.c (original)
+++ cfe/trunk/test/Analysis/dead-stores.c Fri Feb 11 17:24:26 2011
@@ -175,15 +175,37 @@
x = 10; // expected-warning{{Value stored to 'x' is never read}}
while (1)
x = 10; // expected-warning{{Value stored to 'x' is never read}}
+ // unreachable.
do
- x = 10; // expected-warning{{Value stored to 'x' is never read}}
+ x = 10; // no-warning
while (1);
+ return (x = 10); // no-warning
+}
- // Don't warn for dead stores in nested expressions. We have yet
- // to see a real bug in this scenario.
+int f18_a() {
+ int x = 0; // no-warning
return (x = 10); // no-warning
}
+void f18_b() {
+ int x = 0; // no-warning
+ if (1)
+ x = 10; // expected-warning{{Value stored to 'x' is never read}}
+}
+
+void f18_c() {
+ int x = 0;
+ while (1)
+ x = 10; // expected-warning{{Value stored to 'x' is never read}}
+}
+
+void f18_d() {
+ int x = 0; // no-warning
+ do
+ x = 10; // expected-warning{{Value stored to 'x' is never read}}
+ while (1);
+}
+
// PR 3514: false positive `dead initialization` warning for init to global
// http://llvm.org/bugs/show_bug.cgi?id=3514
extern const int MyConstant;
@@ -492,3 +514,16 @@
}while (--m);
}
+// Avoid dead stores resulting from an assignment (and use) being unreachable.
+void rdar8405222_aux(int i);
+void rdar8405222() {
+ const int show = 0;
+ int i = 0;
+
+ if (show)
+ i = 5; // no-warning
+
+ if (show)
+ rdar8405222_aux(i);
+}
+
Modified: cfe/trunk/test/Analysis/unreachable-code-path.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/unreachable-code-path.c?rev=125415&r1=125414&r2=125415&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/unreachable-code-path.c (original)
+++ cfe/trunk/test/Analysis/unreachable-code-path.c Fri Feb 11 17:24:26 2011
@@ -114,9 +114,9 @@
goto b; // expected-warning {{never executed}}
goto a; // expected-warning {{never executed}}
b:
- i = 1; // expected-warning {{Value stored to 'i' is never read}}
+ i = 1; // no-warning
a:
- i = 2; // expected-warning {{Value stored to 'i' is never read}}
+ i = 2; // no-warning
goto f;
e:
goto d;
More information about the cfe-commits
mailing list