aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-05-08 20:01:42 +0000
committerTed Kremenek <kremenek@apple.com>2009-05-08 20:01:42 +0000
commitf21332e786564e83dc77451c05833f74e8f080c2 (patch)
tree40003b6ec7b4760d7f61cc09f9c1bbfd22a5cc9a /lib/Analysis/CFRefCount.cpp
parent4c2743f0afe601b0e8ea7bd9b3cd0fb09083a181 (diff)
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
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp52
1 files 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<GRState>* 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<GRState>* 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<RefBindings>(sym);