diff options
author | Anna Zaks <ganna@apple.com> | 2012-02-23 21:38:21 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-02-23 21:38:21 +0000 |
commit | df901a44198015c5c634ae71f86e9f0783588a19 (patch) | |
tree | 6b555b34c8f30d0dff7746970c61d9631fc8a56c /clang/lib/StaticAnalyzer | |
parent | fa31b8ef10abd5bc0ef9ed7dfb3ac77dcaaa668a (diff) | |
download | bcm5719-llvm-df901a44198015c5c634ae71f86e9f0783588a19.tar.gz bcm5719-llvm-df901a44198015c5c634ae71f86e9f0783588a19.zip |
[analyzer] Malloc: unique leak reports by allocation site.
When we find two leak reports with the same allocation site, report only
one of them.
Provide a helper method to BugReporter to facilitate this.
llvm-svn: 151287
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 40 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 4 |
2 files changed, 40 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 4ae1dd81efa..d6dc97a82c1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -186,6 +186,11 @@ private: static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const; + /// Find the location of the allocation for Sym on the path leading to the + /// exploded node N. + const Stmt *getAllocationSite(const ExplodedNode *N, SymbolRef Sym, + CheckerContext &C) const; + void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const; /// The bug visitor which allows us to print extra diagnostics along the @@ -766,6 +771,24 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){ return MallocMemAux(C, CE, TotalSize, zeroVal, state); } +const Stmt * +MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, + CheckerContext &C) const { + // Walk the ExplodedGraph backwards and find the first node that referred to + // the tracked symbol. + const ExplodedNode *AllocNode = N; + + while (N) { + if (!N->getState()->get<RegionState>(Sym)) + break; + AllocNode = N; + N = N->pred_empty() ? NULL : *(N->pred_begin()); + } + + ProgramPoint P = AllocNode->getLocation(); + return cast<clang::PostStmt>(P).getStmt(); +} + void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const { assert(N); @@ -779,8 +802,16 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, BT_Leak->setSuppressOnSink(true); } + // Most bug reports are cached at the location where they occurred. + // With leaks, we want to unique them by the location where they were + // allocated, and only report a single path. + const Stmt *AllocStmt = getAllocationSite(N, Sym, C); + PathDiagnosticLocation LocUsedForUniqueing = + PathDiagnosticLocation::createBegin(AllocStmt, C.getSourceManager(), + N->getLocationContext()); + BugReport *R = new BugReport(*BT_Leak, - "Memory is never released; potential memory leak", N); + "Memory is never released; potential memory leak", N, LocUsedForUniqueing); R->addVisitor(new MallocBugVisitor(Sym)); C.EmitReport(R); } @@ -818,14 +849,17 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, } } - ExplodedNode *N = C.addTransition(state->set<RegionState>(RS)); + // Generate leak node. + static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak"); + ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag); - if (N && generateReport) { + if (generateReport) { for (llvm::SmallVector<SymbolRef, 2>::iterator I = Errors.begin(), E = Errors.end(); I != E; ++I) { reportLeak(*I, N, C); } } + C.addTransition(state->set<RegionState>(RS), N); } void MallocChecker::checkEndPath(CheckerContext &C) const { diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 0df71f21fb8..0dbc7f115d5 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1270,7 +1270,9 @@ BugReport::~BugReport() { void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { hash.AddPointer(&BT); hash.AddString(Description); - if (Location.isValid()) { + if (UniqueingLocation.isValid()) { + UniqueingLocation.Profile(hash); + } else if (Location.isValid()) { Location.Profile(hash); } else { assert(ErrorNode); |