[cfe-commits] r167352 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp lib/StaticAnalyzer/Core/RegionStore.cpp lib/StaticAnalyzer/Core/SymbolManager.cpp test/Analysis/simple-stream-checks.c
Anna Zaks
ganna at apple.com
Fri Nov 2 19:54:21 PDT 2012
Author: zaks
Date: Fri Nov 2 21:54:20 2012
New Revision: 167352
URL: http://llvm.org/viewvc/llvm-project?rev=167352&view=rev
Log:
[analyzer] Run remove dead on end of path.
This will simplify checkers that need to register for leaks. Currently,
they have to register for both: check dead and check end of path.
I've modified the SymbolReaper to consider everything on the stack dead
if the input StackLocationContext is 0.
(This is a bit disruptive, so I'd like to flash out all the issues
asap.)
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp
cfe/trunk/test/Analysis/simple-stream-checks.c
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Fri Nov 2 21:54:20 2012
@@ -167,8 +167,12 @@
/// are usually reported here).
/// \param K - In some cases it is possible to use PreStmt kind. (Do
/// not use it unless you know what you are doing.)
+ /// If the ReferenceStmt is NULL, everything is this and parent contexts is
+ /// considered live.
+ /// If the stack frame context is NULL, everything on stack is considered
+ /// dead.
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
- const Stmt *ReferenceStmt, const LocationContext *LC,
+ const Stmt *ReferenceStmt, const StackFrameContext *LC,
const Stmt *DiagnosticStmt,
ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
@@ -219,6 +223,11 @@
void processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred);
+ /// Remove dead bindings/symbols before exiting a function.
+ void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
/// Generate the entry node of the callee.
void processCallEnter(CallEnter CE, ExplodedNode *Pred);
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h Fri Nov 2 21:54:20 2012
@@ -580,9 +580,11 @@
///
/// If the statement is NULL, everything is this and parent contexts is
/// considered live.
- SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr,
+ /// If the stack frame context is NULL, everything on stack is considered
+ /// dead.
+ SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
StoreManager &storeMgr)
- : LCtx(ctx->getCurrentStackFrame()), Loc(s), SymMgr(symmgr),
+ : LCtx(Ctx), Loc(s), SymMgr(symmgr),
reapedStore(0, storeMgr) {}
~SymbolReaper() {}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Nov 2 21:54:20 2012
@@ -268,12 +268,12 @@
void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt,
- const LocationContext *LC,
+ const StackFrameContext *LC,
const Stmt *DiagnosticStmt,
ProgramPoint::Kind K) {
assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
- ReferenceStmt == 0) && "PreStmt is not generally supported by "
- "the SymbolReaper yet");
+ ReferenceStmt == 0)
+ && "PostStmt is not generally supported by the SymbolReaper yet");
NumRemoveDeadBindings++;
CleanedState = Pred->getState();
SymbolReaper SymReaper(LC, ReferenceStmt, SymMgr, getStoreManager());
@@ -346,7 +346,7 @@
ExplodedNodeSet CleanedStates;
if (shouldRemoveDeadBindings(AMgr, S, Pred, EntryNode->getLocationContext())){
removeDead(EntryNode, CleanedStates, currStmt,
- Pred->getLocationContext(), currStmt);
+ Pred->getStackFrame(), currStmt);
} else
CleanedStates.Add(EntryNode);
@@ -1315,8 +1315,22 @@
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred) {
StateMgr.EndPath(Pred->getState());
+
ExplodedNodeSet Dst;
- getCheckerManager().runCheckersForEndPath(BC, Dst, Pred, *this);
+ if (Pred->getLocationContext()->inTopFrame()) {
+ // Remove dead symbols.
+ ExplodedNodeSet AfterRemovedDead;
+ removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);
+
+ // Notify checkers.
+ for (ExplodedNodeSet::iterator I = AfterRemovedDead.begin(),
+ E = AfterRemovedDead.end(); I != E; ++I) {
+ getCheckerManager().runCheckersForEndPath(BC, Dst, *I, *this);
+ }
+ } else {
+ getCheckerManager().runCheckersForEndPath(BC, Dst, Pred, *this);
+ }
+
Engine.enqueueEndOfFunction(Dst);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Fri Nov 2 21:54:20 2012
@@ -98,13 +98,16 @@
break;
}
+ if (Node->pred_empty())
+ return std::pair<const Stmt*, const CFGBlock*>(0, 0);
+
Node = *Node->pred_begin();
}
const CFGBlock *Blk = 0;
if (S) {
// Now, get the enclosing basic block.
- while (Node && Node->pred_size() >=1 ) {
+ while (Node) {
const ProgramPoint &PP = Node->getLocation();
if (isa<BlockEdge>(PP) &&
(PP.getLocationContext()->getCurrentStackFrame() == SF)) {
@@ -112,6 +115,9 @@
Blk = EPP.getDst();
break;
}
+ if (Node->pred_empty())
+ return std::pair<const Stmt*, const CFGBlock*>(S, 0);
+
Node = *Node->pred_begin();
}
}
@@ -157,6 +163,32 @@
return UnknownVal();
}
+void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ NodeBuilder Bldr(Pred, Dst, BC);
+
+ // Find the last statement in the function and the corresponding basic block.
+ const Stmt *LastSt = 0;
+ const CFGBlock *Blk = 0;
+ llvm::tie(LastSt, Blk) = getLastStmt(Pred);
+ if (!Blk || !LastSt) {
+ return;
+ }
+
+ // If the last statement is return, everything it references should stay live.
+ if (isa<ReturnStmt>(LastSt))
+ return;
+
+ // Here, we call the Symbol Reaper with 0 stack context telling it to clean up
+ // everything on the stack. We use LastStmt as a diagnostic statement, with
+ // which the PreStmtPurgeDead point will be associated.
+ currBldrCtx = &BC;
+ removeDead(Pred, Dst, 0, 0, LastSt,
+ ProgramPoint::PostStmtPurgeDeadSymbolsKind);
+ currBldrCtx = 0;
+}
+
/// The call exit is simulated with a sequence of nodes, which occur between
/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Fri Nov 2 21:54:20 2012
@@ -1805,7 +1805,8 @@
const StackArgumentsSpaceRegion *StackReg =
cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
const StackFrameContext *RegCtx = StackReg->getStackFrame();
- if (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx))
+ if (CurrentLCtx &&
+ (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx)))
AddToWorkList(TR, &C);
}
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp Fri Nov 2 21:54:20 2012
@@ -510,6 +510,9 @@
bool
SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
+ if (LCtx == 0)
+ return false;
+
if (LCtx != ELCtx) {
// If the reaper's location context is a parent of the expression's
// location context, then the expression value is now "out of scope".
@@ -517,6 +520,7 @@
return false;
return true;
}
+
// If no statement is provided, everything is this and parent contexts is live.
if (!Loc)
return true;
@@ -526,6 +530,12 @@
bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
const StackFrameContext *VarContext = VR->getStackFrame();
+
+ if (!VarContext)
+ return true;
+
+ if (!LCtx)
+ return false;
const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
if (VarContext == CurrentContext) {
@@ -557,7 +567,7 @@
return false;
}
- return !VarContext || VarContext->isParentOf(CurrentContext);
+ return VarContext->isParentOf(CurrentContext);
}
SymbolVisitor::~SymbolVisitor() {}
Modified: cfe/trunk/test/Analysis/simple-stream-checks.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/simple-stream-checks.c?rev=167352&r1=167351&r2=167352&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/simple-stream-checks.c (original)
+++ cfe/trunk/test/Analysis/simple-stream-checks.c Fri Nov 2 21:54:20 2012
@@ -49,3 +49,17 @@
fclose(F);
int x = 0; // no warning
}
+
+void leakOnEnfOfPath1(int *Data) {
+ FILE *F = fopen("myfile.txt", "w");// expected-warning {{Opened file is never closed; potential resource leak}}
+}
+
+void leakOnEnfOfPath2(int *Data) {
+ FILE *F = fopen("myfile.txt", "w");
+ return; // expected-warning {{Opened file is never closed; potential resource leak}}
+}
+
+FILE *leakOnEnfOfPath3(int *Data) {
+ FILE *F = fopen("myfile.txt", "w");
+ return F;
+}
More information about the cfe-commits
mailing list