SymbolRef sid, RefVal V,
SmallVectorImpl<SymbolRef> &Leaked) const;
- std::pair<ExplodedNode *, ProgramStateRef >
+ ProgramStateRef
handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
const ProgramPointTag *Tag, CheckerContext &Ctx,
SymbolRef Sym, RefVal V) const;
// Update the autorelease counts.
static SimpleProgramPointTag
AutoreleaseTag("RetainCountChecker : Autorelease");
- llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag,
- C, Sym, X);
+ state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
// Did we cache out?
- if (!Pred)
+ if (!state)
return;
// Get the updated binding.
// Handle dead symbols and end-of-path.
//===----------------------------------------------------------------------===//
-std::pair<ExplodedNode *, ProgramStateRef >
-RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
+ProgramStateRef
+RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
ExplodedNode *Pred,
const ProgramPointTag *Tag,
CheckerContext &Ctx,
// No autorelease counts? Nothing to be done.
if (!ACnt)
- return std::make_pair(Pred, state);
+ return state;
assert(!Ctx.isObjCGCEnabled() && "Autorelease counts in GC mode?");
unsigned Cnt = V.getCount();
V.setCount(Cnt - ACnt);
V.setAutoreleaseCount(0);
}
- state = setRefBinding(state, Sym, V);
- ExplodedNode *N = Ctx.addTransition(state, Pred, Tag);
- if (N == 0)
- state = 0;
- return std::make_pair(N, state);
+ return setRefBinding(state, Sym, V);
}
// Woah! More autorelease counts then retain counts left.
Ctx.emitReport(report);
}
- return std::make_pair((ExplodedNode *)0, (ProgramStateRef )0);
+ return 0;
}
ProgramStateRef
SmallVectorImpl<SymbolRef> &Leaked,
CheckerContext &Ctx,
ExplodedNode *Pred) const {
- if (Leaked.empty())
- return Pred;
-
// Generate an intermediate node representing the leak point.
ExplodedNode *N = Ctx.addTransition(state, Pred);
ExplodedNode *Pred = Ctx.getPredecessor();
for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, /*Tag=*/0,
- Ctx, I->first, I->second);
+ state = handleAutoreleaseCounts(state, Pred, /*Tag=*/0, Ctx,
+ I->first, I->second);
if (!state)
return;
}
ProgramStateRef state = C.getState();
RefBindingsTy B = state->get<RefBindings>();
+ SmallVector<SymbolRef, 10> Leaked;
// Update counts from autorelease pools
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
// Use the symbol as the tag.
// FIXME: This might not be as unique as we would like.
const ProgramPointTag *Tag = getDeadSymbolTag(Sym);
- llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, Tag, C,
- Sym, *T);
+ state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
if (!state)
return;
+
+ // Fetch the new reference count from the state, and use it to handle
+ // this symbol.
+ state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked);
}
}
- B = state->get<RefBindings>();
- SmallVector<SymbolRef, 10> Leaked;
-
- for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
- E = SymReaper.dead_end(); I != E; ++I) {
- if (const RefVal *T = B.lookup(*I))
- state = handleSymbolDeath(state, *I, *T, Leaked);
+ if (Leaked.empty()) {
+ C.addTransition(state);
+ return;
}
Pred = processLeaks(state, Leaked, C, Pred);
return;
// Now generate a new node that nukes the old bindings.
+ // The only bindings left at this point are the leaked symbols.
RefBindingsTy::Factory &F = state->get_context<RefBindings>();
+ B = state->get<RefBindings>();
- for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
- E = SymReaper.dead_end(); I != E; ++I)
+ for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
+ E = Leaked.end();
+ I != E; ++I)
B = F.remove(B, *I);
state = state->set<RefBindings>(B);
- (id)copyAutorelease {
id result = [[Foo alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
[result autorelease]; // expected-note{{Object sent -autorelease message}}
- return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+ return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
@end
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>