xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp (revision 3c2ed8f3386eebae956267998c2d9aaec9105181)
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   using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
778   Optional<BehaviorSummary> BSmr =
779       SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
780 
781   // See if it's one of the specific functions we know how to eval.
782   if (!BSmr)
783     return false;
784 
785   // Bind the return value.
786   if (BSmr == BehaviorSummary::Identity ||
787       BSmr == BehaviorSummary::IdentityOrZero) {
788     SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
789 
790     // If the receiver is unknown or the function has
791     // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
792     // return value.
793     if (RetVal.isUnknown() ||
794         (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
795       SValBuilder &SVB = C.getSValBuilder();
796       RetVal =
797           SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
798     }
799     state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
800 
801     if (BSmr == BehaviorSummary::IdentityOrZero) {
802       // Add a branch where the output is zero.
803       ProgramStateRef NullOutputState = C.getState();
804 
805       // Assume that output is zero on the other branch.
806       NullOutputState = NullOutputState->BindExpr(
807           CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
808 
809       C.addTransition(NullOutputState);
810 
811       // And on the original branch assume that both input and
812       // output are non-zero.
813       if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
814         state = state->assume(*L, /*Assumption=*/true);
815 
816     }
817   }
818 
819   C.addTransition(state);
820   return true;
821 }
822 
823 ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
824                                                  CheckerContext &C) const {
825   ExplodedNode *Pred = C.getPredecessor();
826 
827   // Only adjust the reference count if this is the top-level call frame,
828   // and not the result of inlining.  In the future, we should do
829   // better checking even for inlined calls, and see if they match
830   // with their expected semantics (e.g., the method should return a retained
831   // object, etc.).
832   if (!C.inTopFrame())
833     return Pred;
834 
835   if (!S)
836     return Pred;
837 
838   const Expr *RetE = S->getRetValue();
839   if (!RetE)
840     return Pred;
841 
842   ProgramStateRef state = C.getState();
843   SymbolRef Sym =
844     state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
845   if (!Sym)
846     return Pred;
847 
848   // Get the reference count binding (if any).
849   const RefVal *T = getRefBinding(state, Sym);
850   if (!T)
851     return Pred;
852 
853   // Change the reference count.
854   RefVal X = *T;
855 
856   switch (X.getKind()) {
857     case RefVal::Owned: {
858       unsigned cnt = X.getCount();
859       assert(cnt > 0);
860       X.setCount(cnt - 1);
861       X = X ^ RefVal::ReturnedOwned;
862       break;
863     }
864 
865     case RefVal::NotOwned: {
866       unsigned cnt = X.getCount();
867       if (cnt) {
868         X.setCount(cnt - 1);
869         X = X ^ RefVal::ReturnedOwned;
870       } else {
871         X = X ^ RefVal::ReturnedNotOwned;
872       }
873       break;
874     }
875 
876     default:
877       return Pred;
878   }
879 
880   // Update the binding.
881   state = setRefBinding(state, Sym, X);
882   Pred = C.addTransition(state);
883 
884   // At this point we have updated the state properly.
885   // Everything after this is merely checking to see if the return value has
886   // been over- or under-retained.
887 
888   // Did we cache out?
889   if (!Pred)
890     return nullptr;
891 
892   // Update the autorelease counts.
893   static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
894   state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
895 
896   // Have we generated a sink node?
897   if (!state)
898     return nullptr;
899 
900   // Get the updated binding.
901   T = getRefBinding(state, Sym);
902   assert(T);
903   X = *T;
904 
905   // Consult the summary of the enclosing method.
906   RetainSummaryManager &Summaries = getSummaryManager(C);
907   const Decl *CD = &Pred->getCodeDecl();
908   RetEffect RE = RetEffect::MakeNoRet();
909 
910   // FIXME: What is the convention for blocks? Is there one?
911   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
912     const RetainSummary *Summ = Summaries.getMethodSummary(MD);
913     RE = Summ->getRetEffect();
914   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
915     if (!isa<CXXMethodDecl>(FD)) {
916       const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
917       RE = Summ->getRetEffect();
918     }
919   }
920 
921   return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
922 }
923 
924 ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
925                                                   CheckerContext &C,
926                                                   ExplodedNode *Pred,
927                                                   RetEffect RE, RefVal X,
928                                                   SymbolRef Sym,
929                                                   ProgramStateRef state) const {
930   // HACK: Ignore retain-count issues on values accessed through ivars,
931   // because of cases like this:
932   //   [_contentView retain];
933   //   [_contentView removeFromSuperview];
934   //   [self addSubview:_contentView]; // invalidates 'self'
935   //   [_contentView release];
936   if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
937     return Pred;
938 
939   // Any leaks or other errors?
940   if (X.isReturnedOwned() && X.getCount() == 0) {
941     if (RE.getKind() != RetEffect::NoRet) {
942       if (!RE.isOwned()) {
943 
944         // The returning type is a CF, we expect the enclosing method should
945         // return ownership.
946         X = X ^ RefVal::ErrorLeakReturned;
947 
948         // Generate an error node.
949         state = setRefBinding(state, Sym, X);
950 
951         static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
952         ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
953         if (N) {
954           const LangOptions &LOpts = C.getASTContext().getLangOpts();
955           auto R = llvm::make_unique<CFRefLeakReport>(
956               *getLeakAtReturnBug(LOpts), LOpts, SummaryLog, N, Sym, C,
957               IncludeAllocationLine);
958           C.emitReport(std::move(R));
959         }
960         return N;
961       }
962     }
963   } else if (X.isReturnedNotOwned()) {
964     if (RE.isOwned()) {
965       if (X.getIvarAccessHistory() ==
966             RefVal::IvarAccessHistory::AccessedDirectly) {
967         // Assume the method was trying to transfer a +1 reference from a
968         // strong ivar to the caller.
969         state = setRefBinding(state, Sym,
970                               X.releaseViaIvar() ^ RefVal::ReturnedOwned);
971       } else {
972         // Trying to return a not owned object to a caller expecting an
973         // owned object.
974         state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
975 
976         static CheckerProgramPointTag
977             ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
978 
979         ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
980         if (N) {
981           if (!returnNotOwnedForOwned)
982             returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
983 
984           auto R = llvm::make_unique<CFRefReport>(
985               *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
986               SummaryLog, N, Sym);
987           C.emitReport(std::move(R));
988         }
989         return N;
990       }
991     }
992   }
993   return Pred;
994 }
995 
996 //===----------------------------------------------------------------------===//
997 // Check various ways a symbol can be invalidated.
998 //===----------------------------------------------------------------------===//
999 
1000 void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
1001                                    CheckerContext &C) const {
1002   // Are we storing to something that causes the value to "escape"?
1003   bool escapes = true;
1004 
1005   // A value escapes in three possible cases (this may change):
1006   //
1007   // (1) we are binding to something that is not a memory region.
1008   // (2) we are binding to a memregion that does not have stack storage
1009   // (3) we are binding to a memregion with stack storage that the store
1010   //     does not understand.
1011   ProgramStateRef state = C.getState();
1012 
1013   if (auto regionLoc = loc.getAs<loc::MemRegionVal>()) {
1014     escapes = !regionLoc->getRegion()->hasStackStorage();
1015 
1016     if (!escapes) {
1017       // To test (3), generate a new state with the binding added.  If it is
1018       // the same state, then it escapes (since the store cannot represent
1019       // the binding).
1020       // Do this only if we know that the store is not supposed to generate the
1021       // same state.
1022       SVal StoredVal = state->getSVal(regionLoc->getRegion());
1023       if (StoredVal != val)
1024         escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext())));
1025     }
1026     if (!escapes) {
1027       // Case 4: We do not currently model what happens when a symbol is
1028       // assigned to a struct field, so be conservative here and let the symbol
1029       // go. TODO: This could definitely be improved upon.
1030       escapes = !isa<VarRegion>(regionLoc->getRegion());
1031     }
1032   }
1033 
1034   // If we are storing the value into an auto function scope variable annotated
1035   // with (__attribute__((cleanup))), stop tracking the value to avoid leak
1036   // false positives.
1037   if (const auto *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
1038     const VarDecl *VD = LVR->getDecl();
1039     if (VD->hasAttr<CleanupAttr>()) {
1040       escapes = true;
1041     }
1042   }
1043 
1044   // If our store can represent the binding and we aren't storing to something
1045   // that doesn't have local storage then just return and have the simulation
1046   // state continue as is.
1047   if (!escapes)
1048       return;
1049 
1050   // Otherwise, find all symbols referenced by 'val' that we are tracking
1051   // and stop tracking them.
1052   state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1053   C.addTransition(state);
1054 }
1055 
1056 ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
1057                                                SVal Cond,
1058                                                bool Assumption) const {
1059   // FIXME: We may add to the interface of evalAssume the list of symbols
1060   //  whose assumptions have changed.  For now we just iterate through the
1061   //  bindings and check if any of the tracked symbols are NULL.  This isn't
1062   //  too bad since the number of symbols we will track in practice are
1063   //  probably small and evalAssume is only called at branches and a few
1064   //  other places.
1065   RefBindingsTy B = state->get<RefBindings>();
1066 
1067   if (B.isEmpty())
1068     return state;
1069 
1070   bool changed = false;
1071   RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1072 
1073   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1074     // Check if the symbol is null stop tracking the symbol.
1075     ConstraintManager &CMgr = state->getConstraintManager();
1076     ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1077     if (AllocFailed.isConstrainedTrue()) {
1078       changed = true;
1079       B = RefBFactory.remove(B, I.getKey());
1080     }
1081   }
1082 
1083   if (changed)
1084     state = state->set<RefBindings>(B);
1085 
1086   return state;
1087 }
1088 
1089 ProgramStateRef
1090 RetainCountChecker::checkRegionChanges(ProgramStateRef state,
1091                                        const InvalidatedSymbols *invalidated,
1092                                        ArrayRef<const MemRegion *> ExplicitRegions,
1093                                        ArrayRef<const MemRegion *> Regions,
1094                                        const LocationContext *LCtx,
1095                                        const CallEvent *Call) const {
1096   if (!invalidated)
1097     return state;
1098 
1099   llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
1100   for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
1101        E = ExplicitRegions.end(); I != E; ++I) {
1102     if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
1103       WhitelistedSymbols.insert(SR->getSymbol());
1104   }
1105 
1106   for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
1107        E = invalidated->end(); I!=E; ++I) {
1108     SymbolRef sym = *I;
1109     if (WhitelistedSymbols.count(sym))
1110       continue;
1111     // Remove any existing reference-count binding.
1112     state = removeRefBinding(state, sym);
1113   }
1114   return state;
1115 }
1116 
1117 ProgramStateRef
1118 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
1119                                             ExplodedNode *Pred,
1120                                             const ProgramPointTag *Tag,
1121                                             CheckerContext &Ctx,
1122                                             SymbolRef Sym,
1123                                             RefVal V,
1124                                             const ReturnStmt *S) const {
1125   unsigned ACnt = V.getAutoreleaseCount();
1126 
1127   // No autorelease counts?  Nothing to be done.
1128   if (!ACnt)
1129     return state;
1130 
1131   unsigned Cnt = V.getCount();
1132 
1133   // FIXME: Handle sending 'autorelease' to already released object.
1134 
1135   if (V.getKind() == RefVal::ReturnedOwned)
1136     ++Cnt;
1137 
1138   // If we would over-release here, but we know the value came from an ivar,
1139   // assume it was a strong ivar that's just been relinquished.
1140   if (ACnt > Cnt &&
1141       V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
1142     V = V.releaseViaIvar();
1143     --ACnt;
1144   }
1145 
1146   if (ACnt <= Cnt) {
1147     if (ACnt == Cnt) {
1148       V.clearCounts();
1149       if (V.getKind() == RefVal::ReturnedOwned) {
1150         V = V ^ RefVal::ReturnedNotOwned;
1151       } else {
1152         V = V ^ RefVal::NotOwned;
1153       }
1154     } else {
1155       V.setCount(V.getCount() - ACnt);
1156       V.setAutoreleaseCount(0);
1157     }
1158     return setRefBinding(state, Sym, V);
1159   }
1160 
1161   // HACK: Ignore retain-count issues on values accessed through ivars,
1162   // because of cases like this:
1163   //   [_contentView retain];
1164   //   [_contentView removeFromSuperview];
1165   //   [self addSubview:_contentView]; // invalidates 'self'
1166   //   [_contentView release];
1167   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1168     return state;
1169 
1170   // Woah!  More autorelease counts then retain counts left.
1171   // Emit hard error.
1172   V = V ^ RefVal::ErrorOverAutorelease;
1173   state = setRefBinding(state, Sym, V);
1174 
1175   ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1176   if (N) {
1177     SmallString<128> sbuf;
1178     llvm::raw_svector_ostream os(sbuf);
1179     os << "Object was autoreleased ";
1180     if (V.getAutoreleaseCount() > 1)
1181       os << V.getAutoreleaseCount() << " times but the object ";
1182     else
1183       os << "but ";
1184     os << "has a +" << V.getCount() << " retain count";
1185 
1186     if (!overAutorelease)
1187       overAutorelease.reset(new OverAutorelease(this));
1188 
1189     const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1190     auto R = llvm::make_unique<CFRefReport>(*overAutorelease, LOpts, SummaryLog,
1191                                             N, Sym, os.str());
1192     Ctx.emitReport(std::move(R));
1193   }
1194 
1195   return nullptr;
1196 }
1197 
1198 ProgramStateRef
1199 RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
1200                                       SymbolRef sid, RefVal V,
1201                                     SmallVectorImpl<SymbolRef> &Leaked) const {
1202   bool hasLeak;
1203 
1204   // HACK: Ignore retain-count issues on values accessed through ivars,
1205   // because of cases like this:
1206   //   [_contentView retain];
1207   //   [_contentView removeFromSuperview];
1208   //   [self addSubview:_contentView]; // invalidates 'self'
1209   //   [_contentView release];
1210   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1211     hasLeak = false;
1212   else if (V.isOwned())
1213     hasLeak = true;
1214   else if (V.isNotOwned() || V.isReturnedOwned())
1215     hasLeak = (V.getCount() > 0);
1216   else
1217     hasLeak = false;
1218 
1219   if (!hasLeak)
1220     return removeRefBinding(state, sid);
1221 
1222   Leaked.push_back(sid);
1223   return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1224 }
1225 
1226 ExplodedNode *
1227 RetainCountChecker::processLeaks(ProgramStateRef state,
1228                                  SmallVectorImpl<SymbolRef> &Leaked,
1229                                  CheckerContext &Ctx,
1230                                  ExplodedNode *Pred) const {
1231   // Generate an intermediate node representing the leak point.
1232   ExplodedNode *N = Ctx.addTransition(state, Pred);
1233 
1234   if (N) {
1235     for (SmallVectorImpl<SymbolRef>::iterator
1236          I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
1237 
1238       const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1239       CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts)
1240                           : getLeakAtReturnBug(LOpts);
1241       assert(BT && "BugType not initialized.");
1242 
1243       Ctx.emitReport(llvm::make_unique<CFRefLeakReport>(
1244           *BT, LOpts, SummaryLog, N, *I, Ctx, IncludeAllocationLine));
1245     }
1246   }
1247 
1248   return N;
1249 }
1250 
1251 static bool isISLObjectRef(QualType Ty) {
1252   return StringRef(Ty.getAsString()).startswith("isl_");
1253 }
1254 
1255 void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
1256   if (!Ctx.inTopFrame())
1257     return;
1258 
1259   RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
1260   const LocationContext *LCtx = Ctx.getLocationContext();
1261   const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
1262 
1263   if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
1264     return;
1265 
1266   ProgramStateRef state = Ctx.getState();
1267   const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
1268   ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1269 
1270   for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
1271     const ParmVarDecl *Param = FD->getParamDecl(idx);
1272     SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1273 
1274     QualType Ty = Param->getType();
1275     const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
1276     if (AE && *AE == DecRef && isISLObjectRef(Ty)) {
1277       state = setRefBinding(
1278           state, Sym, RefVal::makeOwned(RetEffect::ObjKind::Generalized, Ty));
1279     } else if (isISLObjectRef(Ty)) {
1280       state = setRefBinding(
1281           state, Sym,
1282           RefVal::makeNotOwned(RetEffect::ObjKind::Generalized, Ty));
1283     }
1284   }
1285 
1286   Ctx.addTransition(state);
1287 }
1288 
1289 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
1290                                           CheckerContext &Ctx) const {
1291   ExplodedNode *Pred = processReturn(RS, Ctx);
1292 
1293   // Created state cached out.
1294   if (!Pred) {
1295     return;
1296   }
1297 
1298   ProgramStateRef state = Pred->getState();
1299   RefBindingsTy B = state->get<RefBindings>();
1300 
1301   // Don't process anything within synthesized bodies.
1302   const LocationContext *LCtx = Pred->getLocationContext();
1303   if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1304     assert(!LCtx->inTopFrame());
1305     return;
1306   }
1307 
1308   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1309     state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1310                                     I->first, I->second);
1311     if (!state)
1312       return;
1313   }
1314 
1315   // If the current LocationContext has a parent, don't check for leaks.
1316   // We will do that later.
1317   // FIXME: we should instead check for imbalances of the retain/releases,
1318   // and suggest annotations.
1319   if (LCtx->getParent())
1320     return;
1321 
1322   B = state->get<RefBindings>();
1323   SmallVector<SymbolRef, 10> Leaked;
1324 
1325   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
1326     state = handleSymbolDeath(state, I->first, I->second, Leaked);
1327 
1328   processLeaks(state, Leaked, Ctx, Pred);
1329 }
1330 
1331 void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1332                                           CheckerContext &C) const {
1333   ExplodedNode *Pred = C.getPredecessor();
1334 
1335   ProgramStateRef state = C.getState();
1336   RefBindingsTy B = state->get<RefBindings>();
1337   SmallVector<SymbolRef, 10> Leaked;
1338 
1339   // Update counts from autorelease pools
1340   for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
1341        E = SymReaper.dead_end(); I != E; ++I) {
1342     SymbolRef Sym = *I;
1343     if (const RefVal *T = B.lookup(Sym)){
1344       // Use the symbol as the tag.
1345       // FIXME: This might not be as unique as we would like.
1346       static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
1347       state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, *T);
1348       if (!state)
1349         return;
1350 
1351       // Fetch the new reference count from the state, and use it to handle
1352       // this symbol.
1353       state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked);
1354     }
1355   }
1356 
1357   if (Leaked.empty()) {
1358     C.addTransition(state);
1359     return;
1360   }
1361 
1362   Pred = processLeaks(state, Leaked, C, Pred);
1363 
1364   // Did we cache out?
1365   if (!Pred)
1366     return;
1367 
1368   // Now generate a new node that nukes the old bindings.
1369   // The only bindings left at this point are the leaked symbols.
1370   RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1371   B = state->get<RefBindings>();
1372 
1373   for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
1374                                             E = Leaked.end();
1375        I != E; ++I)
1376     B = F.remove(B, *I);
1377 
1378   state = state->set<RefBindings>(B);
1379   C.addTransition(state, Pred);
1380 }
1381 
1382 void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
1383                                     const char *NL, const char *Sep) const {
1384 
1385   RefBindingsTy B = State->get<RefBindings>();
1386 
1387   if (B.isEmpty())
1388     return;
1389 
1390   Out << Sep << NL;
1391 
1392   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1393     Out << I->first << " : ";
1394     I->second.print(Out);
1395     Out << NL;
1396   }
1397 }
1398 
1399 //===----------------------------------------------------------------------===//
1400 // Checker registration.
1401 //===----------------------------------------------------------------------===//
1402 
1403 void ento::registerRetainCountChecker(CheckerManager &Mgr) {
1404   Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions());
1405 }
1406