diff options
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/BugReporter.cpp | 47 | ||||
-rw-r--r-- | lib/Analysis/PathDiagnostic.cpp | 62 |
2 files changed, 109 insertions, 0 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 38e982888e..064fff47f4 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -1732,6 +1732,50 @@ static BugReport *FindReportInEquivalenceClass(BugReportEquivClass& EQ) { return NULL; } + +//===----------------------------------------------------------------------===// +// DiagnosticCache. This is a hack to cache analyzer diagnostics. It +// uses global state, which eventually should go elsewhere. +//===----------------------------------------------------------------------===// +namespace { +class VISIBILITY_HIDDEN DiagCacheItem : public llvm::FoldingSetNode { + llvm::FoldingSetNodeID ID; +public: + DiagCacheItem(BugReport *R, PathDiagnostic *PD) { + ID.AddString(R->getBugType().getName()); + ID.AddString(R->getBugType().getCategory()); + ID.AddString(R->getDescription()); + ID.AddInteger(R->getLocation().getRawEncoding()); + PD->Profile(ID); + } + + void Profile(llvm::FoldingSetNodeID &id) { + id = ID; + } + + llvm::FoldingSetNodeID &getID() { return ID; } +}; +} + +static bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) { + // FIXME: Eventually this diagnostic cache should reside in something + // like AnalysisManager instead of being a static variable. This is + // really unsafe in the long term. + typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache; + static DiagnosticCache DC; + + void *InsertPos; + DiagCacheItem *Item = new DiagCacheItem(R, PD); + + if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) { + delete Item; + return true; + } + + DC.InsertNode(Item, InsertPos); + return false; +} + void BugReporter::FlushReport(BugReportEquivClass& EQ) { BugReport *R = FindReportInEquivalenceClass(EQ); @@ -1752,6 +1796,9 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { GeneratePathDiagnostic(*D.get(), EQ); + if (IsCachedDiagnostic(R, D.get())) + return; + // Get the meta data. std::pair<const char**, const char**> Meta = R->getExtraDescriptiveText(); for (const char** s = Meta.first; s != Meta.second; ++s) diff --git a/lib/Analysis/PathDiagnostic.cpp b/lib/Analysis/PathDiagnostic.cpp index ceead6a3ac..800496a161 100644 --- a/lib/Analysis/PathDiagnostic.cpp +++ b/lib/Analysis/PathDiagnostic.cpp @@ -239,4 +239,66 @@ void PathDiagnosticLocation::flatten() { } } +//===----------------------------------------------------------------------===// +// FoldingSet profiling methods. +//===----------------------------------------------------------------------===// + +void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger((unsigned) K); + switch (K) { + case RangeK: + ID.AddInteger(R.getBegin().getRawEncoding()); + ID.AddInteger(R.getEnd().getRawEncoding()); + break; + case SingleLocK: + ID.AddInteger(R.getBegin().getRawEncoding()); + break; + case StmtK: + ID.Add(S); + break; + case DeclK: + ID.Add(D); + break; + } + return; +} + +void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger((unsigned) getKind()); + ID.AddString(str); + // FIXME: Add profiling support for code hints. + ID.AddInteger((unsigned) getDisplayHint()); + for (range_iterator I = ranges_begin(), E = ranges_end(); I != E; ++I) { + ID.AddInteger(I->getBegin().getRawEncoding()); + ID.AddInteger(I->getEnd().getRawEncoding()); + } +} + +void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const { + PathDiagnosticPiece::Profile(ID); + ID.Add(Pos); +} +void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const { + PathDiagnosticPiece::Profile(ID); + for (const_iterator I = begin(), E = end(); I != E; ++I) + ID.Add(*I); +} + +void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const { + PathDiagnosticSpotPiece::Profile(ID); + for (const_iterator I = begin(), E = end(); I != E; ++I) + ID.Add(**I); +} + +void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Size); + ID.AddString(BugType); + ID.AddString(Desc); + ID.AddString(Category); + for (const_iterator I = begin(), E = end(); I != E; ++I) + ID.Add(*I); + + for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I) + ID.AddString(*I); +} |