diff options
author | Eric Christopher <echristo@apple.com> | 2011-08-24 00:39:48 +0000 |
---|---|---|
committer | Eric Christopher <echristo@apple.com> | 2011-08-24 00:39:48 +0000 |
commit | f21e2b47ee29b3c9679570ecaeda9564ee47519f (patch) | |
tree | a4a1189d29bdc9b8c0520e33f72f0c4f2e008a2d /lib/StaticAnalyzer/Core/CFRefCount.cpp | |
parent | 736a9c211c065784f7a7889ade55aa569a89520e (diff) |
Revert "[analyzer] Make CFRefBug and CFRefReportVisitor not dependent on CFRefCount. Unfortunately, CFRefReport still is. No functionality change."
This reverts commit e3fb7e428b7ba0d5d902dfe3f165d70e09b03a15.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138419 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CFRefCount.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CFRefCount.cpp | 158 |
1 files changed, 89 insertions, 69 deletions
diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp index 93f7aae94d..2d1b822b3e 100644 --- a/lib/StaticAnalyzer/Core/CFRefCount.cpp +++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp @@ -1742,6 +1742,8 @@ void CFRefCount::BindingsPrinter::Print(raw_ostream &Out, //===----------------------------------------------------------------------===// // Error reporting. //===----------------------------------------------------------------------===// +static void addExtraTextToCFReport(BugReport &R); + namespace { typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *> SummaryLogTy; @@ -1752,30 +1754,35 @@ namespace { class CFRefBug : public BugType { protected: - CFRefBug(StringRef name) - : BugType(name, "Memory (Core Foundation/Objective-C)") {} + CFRefCount& TF; + + CFRefBug(CFRefCount* tf, StringRef name) + : BugType(name, "Memory (Core Foundation/Objective-C)"), TF(*tf) {} public: + CFRefCount& getTF() { return TF; } + // FIXME: Eventually remove. - virtual const char *getDescription() const = 0; + virtual const char* getDescription() const = 0; virtual bool isLeak() const { return false; } }; class UseAfterRelease : public CFRefBug { public: - UseAfterRelease() : CFRefBug("Use-after-release") {} + UseAfterRelease(CFRefCount* tf) + : CFRefBug(tf, "Use-after-release") {} - const char *getDescription() const { + const char* getDescription() const { return "Reference-counted object is used after it is released"; } }; class BadRelease : public CFRefBug { public: - BadRelease() : CFRefBug("Bad release") {} + BadRelease(CFRefCount* tf) : CFRefBug(tf, "Bad release") {} - const char *getDescription() const { + const char* getDescription() const { return "Incorrect decrement of the reference count of an object that is " "not owned at this point by the caller"; } @@ -1783,8 +1790,8 @@ namespace { class DeallocGC : public CFRefBug { public: - DeallocGC() - : CFRefBug("-dealloc called while using garbage collection") {} + DeallocGC(CFRefCount *tf) + : CFRefBug(tf, "-dealloc called while using garbage collection") {} const char *getDescription() const { return "-dealloc called while using garbage collection"; @@ -1793,8 +1800,8 @@ namespace { class DeallocNotOwned : public CFRefBug { public: - DeallocNotOwned() - : CFRefBug("-dealloc sent to non-exclusively owned object") {} + DeallocNotOwned(CFRefCount *tf) + : CFRefBug(tf, "-dealloc sent to non-exclusively owned object") {} const char *getDescription() const { return "-dealloc sent to object that may be referenced elsewhere"; @@ -1803,8 +1810,8 @@ namespace { class OverAutorelease : public CFRefBug { public: - OverAutorelease() - : CFRefBug("Object sent -autorelease too many times") {} + OverAutorelease(CFRefCount *tf) : + CFRefBug(tf, "Object sent -autorelease too many times") {} const char *getDescription() const { return "Object sent -autorelease too many times"; @@ -1813,8 +1820,8 @@ namespace { class ReturnedNotOwnedForOwned : public CFRefBug { public: - ReturnedNotOwnedForOwned() - : CFRefBug("Method should return an owned object") {} + ReturnedNotOwnedForOwned(CFRefCount *tf) : + CFRefBug(tf, "Method should return an owned object") {} const char *getDescription() const { return "Object with a +0 retain count returned to caller where a +1 " @@ -1825,25 +1832,25 @@ namespace { class Leak : public CFRefBug { const bool isReturn; protected: - Leak(StringRef name, bool isRet) - : CFRefBug(name), isReturn(isRet) {} + Leak(CFRefCount* tf, StringRef name, bool isRet) + : CFRefBug(tf, name), isReturn(isRet) {} public: - const char *getDescription() const { return ""; } + const char* getDescription() const { return ""; } bool isLeak() const { return true; } }; class LeakAtReturn : public Leak { public: - LeakAtReturn(StringRef name) - : Leak(name, true) {} + LeakAtReturn(CFRefCount* tf, StringRef name) + : Leak(tf, name, true) {} }; class LeakWithinFunction : public Leak { public: - LeakWithinFunction(StringRef name) - : Leak(name, false) {} + LeakWithinFunction(CFRefCount* tf, StringRef name) + : Leak(tf, name, false) {} }; //===---------===// @@ -1853,12 +1860,13 @@ namespace { class CFRefReportVisitor : public BugReporterVisitor { protected: SymbolRef Sym; + const CFRefCount &TF; const SummaryLogTy &SummaryLog; - bool GCEnabled; public: - CFRefReportVisitor(SymbolRef sym, bool gcEnabled, const SummaryLogTy &log) - : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {} + CFRefReportVisitor(SymbolRef sym, const CFRefCount &tf, + const SummaryLogTy &log) + : Sym(sym), TF(tf), SummaryLog(log) {} virtual void Profile(llvm::FoldingSetNodeID &ID) const { static int x = 0; @@ -1878,9 +1886,9 @@ namespace { class CFRefLeakReportVisitor : public CFRefReportVisitor { public: - CFRefLeakReportVisitor(SymbolRef sym, bool GCEnabled, + CFRefLeakReportVisitor(SymbolRef sym, const CFRefCount &tf, const SummaryLogTy &log) - : CFRefReportVisitor(sym, GCEnabled, log) {} + : CFRefReportVisitor(sym, tf, log) {} PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, const ExplodedNode *N, @@ -1888,24 +1896,24 @@ namespace { }; class CFRefReport : public BugReport { - void addGCModeDescription(const CFRefCount &TF); - public: CFRefReport(CFRefBug &D, const CFRefCount &tf, const SummaryLogTy &log, ExplodedNode *n, SymbolRef sym, bool registerVisitor = true) : BugReport(D, D.getDescription(), n) { if (registerVisitor) - addVisitor(new CFRefReportVisitor(sym, tf.isGCEnabled(), log)); - addGCModeDescription(tf); + addVisitor(new CFRefReportVisitor(sym, tf, log)); + addExtraTextToCFReport(*this); } CFRefReport(CFRefBug &D, const CFRefCount &tf, const SummaryLogTy &log, ExplodedNode *n, SymbolRef sym, StringRef endText) : BugReport(D, D.getDescription(), endText, n) { - addVisitor(new CFRefReportVisitor(sym, tf.isGCEnabled(), log)); - addGCModeDescription(tf); + addVisitor(new CFRefReportVisitor(sym, tf, log)); + addExtraTextToCFReport(*this); } + virtual ~CFRefReport() {} + virtual std::pair<ranges_iterator, ranges_iterator> getRanges() { const CFRefBug& BugTy = static_cast<CFRefBug&>(getBugType()); if (!BugTy.isLeak()) @@ -1920,42 +1928,54 @@ namespace { const MemRegion* AllocBinding; public: - CFRefLeakReport(CFRefBug &D, const CFRefCount &tf, const SummaryLogTy &log, + CFRefLeakReport(CFRefBug& D, const CFRefCount &tf, const SummaryLogTy &log, ExplodedNode *n, SymbolRef sym, ExprEngine& Eng); SourceLocation getLocation() const { return AllocSite; } }; } // end anonymous namespace -void CFRefReport::addGCModeDescription(const CFRefCount &TF) { - const char *GCModeDescription; +static const char* Msgs[] = { + // GC only + "Code is compiled to only use garbage collection", + // No GC. + "Code is compiled to use reference counts", + // Hybrid, with GC. + "Code is compiled to use either garbage collection (GC) or reference counts" + " (non-GC). The bug occurs with GC enabled", + // Hybrid, without GC + "Code is compiled to use either garbage collection (GC) or reference counts" + " (non-GC). The bug occurs in non-GC mode" +}; + +// Add the metadata text. +static void addExtraTextToCFReport(BugReport &R) { + CFRefCount& TF = static_cast<CFRefBug&>(R.getBugType()).getTF(); switch (TF.getLangOptions().getGCMode()) { + default: + assert(false); + case LangOptions::GCOnly: - assert(TF.isGCEnabled()); - GCModeDescription = "Code is compiled to only use garbage collection"; - break; + assert (TF.isGCEnabled()); + R.addExtraText(Msgs[0]); + return; case LangOptions::NonGC: - assert(!TF.isGCEnabled()); - GCModeDescription = "Code is compiled to use reference counts"; - break; + assert (!TF.isGCEnabled()); + R.addExtraText(Msgs[1]); + return; case LangOptions::HybridGC: if (TF.isGCEnabled()) { - GCModeDescription = "Code is compiled to use either garbage collection " - "(GC) or reference counts (non-GC). The bug occurs " - "with GC enabled"; - break; - } else { - GCModeDescription = "Code is compiled to use either garbage collection " - "(GC) or reference counts (non-GC). The bug occurs " - "in non-GC mode"; - break; + R.addExtraText(Msgs[2]); + return; + } + else { + R.addExtraText(Msgs[3]); + return; } } - - addExtraText(GCModeDescription); } static inline bool contains(const SmallVectorImpl<ArgEffect>& V, @@ -2020,7 +2040,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, if (CurrV.isOwned()) { os << "+1 retain count"; - if (GCEnabled) { + if (TF.isGCEnabled()) { assert(CurrV.getObjKind() == RetEffect::CF); os << ". " "Core Foundation objects are not automatically garbage collected."; @@ -2076,7 +2096,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, RefVal PrevV = *PrevT; // Specially handle -dealloc. - if (!GCEnabled && contains(AEffects, Dealloc)) { + if (!TF.isGCEnabled() && contains(AEffects, Dealloc)) { // Determine if the object's reference count was pushed to zero. assert(!(PrevV == CurrV) && "The typestate *must* have changed."); // We may not have transitioned to 'release' if we hit an error. @@ -2095,7 +2115,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee()); const FunctionDecl *FD = X.getAsFunctionDecl(); - if (GCEnabled) { + if (TF.isGCEnabled()) { // Determine if the object's reference count was pushed to zero. assert(!(PrevV == CurrV) && "The typestate *must* have changed."); @@ -2146,7 +2166,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, os << " The object now has a +" << Count << " retain count."; if (PrevV.getKind() == RefVal::Released) { - assert(GCEnabled && CurrV.getCount() > 0); + assert(TF.isGCEnabled() && CurrV.getCount() > 0); os << " The object is not eligible for garbage collection until the " "retain count reaches 0 again."; } @@ -2175,7 +2195,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, E=AEffects.end(); I != E; ++I) { // A bunch of things have alternate behavior under GC. - if (GCEnabled) + if (TF.isGCEnabled()) switch (*I) { default: break; case Autorelease: @@ -2379,7 +2399,7 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC, return new PathDiagnosticEventPiece(L, os.str()); } -CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const CFRefCount &tf, +CFRefLeakReport::CFRefLeakReport(CFRefBug& D, const CFRefCount &tf, const SummaryLogTy &log, ExplodedNode *n, SymbolRef sym, ExprEngine& Eng) : CFRefReport(D, tf, log, n, sym, false) { @@ -2416,7 +2436,7 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const CFRefCount &tf, if (AllocBinding) os << " and stored into '" << AllocBinding->getString() << '\''; - addVisitor(new CFRefLeakReportVisitor(sym, tf.isGCEnabled(), log)); + addVisitor(new CFRefLeakReportVisitor(sym, tf, log)); } //===----------------------------------------------------------------------===// @@ -3703,26 +3723,26 @@ void RetainReleaseChecker::checkDeadSymbols(SymbolReaper &SymReaper, void CFRefCount::RegisterChecks(ExprEngine& Eng) { BugReporter &BR = Eng.getBugReporter(); - useAfterRelease = new UseAfterRelease(); + useAfterRelease = new UseAfterRelease(this); BR.Register(useAfterRelease); - releaseNotOwned = new BadRelease(); + releaseNotOwned = new BadRelease(this); BR.Register(releaseNotOwned); - deallocGC = new DeallocGC(); + deallocGC = new DeallocGC(this); BR.Register(deallocGC); - deallocNotOwned = new DeallocNotOwned(); + deallocNotOwned = new DeallocNotOwned(this); BR.Register(deallocNotOwned); - overAutorelease = new OverAutorelease(); + overAutorelease = new OverAutorelease(this); BR.Register(overAutorelease); - returnNotOwnedForOwned = new ReturnedNotOwnedForOwned(); + returnNotOwnedForOwned = new ReturnedNotOwnedForOwned(this); BR.Register(returnNotOwnedForOwned); // First register "return" leaks. - const char *name = 0; + const char* name = 0; if (isGCEnabled()) name = "Leak of returned object when using garbage collection"; @@ -3735,7 +3755,7 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) { } // Leaks should not be reported if they are post-dominated by a sink. - leakAtReturn = new LeakAtReturn(name); + leakAtReturn = new LeakAtReturn(this, name); leakAtReturn->setSuppressOnSink(true); BR.Register(leakAtReturn); @@ -3751,7 +3771,7 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) { } // Leaks should not be reported if they are post-dominated by sinks. - leakWithinFunction = new LeakWithinFunction(name); + leakWithinFunction = new LeakWithinFunction(this, name); leakWithinFunction->setSuppressOnSink(true); BR.Register(leakWithinFunction); |