aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-02-18 18:54:33 +0000
committerTed Kremenek <kremenek@apple.com>2009-02-18 18:54:33 +0000
commit1c512f5fcb47526a09f15c26ba673a22fce91e33 (patch)
tree37f35ab24af97019434818431d4969e63e801ef4 /lib/Analysis/CFRefCount.cpp
parent2197c963543397777919cec22b65feb31a9ddf79 (diff)
retain/release checker: Distinguish in the function summaries between
retain/releases performed via [... release] and CFRetain(). The former are no-ops in GC. The checker already handled this, but now we emit nice diagnostics to the user telling them that these are no-ops. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64937 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp39
1 files changed, 27 insertions, 12 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 7bb6e7ce1c..58d8abf881 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -131,7 +131,9 @@ static bool isRefType(QualType RetTy, const char* prefix,
namespace {
/// ArgEffect is used to summarize a function/method call's effect on a
/// particular argument.
-enum ArgEffect { IncRef, DecRef, DoNothing, DoNothingByRef,
+enum ArgEffect { IncRefMsg, IncRef,
+ DecRefMsg, DecRef,
+ DoNothing, DoNothingByRef,
StopTracking, MayEscape, SelfOwn, Autorelease };
/// ArgEffects summarizes the effects of a function/method call on all of
@@ -1025,11 +1027,11 @@ void RetainSummaryManager::InitializeMethodSummaries() {
// Create the "retain" selector.
E = RetEffect::MakeReceiverAlias();
- Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
+ Summ = getPersistentSummary(E, IncRefMsg);
addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
// Create the "release" selector.
- Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
+ Summ = getPersistentSummary(E, DecRefMsg);
addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
// Create the "drain" selector.
@@ -1936,9 +1938,13 @@ RefBindings CFRefCount::Update(RefBindings B, SymbolRef sym,
RefVal V, ArgEffect E,
RefVal::Kind& hasErr,
RefBindings::Factory& RefBFactory) {
-
- // FIXME: This dispatch can potentially be sped up by unifiying it into
- // a single switch statement. Opt for simplicity for now.
+
+ // In GC mode [... release] and [... retain] do nothing.
+ switch (E) {
+ default: break;
+ case IncRefMsg: E = isGCEnabled() ? DoNothing : IncRef; break;
+ case DecRefMsg: E = isGCEnabled() ? DoNothing : DecRef; break;
+ }
switch (E) {
default:
@@ -1987,7 +1993,7 @@ RefBindings CFRefCount::Update(RefBindings B, SymbolRef sym,
case SelfOwn:
V = V ^ RefVal::NotOwned;
- // Fall-through.
+ // Fall-through.
case DecRef:
switch (V.getKind()) {
default:
@@ -2344,11 +2350,20 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
for (llvm::SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
E=AEffects.end(); I != E; ++I) {
- // Did we do an 'autorelease' in GC mode?
- if (TF.isGCEnabled() && *I == Autorelease) {
- os << "In GC mode an 'autorelease' has no effect.";
- continue;
- }
+ // A bunch of things have alternate behavior under GC.
+ if (TF.isGCEnabled())
+ switch (*I) {
+ default: break;
+ case Autorelease:
+ os << "In GC mode an 'autorelease' has no effect.";
+ continue;
+ case IncRefMsg:
+ os << "In GC mode the 'retain' message has no effect.";
+ continue;
+ case DecRefMsg:
+ os << "In GC mode the 'release' message has no effect.";
+ continue;
+ }
}
}