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