1 //==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines the methods for RetainCountChecker, which implements
10 //  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RetainCountChecker.h"
15 
16 using namespace clang;
17 using namespace ento;
18 using namespace retaincountchecker;
19 using llvm::StrInStrNoCase;
20 
21 REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
22 
23 namespace clang {
24 namespace ento {
25 namespace retaincountchecker {
26 
27 const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym) {
28   return State->get<RefBindings>(Sym);
29 }
30 
31 } // end namespace retaincountchecker
32 } // end namespace ento
33 } // end namespace clang
34 
35 static ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
36                                      RefVal Val) {
37   assert(Sym != nullptr);
38   return State->set<RefBindings>(Sym, Val);
39 }
40 
41 static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
42   return State->remove<RefBindings>(Sym);
43 }
44 
45 void RefVal::print(raw_ostream &Out) const {
46   if (!T.isNull())
47     Out << "Tracked " << T.getAsString() << " | ";
48 
49   switch (getKind()) {
50     default: llvm_unreachable("Invalid RefVal kind");
51     case Owned: {
52       Out << "Owned";
53       unsigned cnt = getCount();
54       if (cnt) Out << " (+ " << cnt << ")";
55       break;
56     }
57 
58     case NotOwned: {
59       Out << "NotOwned";
60       unsigned cnt = getCount();
61       if (cnt) Out << " (+ " << cnt << ")";
62       break;
63     }
64 
65     case ReturnedOwned: {
66       Out << "ReturnedOwned";
67       unsigned cnt = getCount();
68       if (cnt) Out << " (+ " << cnt << ")";
69       break;
70     }
71 
72     case ReturnedNotOwned: {
73       Out << "ReturnedNotOwned";
74       unsigned cnt = getCount();
75       if (cnt) Out << " (+ " << cnt << ")";
76       break;
77     }
78 
79     case Released:
80       Out << "Released";
81       break;
82 
83     case ErrorDeallocNotOwned:
84       Out << "-dealloc (not-owned)";
85       break;
86 
87     case ErrorLeak:
88       Out << "Leaked";
89       break;
90 
91     case ErrorLeakReturned:
92       Out << "Leaked (Bad naming)";
93       break;
94 
95     case ErrorUseAfterRelease:
96       Out << "Use-After-Release [ERROR]";
97       break;
98 
99     case ErrorReleaseNotOwned:
100       Out << "Release of Not-Owned [ERROR]";
101       break;
102 
103     case RefVal::ErrorOverAutorelease:
104       Out << "Over-autoreleased";
105       break;
106 
107     case RefVal::ErrorReturnedNotOwned:
108       Out << "Non-owned object returned instead of owned";
109       break;
110   }
111 
112   switch (getIvarAccessHistory()) {
113   case IvarAccessHistory::None:
114     break;
115   case IvarAccessHistory::AccessedDirectly:
116     Out << " [direct ivar access]";
117     break;
118   case IvarAccessHistory::ReleasedAfterDirectAccess:
119     Out << " [released after direct ivar access]";
120   }
121 
122   if (ACnt) {
123     Out << " [autorelease -" << ACnt << ']';
124   }
125 }
126 
127 namespace {
128 class StopTrackingCallback final : public SymbolVisitor {
129   ProgramStateRef state;
130 public:
131   StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
132   ProgramStateRef getState() const { return state; }
133 
134   bool VisitSymbol(SymbolRef sym) override {
135     state = removeRefBinding(state, sym);
136     return true;
137   }
138 };
139 } // end anonymous namespace
140 
141 //===----------------------------------------------------------------------===//
142 // Handle statements that may have an effect on refcounts.
143 //===----------------------------------------------------------------------===//
144 
145 void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
146                                        CheckerContext &C) const {
147 
148   // Scan the BlockDecRefExprs for any object the retain count checker
149   // may be tracking.
150   if (!BE->getBlockDecl()->hasCaptures())
151     return;
152 
153   ProgramStateRef state = C.getState();
154   auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
155 
156   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
157                                             E = R->referenced_vars_end();
158 
159   if (I == E)
160     return;
161 
162   // FIXME: For now we invalidate the tracking of all symbols passed to blocks
163   // via captured variables, even though captured variables result in a copy
164   // and in implicit increment/decrement of a retain count.
165   SmallVector<const MemRegion*, 10> Regions;
166   const LocationContext *LC = C.getLocationContext();
167   MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
168 
169   for ( ; I != E; ++I) {
170     const VarRegion *VR = I.getCapturedRegion();
171     if (VR->getSuperRegion() == R) {
172       VR = MemMgr.getVarRegion(VR->getDecl(), LC);
173     }
174     Regions.push_back(VR);
175   }
176 
177   state = state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
178   C.addTransition(state);
179 }
180 
181 void RetainCountChecker::checkPostStmt(const CastExpr *CE,
182                                        CheckerContext &C) const {
183   const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
184   if (!BE)
185     return;
186 
187   ArgEffect AE = ArgEffect(IncRef, ObjKind::ObjC);
188 
189   switch (BE->getBridgeKind()) {
190     case OBC_Bridge:
191       // Do nothing.
192       return;
193     case OBC_BridgeRetained:
194       AE = AE.withKind(IncRef);
195       break;
196     case OBC_BridgeTransfer:
197       AE = AE.withKind(DecRefBridgedTransferred);
198       break;
199   }
200 
201   ProgramStateRef state = C.getState();
202   SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
203   if (!Sym)
204     return;
205   const RefVal* T = getRefBinding(state, Sym);
206   if (!T)
207     return;
208 
209   RefVal::Kind hasErr = (RefVal::Kind) 0;
210   state = updateSymbol(state, Sym, *T, AE, hasErr, C);
211 
212   if (hasErr) {
213     // FIXME: If we get an error during a bridge cast, should we report it?
214     return;
215   }
216 
217   C.addTransition(state);
218 }
219 
220 void RetainCountChecker::processObjCLiterals(CheckerContext &C,
221                                              const Expr *Ex) const {
222   ProgramStateRef state = C.getState();
223   const ExplodedNode *pred = C.getPredecessor();
224   for (const Stmt *Child : Ex->children()) {
225     SVal V = pred->getSVal(Child);
226     if (SymbolRef sym = V.getAsSymbol())
227       if (const RefVal* T = getRefBinding(state, sym)) {
228         RefVal::Kind hasErr = (RefVal::Kind) 0;
229         state = updateSymbol(state, sym, *T,
230                              ArgEffect(MayEscape, ObjKind::ObjC), 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(ObjKind::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(ObjKind::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(ObjKind::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   ObjKind Kind;
292   if (Ty->isObjCRetainableType())
293     Kind = ObjKind::ObjC;
294   else if (coreFoundation::isCFObjectRef(Ty))
295     Kind = ObjKind::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 static bool isPointerToObject(QualType QT) {
393   QualType PT = QT->getPointeeType();
394   if (!PT.isNull())
395     if (PT->getAsCXXRecordDecl())
396       return true;
397   return false;
398 }
399 
400 /// Whether the tracked value should be escaped on a given call.
401 /// OSObjects are escaped when passed to void * / etc.
402 static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
403                                        const RefVal *TrackedValue) {
404   if (TrackedValue->getObjKind() != ObjKind::OS)
405     return false;
406   if (ArgIdx >= CE.parameters().size())
407     return false;
408   return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
409 }
410 
411 // We don't always get the exact modeling of the function with regards to the
412 // retain count checker even when the function is inlined. For example, we need
413 // to stop tracking the symbols which were marked with StopTrackingHard.
414 void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
415                                                  const CallEvent &CallOrMsg,
416                                                  CheckerContext &C) const {
417   ProgramStateRef state = C.getState();
418 
419   // Evaluate the effect of the arguments.
420   for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
421     SVal V = CallOrMsg.getArgSVal(idx);
422 
423     if (SymbolRef Sym = V.getAsLocSymbol()) {
424       bool ShouldRemoveBinding = Summ.getArg(idx).getKind() == StopTrackingHard;
425       if (const RefVal *T = getRefBinding(state, Sym))
426         if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
427           ShouldRemoveBinding = true;
428 
429       if (ShouldRemoveBinding)
430         state = removeRefBinding(state, Sym);
431     }
432   }
433 
434   // Evaluate the effect on the message receiver.
435   if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
436     if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
437       if (Summ.getReceiverEffect().getKind() == StopTrackingHard) {
438         state = removeRefBinding(state, Sym);
439       }
440     }
441   }
442 
443   // Consult the summary for the return value.
444   RetEffect RE = Summ.getRetEffect();
445 
446   if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
447     if (RE.getKind() == RetEffect::NoRetHard)
448       state = removeRefBinding(state, Sym);
449   }
450 
451   C.addTransition(state);
452 }
453 
454 static bool isSmartPtrField(const MemRegion *MR) {
455   const auto *TR = dyn_cast<TypedValueRegion>(
456     cast<SubRegion>(MR)->getSuperRegion());
457   return TR && RetainSummaryManager::isKnownSmartPointer(TR->getValueType());
458 }
459 
460 
461 /// A value escapes in these possible cases:
462 ///
463 /// - binding to something that is not a memory region.
464 /// - binding to a memregion that does not have stack storage
465 /// - binding to a variable that has a destructor attached using CleanupAttr
466 ///
467 /// We do not currently model what happens when a symbol is
468 /// assigned to a struct field, unless it is a known smart pointer
469 /// implementation, about which we know that it is inlined.
470 /// FIXME: This could definitely be improved upon.
471 static bool shouldEscapeRegion(const MemRegion *R) {
472   if (isSmartPtrField(R))
473     return false;
474 
475   const auto *VR = dyn_cast<VarRegion>(R);
476 
477   if (!R->hasStackStorage() || !VR)
478     return true;
479 
480   const VarDecl *VD = VR->getDecl();
481   if (!VD->hasAttr<CleanupAttr>())
482     return false; // CleanupAttr attaches destructors, which cause escaping.
483   return true;
484 }
485 
486 static SmallVector<ProgramStateRef, 2>
487 updateOutParameters(ProgramStateRef State, const RetainSummary &Summ,
488                     const CallEvent &CE) {
489 
490   SVal L = CE.getReturnValue();
491 
492   // Splitting is required to support out parameters,
493   // as out parameters might be created only on the "success" branch.
494   // We want to avoid eagerly splitting unless out parameters are actually
495   // needed.
496   bool SplitNecessary = false;
497   for (auto &P : Summ.getArgEffects())
498     if (P.second.getKind() == RetainedOutParameterOnNonZero ||
499         P.second.getKind() == RetainedOutParameterOnZero)
500       SplitNecessary = true;
501 
502   ProgramStateRef AssumeNonZeroReturn = State;
503   ProgramStateRef AssumeZeroReturn = State;
504 
505   if (SplitNecessary) {
506     if (auto DL = L.getAs<DefinedOrUnknownSVal>()) {
507       AssumeNonZeroReturn = AssumeNonZeroReturn->assume(*DL, true);
508       AssumeZeroReturn = AssumeZeroReturn->assume(*DL, false);
509     }
510   }
511 
512   for (unsigned idx = 0, e = CE.getNumArgs(); idx != e; ++idx) {
513     SVal ArgVal = CE.getArgSVal(idx);
514     ArgEffect AE = Summ.getArg(idx);
515 
516     auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
517     if (!ArgRegion)
518       continue;
519 
520     QualType PointeeTy = ArgRegion->getValueType();
521     SVal PointeeVal = State->getSVal(ArgRegion);
522     SymbolRef Pointee = PointeeVal.getAsLocSymbol();
523     if (!Pointee)
524       continue;
525 
526     if (shouldEscapeRegion(ArgRegion))
527       continue;
528 
529     auto makeNotOwnedParameter = [&](ProgramStateRef St) {
530       return setRefBinding(St, Pointee,
531                            RefVal::makeNotOwned(AE.getObjKind(), PointeeTy));
532     };
533     auto makeOwnedParameter = [&](ProgramStateRef St) {
534       return setRefBinding(St, Pointee,
535                            RefVal::makeOwned(ObjKind::OS, PointeeTy));
536     };
537 
538     switch (AE.getKind()) {
539     case UnretainedOutParameter:
540       AssumeNonZeroReturn = makeNotOwnedParameter(AssumeNonZeroReturn);
541       AssumeZeroReturn = makeNotOwnedParameter(AssumeZeroReturn);
542       break;
543     case RetainedOutParameter:
544       AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
545       AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
546       break;
547     case RetainedOutParameterOnNonZero:
548       AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
549       break;
550     case RetainedOutParameterOnZero:
551       AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
552       break;
553     default:
554       break;
555     }
556   }
557 
558   if (SplitNecessary) {
559     return {AssumeNonZeroReturn, AssumeZeroReturn};
560   } else {
561     assert(AssumeZeroReturn == AssumeNonZeroReturn);
562     return {AssumeZeroReturn};
563   }
564 }
565 
566 void RetainCountChecker::checkSummary(const RetainSummary &Summ,
567                                       const CallEvent &CallOrMsg,
568                                       CheckerContext &C) const {
569   ProgramStateRef state = C.getState();
570 
571   // Evaluate the effect of the arguments.
572   RefVal::Kind hasErr = (RefVal::Kind) 0;
573   SourceRange ErrorRange;
574   SymbolRef ErrorSym = nullptr;
575 
576   // Helper tag for providing diagnostics: indicate whether dealloc was sent
577   // at this location.
578   bool DeallocSent = false;
579 
580   for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
581     SVal V = CallOrMsg.getArgSVal(idx);
582 
583     ArgEffect Effect = Summ.getArg(idx);
584     if (SymbolRef Sym = V.getAsLocSymbol()) {
585       if (const RefVal *T = getRefBinding(state, Sym)) {
586 
587         if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
588           Effect = ArgEffect(StopTrackingHard, ObjKind::OS);
589 
590         state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
591         if (hasErr) {
592           ErrorRange = CallOrMsg.getArgSourceRange(idx);
593           ErrorSym = Sym;
594           break;
595         } else if (Effect.getKind() == Dealloc) {
596           DeallocSent = true;
597         }
598       }
599     }
600   }
601 
602   // Evaluate the effect on the message receiver / `this` argument.
603   bool ReceiverIsTracked = false;
604   if (!hasErr) {
605     if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
606       if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
607         if (const RefVal *T = getRefBinding(state, Sym)) {
608           ReceiverIsTracked = true;
609           state = updateSymbol(state, Sym, *T,
610                                Summ.getReceiverEffect(), hasErr, C);
611           if (hasErr) {
612             ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
613             ErrorSym = Sym;
614           } else if (Summ.getReceiverEffect().getKind() == Dealloc) {
615             DeallocSent = true;
616           }
617         }
618       }
619     } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
620       if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
621         if (const RefVal *T = getRefBinding(state, Sym)) {
622           state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
623                                hasErr, C);
624           if (hasErr) {
625             ErrorRange = MCall->getOriginExpr()->getSourceRange();
626             ErrorSym = Sym;
627           }
628         }
629       }
630     }
631   }
632 
633   // Process any errors.
634   if (hasErr) {
635     processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
636     return;
637   }
638 
639   // Consult the summary for the return value.
640   RetEffect RE = Summ.getRetEffect();
641 
642   if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
643     if (ReceiverIsTracked)
644       RE = getSummaryManager(C).getObjAllocRetEffect();
645     else
646       RE = RetEffect::MakeNoRet();
647   }
648 
649   if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
650     QualType ResultTy = CallOrMsg.getResultType();
651     if (RE.notOwned()) {
652       const Expr *Ex = CallOrMsg.getOriginExpr();
653       assert(Ex);
654       ResultTy = GetReturnType(Ex, C.getASTContext());
655     }
656     if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
657       state = setRefBinding(state, Sym, *updatedRefVal);
658   }
659 
660   SmallVector<ProgramStateRef, 2> Out =
661       updateOutParameters(state, Summ, CallOrMsg);
662 
663   for (ProgramStateRef St : Out) {
664     if (DeallocSent) {
665       C.addTransition(St, C.getPredecessor(), &DeallocSentTag);
666     } else {
667       C.addTransition(St);
668     }
669   }
670 }
671 
672 ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state,
673                                                  SymbolRef sym, RefVal V,
674                                                  ArgEffect AE,
675                                                  RefVal::Kind &hasErr,
676                                                  CheckerContext &C) const {
677   bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
678   if (AE.getObjKind() == ObjKind::ObjC && IgnoreRetainMsg) {
679     switch (AE.getKind()) {
680     default:
681       break;
682     case IncRef:
683       AE = AE.withKind(DoNothing);
684       break;
685     case DecRef:
686       AE = AE.withKind(DoNothing);
687       break;
688     case DecRefAndStopTrackingHard:
689       AE = AE.withKind(StopTracking);
690       break;
691     }
692   }
693 
694   // Handle all use-after-releases.
695   if (V.getKind() == RefVal::Released) {
696     V = V ^ RefVal::ErrorUseAfterRelease;
697     hasErr = V.getKind();
698     return setRefBinding(state, sym, V);
699   }
700 
701   switch (AE.getKind()) {
702     case UnretainedOutParameter:
703     case RetainedOutParameter:
704     case RetainedOutParameterOnZero:
705     case RetainedOutParameterOnNonZero:
706       llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
707                        "not have ref state.");
708 
709     case Dealloc: // NB. we only need to add a note in a non-error case.
710       switch (V.getKind()) {
711         default:
712           llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
713         case RefVal::Owned:
714           // The object immediately transitions to the released state.
715           V = V ^ RefVal::Released;
716           V.clearCounts();
717           return setRefBinding(state, sym, V);
718         case RefVal::NotOwned:
719           V = V ^ RefVal::ErrorDeallocNotOwned;
720           hasErr = V.getKind();
721           break;
722       }
723       break;
724 
725     case MayEscape:
726       if (V.getKind() == RefVal::Owned) {
727         V = V ^ RefVal::NotOwned;
728         break;
729       }
730 
731       LLVM_FALLTHROUGH;
732 
733     case DoNothing:
734       return state;
735 
736     case Autorelease:
737       // Update the autorelease counts.
738       V = V.autorelease();
739       break;
740 
741     case StopTracking:
742     case StopTrackingHard:
743       return removeRefBinding(state, sym);
744 
745     case IncRef:
746       switch (V.getKind()) {
747         default:
748           llvm_unreachable("Invalid RefVal state for a retain.");
749         case RefVal::Owned:
750         case RefVal::NotOwned:
751           V = V + 1;
752           break;
753       }
754       break;
755 
756     case DecRef:
757     case DecRefBridgedTransferred:
758     case DecRefAndStopTrackingHard:
759       switch (V.getKind()) {
760         default:
761           // case 'RefVal::Released' handled above.
762           llvm_unreachable("Invalid RefVal state for a release.");
763 
764         case RefVal::Owned:
765           assert(V.getCount() > 0);
766           if (V.getCount() == 1) {
767             if (AE.getKind() == DecRefBridgedTransferred ||
768                 V.getIvarAccessHistory() ==
769                   RefVal::IvarAccessHistory::AccessedDirectly)
770               V = V ^ RefVal::NotOwned;
771             else
772               V = V ^ RefVal::Released;
773           } else if (AE.getKind() == DecRefAndStopTrackingHard) {
774             return removeRefBinding(state, sym);
775           }
776 
777           V = V - 1;
778           break;
779 
780         case RefVal::NotOwned:
781           if (V.getCount() > 0) {
782             if (AE.getKind() == DecRefAndStopTrackingHard)
783               return removeRefBinding(state, sym);
784             V = V - 1;
785           } else if (V.getIvarAccessHistory() ==
786                        RefVal::IvarAccessHistory::AccessedDirectly) {
787             // Assume that the instance variable was holding on the object at
788             // +1, and we just didn't know.
789             if (AE.getKind() == DecRefAndStopTrackingHard)
790               return removeRefBinding(state, sym);
791             V = V.releaseViaIvar() ^ RefVal::Released;
792           } else {
793             V = V ^ RefVal::ErrorReleaseNotOwned;
794             hasErr = V.getKind();
795           }
796           break;
797       }
798       break;
799   }
800   return setRefBinding(state, sym, V);
801 }
802 
803 const RefCountBug &
804 RetainCountChecker::errorKindToBugKind(RefVal::Kind ErrorKind,
805                                        SymbolRef Sym) const {
806   switch (ErrorKind) {
807     case RefVal::ErrorUseAfterRelease:
808       return useAfterRelease;
809     case RefVal::ErrorReleaseNotOwned:
810       return releaseNotOwned;
811     case RefVal::ErrorDeallocNotOwned:
812       if (Sym->getType()->getPointeeCXXRecordDecl())
813         return freeNotOwned;
814       return deallocNotOwned;
815     default:
816       llvm_unreachable("Unhandled error.");
817   }
818 }
819 
820 void RetainCountChecker::processNonLeakError(ProgramStateRef St,
821                                              SourceRange ErrorRange,
822                                              RefVal::Kind ErrorKind,
823                                              SymbolRef Sym,
824                                              CheckerContext &C) const {
825   // HACK: Ignore retain-count issues on values accessed through ivars,
826   // because of cases like this:
827   //   [_contentView retain];
828   //   [_contentView removeFromSuperview];
829   //   [self addSubview:_contentView]; // invalidates 'self'
830   //   [_contentView release];
831   if (const RefVal *RV = getRefBinding(St, Sym))
832     if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
833       return;
834 
835   ExplodedNode *N = C.generateErrorNode(St);
836   if (!N)
837     return;
838 
839   auto report = llvm::make_unique<RefCountReport>(
840       errorKindToBugKind(ErrorKind, Sym),
841       C.getASTContext().getLangOpts(), N, Sym);
842   report->addRange(ErrorRange);
843   C.emitReport(std::move(report));
844 }
845 
846 //===----------------------------------------------------------------------===//
847 // Handle the return values of retain-count-related functions.
848 //===----------------------------------------------------------------------===//
849 
850 bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
851   ProgramStateRef state = C.getState();
852   const FunctionDecl *FD = C.getCalleeDecl(CE);
853   if (!FD)
854     return false;
855 
856   RetainSummaryManager &SmrMgr = getSummaryManager(C);
857   QualType ResultTy = CE->getCallReturnType(C.getASTContext());
858 
859   // See if the function has 'rc_ownership_trusted_implementation'
860   // annotate attribute. If it does, we will not inline it.
861   bool hasTrustedImplementationAnnotation = false;
862 
863   const LocationContext *LCtx = C.getLocationContext();
864 
865   using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
866   Optional<BehaviorSummary> BSmr =
867       SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
868 
869   // See if it's one of the specific functions we know how to eval.
870   if (!BSmr)
871     return false;
872 
873   // Bind the return value.
874   if (BSmr == BehaviorSummary::Identity ||
875       BSmr == BehaviorSummary::IdentityOrZero ||
876       BSmr == BehaviorSummary::IdentityThis) {
877 
878     const Expr *BindReturnTo =
879         (BSmr == BehaviorSummary::IdentityThis)
880             ? cast<CXXMemberCallExpr>(CE)->getImplicitObjectArgument()
881             : CE->getArg(0);
882     SVal RetVal = state->getSVal(BindReturnTo, LCtx);
883 
884     // If the receiver is unknown or the function has
885     // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
886     // return value.
887     // FIXME: this branch is very strange.
888     if (RetVal.isUnknown() ||
889         (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
890       SValBuilder &SVB = C.getSValBuilder();
891       RetVal =
892           SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
893     }
894 
895     // Bind the value.
896     state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
897 
898     if (BSmr == BehaviorSummary::IdentityOrZero) {
899       // Add a branch where the output is zero.
900       ProgramStateRef NullOutputState = C.getState();
901 
902       // Assume that output is zero on the other branch.
903       NullOutputState = NullOutputState->BindExpr(
904           CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
905       C.addTransition(NullOutputState, &CastFailTag);
906 
907       // And on the original branch assume that both input and
908       // output are non-zero.
909       if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
910         state = state->assume(*L, /*Assumption=*/true);
911 
912     }
913   }
914 
915   C.addTransition(state);
916   return true;
917 }
918 
919 ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
920                                                  CheckerContext &C) const {
921   ExplodedNode *Pred = C.getPredecessor();
922 
923   // Only adjust the reference count if this is the top-level call frame,
924   // and not the result of inlining.  In the future, we should do
925   // better checking even for inlined calls, and see if they match
926   // with their expected semantics (e.g., the method should return a retained
927   // object, etc.).
928   if (!C.inTopFrame())
929     return Pred;
930 
931   if (!S)
932     return Pred;
933 
934   const Expr *RetE = S->getRetValue();
935   if (!RetE)
936     return Pred;
937 
938   ProgramStateRef state = C.getState();
939   SymbolRef Sym =
940     state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
941   if (!Sym)
942     return Pred;
943 
944   // Get the reference count binding (if any).
945   const RefVal *T = getRefBinding(state, Sym);
946   if (!T)
947     return Pred;
948 
949   // Change the reference count.
950   RefVal X = *T;
951 
952   switch (X.getKind()) {
953     case RefVal::Owned: {
954       unsigned cnt = X.getCount();
955       assert(cnt > 0);
956       X.setCount(cnt - 1);
957       X = X ^ RefVal::ReturnedOwned;
958       break;
959     }
960 
961     case RefVal::NotOwned: {
962       unsigned cnt = X.getCount();
963       if (cnt) {
964         X.setCount(cnt - 1);
965         X = X ^ RefVal::ReturnedOwned;
966       } else {
967         X = X ^ RefVal::ReturnedNotOwned;
968       }
969       break;
970     }
971 
972     default:
973       return Pred;
974   }
975 
976   // Update the binding.
977   state = setRefBinding(state, Sym, X);
978   Pred = C.addTransition(state);
979 
980   // At this point we have updated the state properly.
981   // Everything after this is merely checking to see if the return value has
982   // been over- or under-retained.
983 
984   // Did we cache out?
985   if (!Pred)
986     return nullptr;
987 
988   // Update the autorelease counts.
989   static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
990   state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
991 
992   // Have we generated a sink node?
993   if (!state)
994     return nullptr;
995 
996   // Get the updated binding.
997   T = getRefBinding(state, Sym);
998   assert(T);
999   X = *T;
1000 
1001   // Consult the summary of the enclosing method.
1002   RetainSummaryManager &Summaries = getSummaryManager(C);
1003   const Decl *CD = &Pred->getCodeDecl();
1004   RetEffect RE = RetEffect::MakeNoRet();
1005 
1006   // FIXME: What is the convention for blocks? Is there one?
1007   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
1008     const RetainSummary *Summ = Summaries.getMethodSummary(MD);
1009     RE = Summ->getRetEffect();
1010   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
1011     if (!isa<CXXMethodDecl>(FD)) {
1012       const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
1013       RE = Summ->getRetEffect();
1014     }
1015   }
1016 
1017   return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
1018 }
1019 
1020 ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
1021                                                   CheckerContext &C,
1022                                                   ExplodedNode *Pred,
1023                                                   RetEffect RE, RefVal X,
1024                                                   SymbolRef Sym,
1025                                                   ProgramStateRef state) const {
1026   // HACK: Ignore retain-count issues on values accessed through ivars,
1027   // because of cases like this:
1028   //   [_contentView retain];
1029   //   [_contentView removeFromSuperview];
1030   //   [self addSubview:_contentView]; // invalidates 'self'
1031   //   [_contentView release];
1032   if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1033     return Pred;
1034 
1035   // Any leaks or other errors?
1036   if (X.isReturnedOwned() && X.getCount() == 0) {
1037     if (RE.getKind() != RetEffect::NoRet) {
1038       if (!RE.isOwned()) {
1039 
1040         // The returning type is a CF, we expect the enclosing method should
1041         // return ownership.
1042         X = X ^ RefVal::ErrorLeakReturned;
1043 
1044         // Generate an error node.
1045         state = setRefBinding(state, Sym, X);
1046 
1047         static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
1048         ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
1049         if (N) {
1050           const LangOptions &LOpts = C.getASTContext().getLangOpts();
1051           auto R =
1052               llvm::make_unique<RefLeakReport>(leakAtReturn, LOpts, N, Sym, C);
1053           C.emitReport(std::move(R));
1054         }
1055         return N;
1056       }
1057     }
1058   } else if (X.isReturnedNotOwned()) {
1059     if (RE.isOwned()) {
1060       if (X.getIvarAccessHistory() ==
1061             RefVal::IvarAccessHistory::AccessedDirectly) {
1062         // Assume the method was trying to transfer a +1 reference from a
1063         // strong ivar to the caller.
1064         state = setRefBinding(state, Sym,
1065                               X.releaseViaIvar() ^ RefVal::ReturnedOwned);
1066       } else {
1067         // Trying to return a not owned object to a caller expecting an
1068         // owned object.
1069         state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
1070 
1071         static CheckerProgramPointTag
1072             ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
1073 
1074         ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
1075         if (N) {
1076           auto R = llvm::make_unique<RefCountReport>(
1077               returnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym);
1078           C.emitReport(std::move(R));
1079         }
1080         return N;
1081       }
1082     }
1083   }
1084   return Pred;
1085 }
1086 
1087 //===----------------------------------------------------------------------===//
1088 // Check various ways a symbol can be invalidated.
1089 //===----------------------------------------------------------------------===//
1090 
1091 void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
1092                                    CheckerContext &C) const {
1093   ProgramStateRef state = C.getState();
1094   const MemRegion *MR = loc.getAsRegion();
1095 
1096   // Find all symbols referenced by 'val' that we are tracking
1097   // and stop tracking them.
1098   if (MR && shouldEscapeRegion(MR)) {
1099     state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1100     C.addTransition(state);
1101   }
1102 }
1103 
1104 ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
1105                                                SVal Cond,
1106                                                bool Assumption) const {
1107   // FIXME: We may add to the interface of evalAssume the list of symbols
1108   //  whose assumptions have changed.  For now we just iterate through the
1109   //  bindings and check if any of the tracked symbols are NULL.  This isn't
1110   //  too bad since the number of symbols we will track in practice are
1111   //  probably small and evalAssume is only called at branches and a few
1112   //  other places.
1113   RefBindingsTy B = state->get<RefBindings>();
1114 
1115   if (B.isEmpty())
1116     return state;
1117 
1118   bool changed = false;
1119   RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1120   ConstraintManager &CMgr = state->getConstraintManager();
1121 
1122   for (auto &I : B) {
1123     // Check if the symbol is null stop tracking the symbol.
1124     ConditionTruthVal AllocFailed = CMgr.isNull(state, I.first);
1125     if (AllocFailed.isConstrainedTrue()) {
1126       changed = true;
1127       B = RefBFactory.remove(B, I.first);
1128     }
1129   }
1130 
1131   if (changed)
1132     state = state->set<RefBindings>(B);
1133 
1134   return state;
1135 }
1136 
1137 ProgramStateRef RetainCountChecker::checkRegionChanges(
1138     ProgramStateRef state, const InvalidatedSymbols *invalidated,
1139     ArrayRef<const MemRegion *> ExplicitRegions,
1140     ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
1141     const CallEvent *Call) const {
1142   if (!invalidated)
1143     return state;
1144 
1145   llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
1146 
1147   for (const MemRegion *I : ExplicitRegions)
1148     if (const SymbolicRegion *SR = I->StripCasts()->getAs<SymbolicRegion>())
1149       WhitelistedSymbols.insert(SR->getSymbol());
1150 
1151   for (SymbolRef sym : *invalidated) {
1152     if (WhitelistedSymbols.count(sym))
1153       continue;
1154     // Remove any existing reference-count binding.
1155     state = removeRefBinding(state, sym);
1156   }
1157   return state;
1158 }
1159 
1160 ProgramStateRef
1161 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
1162                                             ExplodedNode *Pred,
1163                                             const ProgramPointTag *Tag,
1164                                             CheckerContext &Ctx,
1165                                             SymbolRef Sym,
1166                                             RefVal V,
1167                                             const ReturnStmt *S) const {
1168   unsigned ACnt = V.getAutoreleaseCount();
1169 
1170   // No autorelease counts?  Nothing to be done.
1171   if (!ACnt)
1172     return state;
1173 
1174   unsigned Cnt = V.getCount();
1175 
1176   // FIXME: Handle sending 'autorelease' to already released object.
1177 
1178   if (V.getKind() == RefVal::ReturnedOwned)
1179     ++Cnt;
1180 
1181   // If we would over-release here, but we know the value came from an ivar,
1182   // assume it was a strong ivar that's just been relinquished.
1183   if (ACnt > Cnt &&
1184       V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
1185     V = V.releaseViaIvar();
1186     --ACnt;
1187   }
1188 
1189   if (ACnt <= Cnt) {
1190     if (ACnt == Cnt) {
1191       V.clearCounts();
1192       if (V.getKind() == RefVal::ReturnedOwned) {
1193         V = V ^ RefVal::ReturnedNotOwned;
1194       } else {
1195         V = V ^ RefVal::NotOwned;
1196       }
1197     } else {
1198       V.setCount(V.getCount() - ACnt);
1199       V.setAutoreleaseCount(0);
1200     }
1201     return setRefBinding(state, Sym, V);
1202   }
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     return state;
1212 
1213   // Woah!  More autorelease counts then retain counts left.
1214   // Emit hard error.
1215   V = V ^ RefVal::ErrorOverAutorelease;
1216   state = setRefBinding(state, Sym, V);
1217 
1218   ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1219   if (N) {
1220     SmallString<128> sbuf;
1221     llvm::raw_svector_ostream os(sbuf);
1222     os << "Object was autoreleased ";
1223     if (V.getAutoreleaseCount() > 1)
1224       os << V.getAutoreleaseCount() << " times but the object ";
1225     else
1226       os << "but ";
1227     os << "has a +" << V.getCount() << " retain count";
1228 
1229     const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1230     auto R = llvm::make_unique<RefCountReport>(overAutorelease, LOpts, N, Sym,
1231                                                os.str());
1232     Ctx.emitReport(std::move(R));
1233   }
1234 
1235   return nullptr;
1236 }
1237 
1238 ProgramStateRef
1239 RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
1240                                       SymbolRef sid, RefVal V,
1241                                     SmallVectorImpl<SymbolRef> &Leaked) const {
1242   bool hasLeak;
1243 
1244   // HACK: Ignore retain-count issues on values accessed through ivars,
1245   // because of cases like this:
1246   //   [_contentView retain];
1247   //   [_contentView removeFromSuperview];
1248   //   [self addSubview:_contentView]; // invalidates 'self'
1249   //   [_contentView release];
1250   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1251     hasLeak = false;
1252   else if (V.isOwned())
1253     hasLeak = true;
1254   else if (V.isNotOwned() || V.isReturnedOwned())
1255     hasLeak = (V.getCount() > 0);
1256   else
1257     hasLeak = false;
1258 
1259   if (!hasLeak)
1260     return removeRefBinding(state, sid);
1261 
1262   Leaked.push_back(sid);
1263   return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1264 }
1265 
1266 ExplodedNode *
1267 RetainCountChecker::processLeaks(ProgramStateRef state,
1268                                  SmallVectorImpl<SymbolRef> &Leaked,
1269                                  CheckerContext &Ctx,
1270                                  ExplodedNode *Pred) const {
1271   // Generate an intermediate node representing the leak point.
1272   ExplodedNode *N = Ctx.addTransition(state, Pred);
1273   const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1274 
1275   if (N) {
1276     for (SymbolRef L : Leaked) {
1277       const RefCountBug &BT = Pred ? leakWithinFunction : leakAtReturn;
1278       Ctx.emitReport(llvm::make_unique<RefLeakReport>(BT, LOpts, N, L, Ctx));
1279     }
1280   }
1281 
1282   return N;
1283 }
1284 
1285 static bool isISLObjectRef(QualType Ty) {
1286   return StringRef(Ty.getAsString()).startswith("isl_");
1287 }
1288 
1289 void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
1290   if (!Ctx.inTopFrame())
1291     return;
1292 
1293   RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
1294   const LocationContext *LCtx = Ctx.getLocationContext();
1295   const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
1296 
1297   if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
1298     return;
1299 
1300   ProgramStateRef state = Ctx.getState();
1301   const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
1302   ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1303 
1304   for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
1305     const ParmVarDecl *Param = FD->getParamDecl(idx);
1306     SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1307 
1308     QualType Ty = Param->getType();
1309     const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
1310     if (AE && AE->getKind() == DecRef && isISLObjectRef(Ty)) {
1311       state = setRefBinding(
1312           state, Sym, RefVal::makeOwned(ObjKind::Generalized, Ty));
1313     } else if (isISLObjectRef(Ty)) {
1314       state = setRefBinding(
1315           state, Sym,
1316           RefVal::makeNotOwned(ObjKind::Generalized, Ty));
1317     }
1318   }
1319 
1320   Ctx.addTransition(state);
1321 }
1322 
1323 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
1324                                           CheckerContext &Ctx) const {
1325   ExplodedNode *Pred = processReturn(RS, Ctx);
1326 
1327   // Created state cached out.
1328   if (!Pred) {
1329     return;
1330   }
1331 
1332   ProgramStateRef state = Pred->getState();
1333   RefBindingsTy B = state->get<RefBindings>();
1334 
1335   // Don't process anything within synthesized bodies.
1336   const LocationContext *LCtx = Pred->getLocationContext();
1337   if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1338     assert(!LCtx->inTopFrame());
1339     return;
1340   }
1341 
1342   for (auto &I : B) {
1343     state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1344                                     I.first, I.second);
1345     if (!state)
1346       return;
1347   }
1348 
1349   // If the current LocationContext has a parent, don't check for leaks.
1350   // We will do that later.
1351   // FIXME: we should instead check for imbalances of the retain/releases,
1352   // and suggest annotations.
1353   if (LCtx->getParent())
1354     return;
1355 
1356   B = state->get<RefBindings>();
1357   SmallVector<SymbolRef, 10> Leaked;
1358 
1359   for (auto &I : B)
1360     state = handleSymbolDeath(state, I.first, I.second, Leaked);
1361 
1362   processLeaks(state, Leaked, Ctx, Pred);
1363 }
1364 
1365 void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1366                                           CheckerContext &C) const {
1367   ExplodedNode *Pred = C.getPredecessor();
1368 
1369   ProgramStateRef state = C.getState();
1370   SmallVector<SymbolRef, 10> Leaked;
1371 
1372   // Update counts from autorelease pools
1373   for (const auto &I: state->get<RefBindings>()) {
1374     SymbolRef Sym = I.first;
1375     if (SymReaper.isDead(Sym)) {
1376       static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
1377       const RefVal &V = I.second;
1378       state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V);
1379       if (!state)
1380         return;
1381 
1382       // Fetch the new reference count from the state, and use it to handle
1383       // this symbol.
1384       state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked);
1385     }
1386   }
1387 
1388   if (Leaked.empty()) {
1389     C.addTransition(state);
1390     return;
1391   }
1392 
1393   Pred = processLeaks(state, Leaked, C, Pred);
1394 
1395   // Did we cache out?
1396   if (!Pred)
1397     return;
1398 
1399   // Now generate a new node that nukes the old bindings.
1400   // The only bindings left at this point are the leaked symbols.
1401   RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1402   RefBindingsTy B = state->get<RefBindings>();
1403 
1404   for (SymbolRef L : Leaked)
1405     B = F.remove(B, L);
1406 
1407   state = state->set<RefBindings>(B);
1408   C.addTransition(state, Pred);
1409 }
1410 
1411 void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
1412                                     const char *NL, const char *Sep) const {
1413 
1414   RefBindingsTy B = State->get<RefBindings>();
1415 
1416   if (B.isEmpty())
1417     return;
1418 
1419   Out << Sep << NL;
1420 
1421   for (auto &I : B) {
1422     Out << I.first << " : ";
1423     I.second.print(Out);
1424     Out << NL;
1425   }
1426 }
1427 
1428 //===----------------------------------------------------------------------===//
1429 // Checker registration.
1430 //===----------------------------------------------------------------------===//
1431 
1432 void ento::registerRetainCountChecker(CheckerManager &Mgr) {
1433   auto *Chk = Mgr.registerChecker<RetainCountChecker>();
1434   Chk->TrackObjCAndCFObjects = true;
1435 }
1436 
1437 // FIXME: remove this, hack for backwards compatibility:
1438 // it should be possible to enable the NS/CF retain count checker as
1439 // osx.cocoa.RetainCount, and it should be possible to disable
1440 // osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false.
1441 static bool hasPrevCheckOSObjectOptionDisabled(AnalyzerOptions &Options) {
1442   auto I = Options.Config.find("osx.cocoa.RetainCount:CheckOSObject");
1443   if (I != Options.Config.end())
1444     return I->getValue() == "false";
1445   return false;
1446 }
1447 
1448 void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
1449   auto *Chk = Mgr.registerChecker<RetainCountChecker>();
1450   if (!hasPrevCheckOSObjectOptionDisabled(Mgr.getAnalyzerOptions()))
1451     Chk->TrackOSObjects = true;
1452 }
1453