diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-02-18 23:28:26 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-02-18 23:28:26 +0000 |
commit | d55979238d90067fa0a9eb2730db969f93ab9bca (patch) | |
tree | 55d21530f2abda27eaf326a85850d43b12a4bf9a /lib/Analysis/CFRefCount.cpp | |
parent | 67a6b6bf004661182e1654edd24942c067701f8b (diff) |
retain/release checker: Place the leak diagnostic after the last statement that
references the tracked object.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64980 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 8a4b97be27..939e20a02d 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -2579,22 +2579,44 @@ CFRefLeakReport::getEndPath(BugReporter& br, const ExplodedNode<GRState>* EndN){ SourceManager& SMgr = BR.getContext().getSourceManager(); unsigned AllocLine =SMgr.getInstantiationLineNumber(FirstStmt->getLocStart()); - // Get the leak site. We may have multiple ExplodedNodes (one with the - // leak) that occur on the same line number; if the node with the leak - // has any immediate predecessor nodes with the same line number, find - // any transitive-successors that have a different statement and use that - // line number instead. This avoids emiting a diagnostic like: - // - // // 'y' is leaked. - // int x = foo(y); - // - // instead we want: - // - // int x = foo(y); - // // 'y' is leaked. + // Get the leak site. We want to find the last place where the symbol + // was used in an expression. + const ExplodedNode<GRState>* LeakN = EndN; + Stmt *S = 0; + + while (LeakN) { + ProgramPoint P = LeakN->getLocation(); + + + if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) + S = PS->getStmt(); + else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) + S = BE->getSrc()->getTerminator(); + + if (S) { + // Scan 'S' for uses of Sym. + GRStateRef state(LeakN->getState(), BR.getStateManager()); + bool foundSymbol = false; + + for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); + I!=E; ++I) + if (Expr *Ex = dyn_cast_or_null<Expr>(*I)) { + SVal X = state.GetSVal(Ex); + if (isa<loc::SymbolVal>(X) && + cast<loc::SymbolVal>(X).getSymbol() == Sym){ + foundSymbol = true; + break; + } + } + + if (foundSymbol) + break; + } + + LeakN = LeakN->pred_empty() ? 0 : *(LeakN->pred_begin()); + } - Stmt* S = getStmt(BR); // This is the statement where the leak occured. - assert (S); + assert(LeakN && S && "No leak site found."); // Generate the diagnostic. FullSourceLoc L(S->getLocStart(), SMgr); |