1 //==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines the methods for RetainCountChecker, which implements
11 //  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "RetainCountChecker.h"
16 
17 using namespace clang;
18 using namespace ento;
19 using namespace retaincountchecker;
20 using llvm::StrInStrNoCase;
21 
22 REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
23 
24 namespace clang {
25 namespace ento {
26 namespace retaincountchecker {
27 
28 const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym) {
29   return State->get<RefBindings>(Sym);
30 }
31 
32 ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
33                                      RefVal Val) {
34   assert(Sym != nullptr);
35   return State->set<RefBindings>(Sym, Val);
36 }
37 
38 ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
39   return State->remove<RefBindings>(Sym);
40 }
41 
42 } // end namespace retaincountchecker
43 } // end namespace ento
44 } // end namespace clang
45 
46 void RefVal::print(raw_ostream &Out) const {
47   if (!T.isNull())
48     Out << "Tracked " << T.getAsString() << " | ";
49 
50   switch (getKind()) {
51     default: llvm_unreachable("Invalid RefVal kind");
52     case Owned: {
53       Out << "Owned";
54       unsigned cnt = getCount();
55       if (cnt) Out << " (+ " << cnt << ")";
56       break;
57     }
58 
59     case NotOwned: {
60       Out << "NotOwned";
61       unsigned cnt = getCount();
62       if (cnt) Out << " (+ " << cnt << ")";
63       break;
64     }
65 
66     case ReturnedOwned: {
67       Out << "ReturnedOwned";
68       unsigned cnt = getCount();
69       if (cnt) Out << " (+ " << cnt << ")";
70       break;
71     }
72 
73     case ReturnedNotOwned: {
74       Out << "ReturnedNotOwned";
75       unsigned cnt = getCount();
76       if (cnt) Out << " (+ " << cnt << ")";
77       break;
78     }
79 
80     case Released:
81       Out << "Released";
82       break;
83 
84     case ErrorDeallocNotOwned:
85       Out << "-dealloc (not-owned)";
86       break;
87 
88     case ErrorLeak:
89       Out << "Leaked";
90       break;
91 
92     case ErrorLeakReturned:
93       Out << "Leaked (Bad naming)";
94       break;
95 
96     case ErrorUseAfterRelease:
97       Out << "Use-After-Release [ERROR]";
98       break;
99 
100     case ErrorReleaseNotOwned:
101       Out << "Release of Not-Owned [ERROR]";
102       break;
103 
104     case RefVal::ErrorOverAutorelease:
105       Out << "Over-autoreleased";
106       break;
107 
108     case RefVal::ErrorReturnedNotOwned:
109       Out << "Non-owned object returned instead of owned";
110       break;
111   }
112 
113   switch (getIvarAccessHistory()) {
114   case IvarAccessHistory::None:
115     break;
116   case IvarAccessHistory::AccessedDirectly:
117     Out << " [direct ivar access]";
118     break;
119   case IvarAccessHistory::ReleasedAfterDirectAccess:
120     Out << " [released after direct ivar access]";
121   }
122 
123   if (ACnt) {
124     Out << " [autorelease -" << ACnt << ']';
125   }
126 }
127 
128 namespace {
129 class StopTrackingCallback final : public SymbolVisitor {
130   ProgramStateRef state;
131 public:
132   StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
133   ProgramStateRef getState() const { return state; }
134 
135   bool VisitSymbol(SymbolRef sym) override {
136     state = state->remove<RefBindings>(sym);
137     return true;
138   }
139 };
140 } // end anonymous namespace
141 
142 //===----------------------------------------------------------------------===//
143 // Handle statements that may have an effect on refcounts.
144 //===----------------------------------------------------------------------===//
145 
146 void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
147                                        CheckerContext &C) const {
148 
149   // Scan the BlockDecRefExprs for any object the retain count checker
150   // may be tracking.
151   if (!BE->getBlockDecl()->hasCaptures())
152     return;
153 
154   ProgramStateRef state = C.getState();
155   auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
156 
157   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
158                                             E = R->referenced_vars_end();
159 
160   if (I == E)
161     return;
162 
163   // FIXME: For now we invalidate the tracking of all symbols passed to blocks
164   // via captured variables, even though captured variables result in a copy
165   // and in implicit increment/decrement of a retain count.
166   SmallVector<const MemRegion*, 10> Regions;
167   const LocationContext *LC = C.getLocationContext();
168   MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
169 
170   for ( ; I != E; ++I) {
171     const VarRegion *VR = I.getCapturedRegion();
172     if (VR->getSuperRegion() == R) {
173       VR = MemMgr.getVarRegion(VR->getDecl(), LC);
174     }
175     Regions.push_back(VR);
176   }
177 
178   state = state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
179   C.addTransition(state);
180 }
181 
182 void RetainCountChecker::checkPostStmt(const CastExpr *CE,
183                                        CheckerContext &C) const {
184   const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
185   if (!BE)
186     return;
187 
188   ArgEffect AE = IncRef;
189 
190   switch (BE->getBridgeKind()) {
191     case OBC_Bridge:
192       // Do nothing.
193       return;
194     case OBC_BridgeRetained:
195       AE = IncRef;
196       break;
197     case OBC_BridgeTransfer:
198       AE = DecRefBridgedTransferred;
199       break;
200   }
201 
202   ProgramStateRef state = C.getState();
203   SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
204   if (!Sym)
205     return;
206   const RefVal* T = getRefBinding(state, Sym);
207   if (!T)
208     return;
209 
210   RefVal::Kind hasErr = (RefVal::Kind) 0;
211   state = updateSymbol(state, Sym, *T, AE, hasErr, C);
212 
213   if (hasErr) {
214     // FIXME: If we get an error during a bridge cast, should we report it?
215     return;
216   }
217 
218   C.addTransition(state);
219 }
220 
221 void RetainCountChecker::processObjCLiterals(CheckerContext &C,
222                                              const Expr *Ex) const {
223   ProgramStateRef state = C.getState();
224   const ExplodedNode *pred = C.getPredecessor();
225   for (const Stmt *Child : Ex->children()) {
226     SVal V = pred->getSVal(Child);
227     if (SymbolRef sym = V.getAsSymbol())
228       if (const RefVal* T = getRefBinding(state, sym)) {
229         RefVal::Kind hasErr = (RefVal::Kind) 0;
230         state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
231         if (hasErr) {
232           processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
233           return;
234         }
235       }
236   }
237 
238   // Return the object as autoreleased.
239   //  RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
240   if (SymbolRef sym =
241         state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
242     QualType ResultTy = Ex->getType();
243     state = setRefBinding(state, sym,
244                           RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
245   }
246 
247   C.addTransition(state);
248 }
249 
250 void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
251                                        CheckerContext &C) const {
252   // Apply the 'MayEscape' to all values.
253   processObjCLiterals(C, AL);
254 }
255 
256 void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
257                                        CheckerContext &C) const {
258   // Apply the 'MayEscape' to all keys and values.
259   processObjCLiterals(C, DL);
260 }
261 
262 void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
263                                        CheckerContext &C) const {
264   const ExplodedNode *Pred = C.getPredecessor();
265   ProgramStateRef State = Pred->getState();
266 
267   if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) {
268     QualType ResultTy = Ex->getType();
269     State = setRefBinding(State, Sym,
270                           RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
271   }
272 
273   C.addTransition(State);
274 }
275 
276 void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
277                                        CheckerContext &C) const {
278   Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
279   if (!IVarLoc)
280     return;
281 
282   ProgramStateRef State = C.getState();
283   SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
284   if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion()))
285     return;
286 
287   // Accessing an ivar directly is unusual. If we've done that, be more
288   // forgiving about what the surrounding code is allowed to do.
289 
290   QualType Ty = Sym->getType();
291   RetEffect::ObjKind Kind;
292   if (Ty->isObjCRetainableType())
293     Kind = RetEffect::ObjC;
294   else if (coreFoundation::isCFObjectRef(Ty))
295     Kind = RetEffect::CF;
296   else
297     return;
298 
299   // If the value is already known to be nil, don't bother tracking it.
300   ConstraintManager &CMgr = State->getConstraintManager();
301   if (CMgr.isNull(State, Sym).isConstrainedTrue())
302     return;
303 
304   if (const RefVal *RV = getRefBinding(State, Sym)) {
305     // If we've seen this symbol before, or we're only seeing it now because
306     // of something the analyzer has synthesized, don't do anything.
307     if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
308         isSynthesizedAccessor(C.getStackFrame())) {
309       return;
310     }
311 
312     // Note that this value has been loaded from an ivar.
313     C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
314     return;
315   }
316 
317   RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
318 
319   // In a synthesized accessor, the effective retain count is +0.
320   if (isSynthesizedAccessor(C.getStackFrame())) {
321     C.addTransition(setRefBinding(State, Sym, PlusZero));
322     return;
323   }
324 
325   State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
326   C.addTransition(State);
327 }
328 
329 void RetainCountChecker::checkPostCall(const CallEvent &Call,
330                                        CheckerContext &C) const {
331   RetainSummaryManager &Summaries = getSummaryManager(C);
332 
333   // Leave null if no receiver.
334   QualType ReceiverType;
335   if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
336     if (MC->isInstanceMessage()) {
337       SVal ReceiverV = MC->getReceiverSVal();
338       if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
339         if (const RefVal *T = getRefBinding(C.getState(), Sym))
340           ReceiverType = T->getType();
341     }
342   }
343 
344   const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
345 
346   if (C.wasInlined) {
347     processSummaryOfInlined(*Summ, Call, C);
348     return;
349   }
350   checkSummary(*Summ, Call, C);
351 }
352 
353 /// GetReturnType - Used to get the return type of a message expression or
354 ///  function call with the intention of affixing that type to a tracked symbol.
355 ///  While the return type can be queried directly from RetEx, when
356 ///  invoking class methods we augment to the return type to be that of
357 ///  a pointer to the class (as opposed it just being id).
358 // FIXME: We may be able to do this with related result types instead.
359 // This function is probably overestimating.
360 static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
361   QualType RetTy = RetE->getType();
362   // If RetE is not a message expression just return its type.
363   // If RetE is a message expression, return its types if it is something
364   /// more specific than id.
365   if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
366     if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
367       if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
368           PT->isObjCClassType()) {
369         // At this point we know the return type of the message expression is
370         // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
371         // is a call to a class method whose type we can resolve.  In such
372         // cases, promote the return type to XXX* (where XXX is the class).
373         const ObjCInterfaceDecl *D = ME->getReceiverInterface();
374         return !D ? RetTy :
375                     Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
376       }
377 
378   return RetTy;
379 }
380 
381 static Optional<RefVal> refValFromRetEffect(RetEffect RE,
382                                             QualType ResultTy) {
383   if (RE.isOwned()) {
384     return RefVal::makeOwned(RE.getObjKind(), ResultTy);
385   } else if (RE.notOwned()) {
386     return RefVal::makeNotOwned(RE.getObjKind(), ResultTy);
387   }
388 
389   return None;
390 }
391 
392 // We don't always get the exact modeling of the function with regards to the
393 // retain count checker even when the function is inlined. For example, we need
394 // to stop tracking the symbols which were marked with StopTrackingHard.
395 void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
396                                                  const CallEvent &CallOrMsg,
397                                                  CheckerContext &C) const {
398   ProgramStateRef state = C.getState();
399 
400   // Evaluate the effect of the arguments.
401   for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
402     if (Summ.getArg(idx) == StopTrackingHard) {
403       SVal V = CallOrMsg.getArgSVal(idx);
404       if (SymbolRef Sym = V.getAsLocSymbol()) {
405         state = removeRefBinding(state, Sym);
406       }
407     }
408   }
409 
410   // Evaluate the effect on the message receiver.
411   if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
412     if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
413       if (Summ.getReceiverEffect() == StopTrackingHard) {
414         state = removeRefBinding(state, Sym);
415       }
416     }
417   }
418 
419   // Consult the summary for the return value.
420   RetEffect RE = Summ.getRetEffect();
421 
422   if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
423     if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
424       if (Optional<RefVal> updatedRefVal =
425               refValFromRetEffect(RE, MCall->getResultType())) {
426         state = setRefBinding(state, Sym, *updatedRefVal);
427       }
428     }
429 
430     if (RE.getKind() == RetEffect::NoRetHard)
431       state = removeRefBinding(state, Sym);
432   }
433 
434   C.addTransition(state);
435 }
436 
437 static ProgramStateRef updateOutParameter(ProgramStateRef State,
438                                           SVal ArgVal,
439                                           ArgEffect Effect) {
440   auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
441   if (!ArgRegion)
442     return State;
443 
444   QualType PointeeTy = ArgRegion->getValueType();
445   if (!coreFoundation::isCFObjectRef(PointeeTy))
446     return State;
447 
448   SVal PointeeVal = State->getSVal(ArgRegion);
449   SymbolRef Pointee = PointeeVal.getAsLocSymbol();
450   if (!Pointee)
451     return State;
452 
453   switch (Effect) {
454   case UnretainedOutParameter:
455     State = setRefBinding(State, Pointee,
456                           RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
457     break;
458   case RetainedOutParameter:
459     // Do nothing. Retained out parameters will either point to a +1 reference
460     // or NULL, but the way you check for failure differs depending on the API.
461     // Consequently, we don't have a good way to track them yet.
462     break;
463 
464   default:
465     llvm_unreachable("only for out parameters");
466   }
467 
468   return State;
469 }
470 
471 void RetainCountChecker::checkSummary(const RetainSummary &Summ,
472                                       const CallEvent &CallOrMsg,
473                                       CheckerContext &C) const {
474   ProgramStateRef state = C.getState();
475 
476   // Evaluate the effect of the arguments.
477   RefVal::Kind hasErr = (RefVal::Kind) 0;
478   SourceRange ErrorRange;
479   SymbolRef ErrorSym = nullptr;
480 
481   for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
482     SVal V = CallOrMsg.getArgSVal(idx);
483 
484     ArgEffect Effect = Summ.getArg(idx);
485     if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
486       state = updateOutParameter(state, V, Effect);
487     } else if (SymbolRef Sym = V.getAsLocSymbol()) {
488       if (const RefVal *T = getRefBinding(state, Sym)) {
489         state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
490         if (hasErr) {
491           ErrorRange = CallOrMsg.getArgSourceRange(idx);
492           ErrorSym = Sym;
493           break;
494         }
495       }
496     }
497   }
498 
499   // Evaluate the effect on the message receiver / `this` argument.
500   bool ReceiverIsTracked = false;
501   if (!hasErr) {
502     if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
503       if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
504         if (const RefVal *T = getRefBinding(state, Sym)) {
505           ReceiverIsTracked = true;
506           state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
507                                  hasErr, C);
508           if (hasErr) {
509             ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
510             ErrorSym = Sym;
511           }
512         }
513       }
514     } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
515       if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
516         if (const RefVal *T = getRefBinding(state, Sym)) {
517           state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
518                                hasErr, C);
519           if (hasErr) {
520             ErrorRange = MCall->getOriginExpr()->getSourceRange();
521             ErrorSym = Sym;
522           }
523         }
524       }
525     }
526   }
527 
528   // Process any errors.
529   if (hasErr) {
530     processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
531     return;
532   }
533 
534   // Consult the summary for the return value.
535   RetEffect RE = Summ.getRetEffect();
536 
537   if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
538     if (ReceiverIsTracked)
539       RE = getSummaryManager(C).getObjAllocRetEffect();
540     else
541       RE = RetEffect::MakeNoRet();
542   }
543 
544   if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
545     QualType ResultTy = CallOrMsg.getResultType();
546     if (RE.notOwned()) {
547       const Expr *Ex = CallOrMsg.getOriginExpr();
548       assert(Ex);
549       ResultTy = GetReturnType(Ex, C.getASTContext());
550     }
551     if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
552       state = setRefBinding(state, Sym, *updatedRefVal);
553   }
554 
555   // This check is actually necessary; otherwise the statement builder thinks
556   // we've hit a previously-found path.
557   // Normally addTransition takes care of this, but we want the node pointer.
558   ExplodedNode *NewNode;
559   if (state == C.getState()) {
560     NewNode = C.getPredecessor();
561   } else {
562     NewNode = C.addTransition(state);
563   }
564 
565   // Annotate the node with summary we used.
566   if (NewNode) {
567     // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
568     if (ShouldResetSummaryLog) {
569       SummaryLog.clear();
570       ShouldResetSummaryLog = false;
571     }
572     SummaryLog[NewNode] = &Summ;
573   }
574 }
575 
576 ProgramStateRef
577 RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
578                                  RefVal V, ArgEffect E, RefVal::Kind &hasErr,
579                                  CheckerContext &C) const {
580   bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
581   switch (E) {
582   default:
583     break;
584   case IncRefMsg:
585     E = IgnoreRetainMsg ? DoNothing : IncRef;
586     break;
587   case DecRefMsg:
588     E = IgnoreRetainMsg ? DoNothing: DecRef;
589     break;
590   case DecRefMsgAndStopTrackingHard:
591     E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
592     break;
593   case MakeCollectable:
594     E = DoNothing;
595   }
596 
597   // Handle all use-after-releases.
598   if (V.getKind() == RefVal::Released) {
599     V = V ^ RefVal::ErrorUseAfterRelease;
600     hasErr = V.getKind();
601     return setRefBinding(state, sym, V);
602   }
603 
604   switch (E) {
605     case DecRefMsg:
606     case IncRefMsg:
607     case MakeCollectable:
608     case DecRefMsgAndStopTrackingHard:
609       llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
610 
611     case UnretainedOutParameter:
612     case RetainedOutParameter:
613       llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
614                        "not have ref state.");
615 
616     case Dealloc:
617       switch (V.getKind()) {
618         default:
619           llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
620         case RefVal::Owned:
621           // The object immediately transitions to the released state.
622           V = V ^ RefVal::Released;
623           V.clearCounts();
624           return setRefBinding(state, sym, V);
625         case RefVal::NotOwned:
626           V = V ^ RefVal::ErrorDeallocNotOwned;
627           hasErr = V.getKind();
628           break;
629       }
630       break;
631 
632     case MayEscape:
633       if (V.getKind() == RefVal::Owned) {
634         V = V ^ RefVal::NotOwned;
635         break;
636       }
637 
638       // Fall-through.
639 
640     case DoNothing:
641       return state;
642 
643     case Autorelease:
644       // Update the autorelease counts.
645       V = V.autorelease();
646       break;
647 
648     case StopTracking:
649     case StopTrackingHard:
650       return removeRefBinding(state, sym);
651 
652     case IncRef:
653       switch (V.getKind()) {
654         default:
655           llvm_unreachable("Invalid RefVal state for a retain.");
656         case RefVal::Owned:
657         case RefVal::NotOwned:
658           V = V + 1;
659           break;
660       }
661       break;
662 
663     case DecRef:
664     case DecRefBridgedTransferred:
665     case DecRefAndStopTrackingHard:
666       switch (V.getKind()) {
667         default:
668           // case 'RefVal::Released' handled above.
669           llvm_unreachable("Invalid RefVal state for a release.");
670 
671         case RefVal::Owned:
672           assert(V.getCount() > 0);
673           if (V.getCount() == 1) {
674             if (E == DecRefBridgedTransferred ||
675                 V.getIvarAccessHistory() ==
676                   RefVal::IvarAccessHistory::AccessedDirectly)
677               V = V ^ RefVal::NotOwned;
678             else
679               V = V ^ RefVal::Released;
680           } else if (E == DecRefAndStopTrackingHard) {
681             return removeRefBinding(state, sym);
682           }
683 
684           V = V - 1;
685           break;
686 
687         case RefVal::NotOwned:
688           if (V.getCount() > 0) {
689             if (E == DecRefAndStopTrackingHard)
690               return removeRefBinding(state, sym);
691             V = V - 1;
692           } else if (V.getIvarAccessHistory() ==
693                        RefVal::IvarAccessHistory::AccessedDirectly) {
694             // Assume that the instance variable was holding on the object at
695             // +1, and we just didn't know.
696             if (E == DecRefAndStopTrackingHard)
697               return removeRefBinding(state, sym);
698             V = V.releaseViaIvar() ^ RefVal::Released;
699           } else {
700             V = V ^ RefVal::ErrorReleaseNotOwned;
701             hasErr = V.getKind();
702           }
703           break;
704       }
705       break;
706   }
707   return setRefBinding(state, sym, V);
708 }
709 
710 void RetainCountChecker::processNonLeakError(ProgramStateRef St,
711                                              SourceRange ErrorRange,
712                                              RefVal::Kind ErrorKind,
713                                              SymbolRef Sym,
714                                              CheckerContext &C) const {
715   // HACK: Ignore retain-count issues on values accessed through ivars,
716   // because of cases like this:
717   //   [_contentView retain];
718   //   [_contentView removeFromSuperview];
719   //   [self addSubview:_contentView]; // invalidates 'self'
720   //   [_contentView release];
721   if (const RefVal *RV = getRefBinding(St, Sym))
722     if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
723       return;
724 
725   ExplodedNode *N = C.generateErrorNode(St);
726   if (!N)
727     return;
728 
729   CFRefBug *BT;
730   switch (ErrorKind) {
731     default:
732       llvm_unreachable("Unhandled error.");
733     case RefVal::ErrorUseAfterRelease:
734       if (!useAfterRelease)
735         useAfterRelease.reset(new UseAfterRelease(this));
736       BT = useAfterRelease.get();
737       break;
738     case RefVal::ErrorReleaseNotOwned:
739       if (!releaseNotOwned)
740         releaseNotOwned.reset(new BadRelease(this));
741       BT = releaseNotOwned.get();
742       break;
743     case RefVal::ErrorDeallocNotOwned:
744       if (!deallocNotOwned)
745         deallocNotOwned.reset(new DeallocNotOwned(this));
746       BT = deallocNotOwned.get();
747       break;
748   }
749 
750   assert(BT);
751   auto report = llvm::make_unique<CFRefReport>(
752       *BT, C.getASTContext().getLangOpts(), SummaryLog, N, Sym);
753   report->addRange(ErrorRange);
754   C.emitReport(std::move(report));
755 }
756 
757 //===----------------------------------------------------------------------===//
758 // Handle the return values of retain-count-related functions.
759 //===----------------------------------------------------------------------===//
760 
761 bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
762   // Get the callee. We're only interested in simple C functions.
763   ProgramStateRef state = C.getState();
764   const FunctionDecl *FD = C.getCalleeDecl(CE);
765   if (!FD)
766     return false;
767 
768   RetainSummaryManager &SmrMgr = getSummaryManager(C);
769   QualType ResultTy = CE->getCallReturnType(C.getASTContext());
770 
771   // See if the function has 'rc_ownership_trusted_implementation'
772   // annotate attribute. If it does, we will not inline it.
773   bool hasTrustedImplementationAnnotation = false;
774 
775   const LocationContext *LCtx = C.getLocationContext();
776 
777   // See if it's one of the specific functions we know how to eval.
778   if (!SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation))
779     return false;
780 
781   // Bind the return value.
782   // For now, all the functions which we can evaluate and which take
783   // at least one argument are identities.
784   if (CE->getNumArgs() >= 1) {
785     SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
786 
787     // If the receiver is unknown or the function has
788     // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
789     // return value.
790     if (RetVal.isUnknown() ||
791         (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
792       SValBuilder &SVB = C.getSValBuilder();
793       RetVal =
794           SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
795     }
796     state = state->BindExpr(CE, LCtx, RetVal, false);
797   }
798 
799   C.addTransition(state);
800   return true;
801 }
802 
803 ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
804                                                  CheckerContext &C) const {
805   ExplodedNode *Pred = C.getPredecessor();
806 
807   // Only adjust the reference count if this is the top-level call frame,
808   // and not the result of inlining.  In the future, we should do
809   // better checking even for inlined calls, and see if they match
810   // with their expected semantics (e.g., the method should return a retained
811   // object, etc.).
812   if (!C.inTopFrame())
813     return Pred;
814 
815   if (!S)
816     return Pred;
817 
818   const Expr *RetE = S->getRetValue();
819   if (!RetE)
820     return Pred;
821 
822   ProgramStateRef state = C.getState();
823   SymbolRef Sym =
824     state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
825   if (!Sym)
826     return Pred;
827 
828   // Get the reference count binding (if any).
829   const RefVal *T = getRefBinding(state, Sym);
830   if (!T)
831     return Pred;
832 
833   // Change the reference count.
834   RefVal X = *T;
835 
836   switch (X.getKind()) {
837     case RefVal::Owned: {
838       unsigned cnt = X.getCount();
839       assert(cnt > 0);
840       X.setCount(cnt - 1);
841       X = X ^ RefVal::ReturnedOwned;
842       break;
843     }
844 
845     case RefVal::NotOwned: {
846       unsigned cnt = X.getCount();
847       if (cnt) {
848         X.setCount(cnt - 1);
849         X = X ^ RefVal::ReturnedOwned;
850       } else {
851         X = X ^ RefVal::ReturnedNotOwned;
852       }
853       break;
854     }
855 
856     default:
857       return Pred;
858   }
859 
860   // Update the binding.
861   state = setRefBinding(state, Sym, X);
862   Pred = C.addTransition(state);
863 
864   // At this point we have updated the state properly.
865   // Everything after this is merely checking to see if the return value has
866   // been over- or under-retained.
867 
868   // Did we cache out?
869   if (!Pred)
870     return nullptr;
871 
872   // Update the autorelease counts.
873   static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
874   state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
875 
876   // Have we generated a sink node?
877   if (!state)
878     return nullptr;
879 
880   // Get the updated binding.
881   T = getRefBinding(state, Sym);
882   assert(T);
883   X = *T;
884 
885   // Consult the summary of the enclosing method.
886   RetainSummaryManager &Summaries = getSummaryManager(C);
887   const Decl *CD = &Pred->getCodeDecl();
888   RetEffect RE = RetEffect::MakeNoRet();
889 
890   // FIXME: What is the convention for blocks? Is there one?
891   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
892     const RetainSummary *Summ = Summaries.getMethodSummary(MD);
893     RE = Summ->getRetEffect();
894   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
895     if (!isa<CXXMethodDecl>(FD)) {
896       const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
897       RE = Summ->getRetEffect();
898     }
899   }
900 
901   return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
902 }
903 
904 ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
905                                                   CheckerContext &C,
906                                                   ExplodedNode *Pred,
907                                                   RetEffect RE, RefVal X,
908                                                   SymbolRef Sym,
909                                                   ProgramStateRef state) const {
910   // HACK: Ignore retain-count issues on values accessed through ivars,
911   // because of cases like this:
912   //   [_contentView retain];
913   //   [_contentView removeFromSuperview];
914   //   [self addSubview:_contentView]; // invalidates 'self'
915   //   [_contentView release];
916   if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
917     return Pred;
918 
919   // Any leaks or other errors?
920   if (X.isReturnedOwned() && X.getCount() == 0) {
921     if (RE.getKind() != RetEffect::NoRet) {
922       if (!RE.isOwned()) {
923 
924         // The returning type is a CF, we expect the enclosing method should
925         // return ownership.
926         X = X ^ RefVal::ErrorLeakReturned;
927 
928         // Generate an error node.
929         state = setRefBinding(state, Sym, X);
930 
931         static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
932         ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
933         if (N) {
934           const LangOptions &LOpts = C.getASTContext().getLangOpts();
935           auto R = llvm::make_unique<CFRefLeakReport>(
936               *getLeakAtReturnBug(LOpts), LOpts, SummaryLog, N, Sym, C,
937               IncludeAllocationLine);
938           C.emitReport(std::move(R));
939         }
940         return N;
941       }
942     }
943   } else if (X.isReturnedNotOwned()) {
944     if (RE.isOwned()) {
945       if (X.getIvarAccessHistory() ==
946             RefVal::IvarAccessHistory::AccessedDirectly) {
947         // Assume the method was trying to transfer a +1 reference from a
948         // strong ivar to the caller.
949         state = setRefBinding(state, Sym,
950                               X.releaseViaIvar() ^ RefVal::ReturnedOwned);
951       } else {
952         // Trying to return a not owned object to a caller expecting an
953         // owned object.
954         state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
955 
956         static CheckerProgramPointTag
957             ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
958 
959         ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
960         if (N) {
961           if (!returnNotOwnedForOwned)
962             returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
963 
964           auto R = llvm::make_unique<CFRefReport>(
965               *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
966               SummaryLog, N, Sym);
967           C.emitReport(std::move(R));
968         }
969         return N;
970       }
971     }
972   }
973   return Pred;
974 }
975 
976 //===----------------------------------------------------------------------===//
977 // Check various ways a symbol can be invalidated.
978 //===----------------------------------------------------------------------===//
979 
980 void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
981                                    CheckerContext &C) const {
982   // Are we storing to something that causes the value to "escape"?
983   bool escapes = true;
984 
985   // A value escapes in three possible cases (this may change):
986   //
987   // (1) we are binding to something that is not a memory region.
988   // (2) we are binding to a memregion that does not have stack storage
989   // (3) we are binding to a memregion with stack storage that the store
990   //     does not understand.
991   ProgramStateRef state = C.getState();
992 
993   if (auto regionLoc = loc.getAs<loc::MemRegionVal>()) {
994     escapes = !regionLoc->getRegion()->hasStackStorage();
995 
996     if (!escapes) {
997       // To test (3), generate a new state with the binding added.  If it is
998       // the same state, then it escapes (since the store cannot represent
999       // the binding).
1000       // Do this only if we know that the store is not supposed to generate the
1001       // same state.
1002       SVal StoredVal = state->getSVal(regionLoc->getRegion());
1003       if (StoredVal != val)
1004         escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext())));
1005     }
1006     if (!escapes) {
1007       // Case 4: We do not currently model what happens when a symbol is
1008       // assigned to a struct field, so be conservative here and let the symbol
1009       // go. TODO: This could definitely be improved upon.
1010       escapes = !isa<VarRegion>(regionLoc->getRegion());
1011     }
1012   }
1013 
1014   // If we are storing the value into an auto function scope variable annotated
1015   // with (__attribute__((cleanup))), stop tracking the value to avoid leak
1016   // false positives.
1017   if (const auto *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
1018     const VarDecl *VD = LVR->getDecl();
1019     if (VD->hasAttr<CleanupAttr>()) {
1020       escapes = true;
1021     }
1022   }
1023 
1024   // If our store can represent the binding and we aren't storing to something
1025   // that doesn't have local storage then just return and have the simulation
1026   // state continue as is.
1027   if (!escapes)
1028       return;
1029 
1030   // Otherwise, find all symbols referenced by 'val' that we are tracking
1031   // and stop tracking them.
1032   state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1033   C.addTransition(state);
1034 }
1035 
1036 ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
1037                                                SVal Cond,
1038                                                bool Assumption) const {
1039   // FIXME: We may add to the interface of evalAssume the list of symbols
1040   //  whose assumptions have changed.  For now we just iterate through the
1041   //  bindings and check if any of the tracked symbols are NULL.  This isn't
1042   //  too bad since the number of symbols we will track in practice are
1043   //  probably small and evalAssume is only called at branches and a few
1044   //  other places.
1045   RefBindingsTy B = state->get<RefBindings>();
1046 
1047   if (B.isEmpty())
1048     return state;
1049 
1050   bool changed = false;
1051   RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1052 
1053   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1054     // Check if the symbol is null stop tracking the symbol.
1055     ConstraintManager &CMgr = state->getConstraintManager();
1056     ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1057     if (AllocFailed.isConstrainedTrue()) {
1058       changed = true;
1059       B = RefBFactory.remove(B, I.getKey());
1060     }
1061   }
1062 
1063   if (changed)
1064     state = state->set<RefBindings>(B);
1065 
1066   return state;
1067 }
1068 
1069 ProgramStateRef
1070 RetainCountChecker::checkRegionChanges(ProgramStateRef state,
1071                                        const InvalidatedSymbols *invalidated,
1072                                        ArrayRef<const MemRegion *> ExplicitRegions,
1073                                        ArrayRef<const MemRegion *> Regions,
1074                                        const LocationContext *LCtx,
1075                                        const CallEvent *Call) const {
1076   if (!invalidated)
1077     return state;
1078 
1079   llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
1080   for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
1081        E = ExplicitRegions.end(); I != E; ++I) {
1082     if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
1083       WhitelistedSymbols.insert(SR->getSymbol());
1084   }
1085 
1086   for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
1087        E = invalidated->end(); I!=E; ++I) {
1088     SymbolRef sym = *I;
1089     if (WhitelistedSymbols.count(sym))
1090       continue;
1091     // Remove any existing reference-count binding.
1092     state = removeRefBinding(state, sym);
1093   }
1094   return state;
1095 }
1096 
1097 ProgramStateRef
1098 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
1099                                             ExplodedNode *Pred,
1100                                             const ProgramPointTag *Tag,
1101                                             CheckerContext &Ctx,
1102                                             SymbolRef Sym,
1103                                             RefVal V,
1104                                             const ReturnStmt *S) const {
1105   unsigned ACnt = V.getAutoreleaseCount();
1106 
1107   // No autorelease counts?  Nothing to be done.
1108   if (!ACnt)
1109     return state;
1110 
1111   unsigned Cnt = V.getCount();
1112 
1113   // FIXME: Handle sending 'autorelease' to already released object.
1114 
1115   if (V.getKind() == RefVal::ReturnedOwned)
1116     ++Cnt;
1117 
1118   // If we would over-release here, but we know the value came from an ivar,
1119   // assume it was a strong ivar that's just been relinquished.
1120   if (ACnt > Cnt &&
1121       V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
1122     V = V.releaseViaIvar();
1123     --ACnt;
1124   }
1125 
1126   if (ACnt <= Cnt) {
1127     if (ACnt == Cnt) {
1128       V.clearCounts();
1129       if (V.getKind() == RefVal::ReturnedOwned) {
1130         V = V ^ RefVal::ReturnedNotOwned;
1131       } else {
1132         V = V ^ RefVal::NotOwned;
1133       }
1134     } else {
1135       V.setCount(V.getCount() - ACnt);
1136       V.setAutoreleaseCount(0);
1137     }
1138     return setRefBinding(state, Sym, V);
1139   }
1140 
1141   // HACK: Ignore retain-count issues on values accessed through ivars,
1142   // because of cases like this:
1143   //   [_contentView retain];
1144   //   [_contentView removeFromSuperview];
1145   //   [self addSubview:_contentView]; // invalidates 'self'
1146   //   [_contentView release];
1147   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1148     return state;
1149 
1150   // Woah!  More autorelease counts then retain counts left.
1151   // Emit hard error.
1152   V = V ^ RefVal::ErrorOverAutorelease;
1153   state = setRefBinding(state, Sym, V);
1154 
1155   ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1156   if (N) {
1157     SmallString<128> sbuf;
1158     llvm::raw_svector_ostream os(sbuf);
1159     os << "Object was autoreleased ";
1160     if (V.getAutoreleaseCount() > 1)
1161       os << V.getAutoreleaseCount() << " times but the object ";
1162     else
1163       os << "but ";
1164     os << "has a +" << V.getCount() << " retain count";
1165 
1166     if (!overAutorelease)
1167       overAutorelease.reset(new OverAutorelease(this));
1168 
1169     const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1170     auto R = llvm::make_unique<CFRefReport>(*overAutorelease, LOpts, SummaryLog,
1171                                             N, Sym, os.str());
1172     Ctx.emitReport(std::move(R));
1173   }
1174 
1175   return nullptr;
1176 }
1177 
1178 ProgramStateRef
1179 RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
1180                                       SymbolRef sid, RefVal V,
1181                                     SmallVectorImpl<SymbolRef> &Leaked) const {
1182   bool hasLeak;
1183 
1184   // HACK: Ignore retain-count issues on values accessed through ivars,
1185   // because of cases like this:
1186   //   [_contentView retain];
1187   //   [_contentView removeFromSuperview];
1188   //   [self addSubview:_contentView]; // invalidates 'self'
1189   //   [_contentView release];
1190   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1191     hasLeak = false;
1192   else if (V.isOwned())
1193     hasLeak = true;
1194   else if (V.isNotOwned() || V.isReturnedOwned())
1195     hasLeak = (V.getCount() > 0);
1196   else
1197     hasLeak = false;
1198 
1199   if (!hasLeak)
1200     return removeRefBinding(state, sid);
1201 
1202   Leaked.push_back(sid);
1203   return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1204 }
1205 
1206 ExplodedNode *
1207 RetainCountChecker::processLeaks(ProgramStateRef state,
1208                                  SmallVectorImpl<SymbolRef> &Leaked,
1209                                  CheckerContext &Ctx,
1210                                  ExplodedNode *Pred) const {
1211   // Generate an intermediate node representing the leak point.
1212   ExplodedNode *N = Ctx.addTransition(state, Pred);
1213 
1214   if (N) {
1215     for (SmallVectorImpl<SymbolRef>::iterator
1216          I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
1217 
1218       const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1219       CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts)
1220                           : getLeakAtReturnBug(LOpts);
1221       assert(BT && "BugType not initialized.");
1222 
1223       Ctx.emitReport(llvm::make_unique<CFRefLeakReport>(
1224           *BT, LOpts, SummaryLog, N, *I, Ctx, IncludeAllocationLine));
1225     }
1226   }
1227 
1228   return N;
1229 }
1230 
1231 static bool isISLObjectRef(QualType Ty) {
1232   return StringRef(Ty.getAsString()).startswith("isl_");
1233 }
1234 
1235 void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
1236   if (!Ctx.inTopFrame())
1237     return;
1238 
1239   RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
1240   const LocationContext *LCtx = Ctx.getLocationContext();
1241   const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
1242 
1243   if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
1244     return;
1245 
1246   ProgramStateRef state = Ctx.getState();
1247   const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
1248   ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1249 
1250   for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
1251     const ParmVarDecl *Param = FD->getParamDecl(idx);
1252     SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1253 
1254     QualType Ty = Param->getType();
1255     const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
1256     if (AE && *AE == DecRef && isISLObjectRef(Ty)) {
1257       state = setRefBinding(
1258           state, Sym, RefVal::makeOwned(RetEffect::ObjKind::Generalized, Ty));
1259     } else if (isISLObjectRef(Ty)) {
1260       state = setRefBinding(
1261           state, Sym,
1262           RefVal::makeNotOwned(RetEffect::ObjKind::Generalized, Ty));
1263     }
1264   }
1265 
1266   Ctx.addTransition(state);
1267 }
1268 
1269 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
1270                                           CheckerContext &Ctx) const {
1271   ExplodedNode *Pred = processReturn(RS, Ctx);
1272 
1273   // Created state cached out.
1274   if (!Pred) {
1275     return;
1276   }
1277 
1278   ProgramStateRef state = Pred->getState();
1279   RefBindingsTy B = state->get<RefBindings>();
1280 
1281   // Don't process anything within synthesized bodies.
1282   const LocationContext *LCtx = Pred->getLocationContext();
1283   if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1284     assert(!LCtx->inTopFrame());
1285     return;
1286   }
1287 
1288   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1289     state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1290                                     I->first, I->second);
1291     if (!state)
1292       return;
1293   }
1294 
1295   // If the current LocationContext has a parent, don't check for leaks.
1296   // We will do that later.
1297   // FIXME: we should instead check for imbalances of the retain/releases,
1298   // and suggest annotations.
1299   if (LCtx->getParent())
1300     return;
1301 
1302   B = state->get<RefBindings>();
1303   SmallVector<SymbolRef, 10> Leaked;
1304 
1305   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
1306     state = handleSymbolDeath(state, I->first, I->second, Leaked);
1307 
1308   processLeaks(state, Leaked, Ctx, Pred);
1309 }
1310 
1311 void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1312                                           CheckerContext &C) const {
1313   ExplodedNode *Pred = C.getPredecessor();
1314 
1315   ProgramStateRef state = C.getState();
1316   RefBindingsTy B = state->get<RefBindings>();
1317   SmallVector<SymbolRef, 10> Leaked;
1318 
1319   // Update counts from autorelease pools
1320   for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
1321        E = SymReaper.dead_end(); I != E; ++I) {
1322     SymbolRef Sym = *I;
1323     if (const RefVal *T = B.lookup(Sym)){
1324       // Use the symbol as the tag.
1325       // FIXME: This might not be as unique as we would like.
1326       static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
1327       state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, *T);
1328       if (!state)
1329         return;
1330 
1331       // Fetch the new reference count from the state, and use it to handle
1332       // this symbol.
1333       state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked);
1334     }
1335   }
1336 
1337   if (Leaked.empty()) {
1338     C.addTransition(state);
1339     return;
1340   }
1341 
1342   Pred = processLeaks(state, Leaked, C, Pred);
1343 
1344   // Did we cache out?
1345   if (!Pred)
1346     return;
1347 
1348   // Now generate a new node that nukes the old bindings.
1349   // The only bindings left at this point are the leaked symbols.
1350   RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1351   B = state->get<RefBindings>();
1352 
1353   for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
1354                                             E = Leaked.end();
1355        I != E; ++I)
1356     B = F.remove(B, *I);
1357 
1358   state = state->set<RefBindings>(B);
1359   C.addTransition(state, Pred);
1360 }
1361 
1362 void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
1363                                     const char *NL, const char *Sep) const {
1364 
1365   RefBindingsTy B = State->get<RefBindings>();
1366 
1367   if (B.isEmpty())
1368     return;
1369 
1370   Out << Sep << NL;
1371 
1372   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1373     Out << I->first << " : ";
1374     I->second.print(Out);
1375     Out << NL;
1376   }
1377 }
1378 
1379 //===----------------------------------------------------------------------===//
1380 // Checker registration.
1381 //===----------------------------------------------------------------------===//
1382 
1383 void ento::registerRetainCountChecker(CheckerManager &Mgr) {
1384   Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions());
1385 }
1386