From f21332e786564e83dc77451c05833f74e8f080c2 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 8 May 2009 20:01:42 +0000 Subject: [PATCH] retain checker: Track the number of times a tracked object is sent 'autorelease'. This isn't used yet to flag errors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71244 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CFRefCount.cpp | 52 ++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 90b15a40b4..2d154759b2 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1361,21 +1361,24 @@ private: Kind kind; RetEffect::ObjKind okind; unsigned Cnt; + unsigned ACnt; QualType T; - RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, QualType t) - : kind(k), okind(o), Cnt(cnt), T(t) {} + RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t) + : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {} RefVal(Kind k, unsigned cnt = 0) - : kind(k), okind(RetEffect::AnyObj), Cnt(cnt) {} + : kind(k), okind(RetEffect::AnyObj), Cnt(cnt), ACnt(0) {} public: Kind getKind() const { return kind; } RetEffect::ObjKind getObjKind() const { return okind; } - unsigned getCount() const { return Cnt; } - void clearCounts() { Cnt = 0; } + unsigned getCount() const { return Cnt; } + unsigned getAutoreleaseCount() const { return ACnt; } + unsigned getCombinedCounts() const { return Cnt + ACnt; } + void clearCounts() { Cnt = 0; ACnt = 0; } QualType getType() const { return T; } @@ -1408,12 +1411,12 @@ public: static RefVal makeOwned(RetEffect::ObjKind o, QualType t, unsigned Count = 1) { - return RefVal(Owned, o, Count, t); + return RefVal(Owned, o, Count, 0, t); } static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t, unsigned Count = 0) { - return RefVal(NotOwned, o, Count, t); + return RefVal(NotOwned, o, Count, 0, t); } static RefVal makeReturnedOwned(unsigned Count) { @@ -1431,20 +1434,29 @@ public: } RefVal operator-(size_t i) const { - return RefVal(getKind(), getObjKind(), getCount() - i, getType()); + return RefVal(getKind(), getObjKind(), getCount() - i, + getAutoreleaseCount(), getType()); } RefVal operator+(size_t i) const { - return RefVal(getKind(), getObjKind(), getCount() + i, getType()); + return RefVal(getKind(), getObjKind(), getCount() + i, + getAutoreleaseCount(), getType()); } RefVal operator^(Kind k) const { - return RefVal(k, getObjKind(), getCount(), getType()); + return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(), + getType()); + } + + RefVal autorelease() const { + return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1, + getType()); } void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger((unsigned) kind); ID.AddInteger(Cnt); + ID.AddInteger(ACnt); ID.Add(T); } @@ -1513,6 +1525,10 @@ void RefVal::print(std::ostream& Out) const { Out << "Release of Not-Owned [ERROR]"; break; } + + if (ACnt) { + Out << " [ARC +" << ACnt << ']'; + } } } // end anonymous namespace @@ -2102,7 +2118,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N, // We may not have transitioned to 'release' if we hit an error. // This case is handled elsewhere. if (CurrV.getKind() == RefVal::Released) { - assert(CurrV.getCount() == 0); + assert(CurrV.getCombinedCounts() == 0); os << "Object released by directly sending the '-dealloc' message"; break; } @@ -2148,8 +2164,15 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N, case RefVal::Owned: case RefVal::NotOwned: - if (PrevV.getCount() == CurrV.getCount()) - return 0; + if (PrevV.getCount() == CurrV.getCount()) { + // Did an autorelease message get sent? + if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount()) + return 0; + + assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount()); + os << "Object added to autorelease pool."; + break; + } if (PrevV.getCount() > CurrV.getCount()) os << "Reference count decremented."; @@ -3040,8 +3063,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, // Update the autorelease counts. state = SendAutorelease(state, ARCountFactory, sym); - - // Fall-through. + V = V.autorelease(); case StopTracking: return state.remove(sym); -- 2.40.0