xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp (revision 5be959c88ed297705b0ec1debaf7ccaa8dfe0db8)
1 // RetainCountDiagnostics.cpp - Checks for leaks and other issues -*- C++ -*--//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines diagnostics for RetainCountChecker, which implements
11 //  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "RetainCountDiagnostics.h"
16 #include "RetainCountChecker.h"
17 
18 using namespace clang;
19 using namespace ento;
20 using namespace retaincountchecker;
21 
22 static bool isNumericLiteralExpression(const Expr *E) {
23   // FIXME: This set of cases was copied from SemaExprObjC.
24   return isa<IntegerLiteral>(E) ||
25          isa<CharacterLiteral>(E) ||
26          isa<FloatingLiteral>(E) ||
27          isa<ObjCBoolLiteralExpr>(E) ||
28          isa<CXXBoolLiteralExpr>(E);
29 }
30 
31 /// If type represents a pointer to CXXRecordDecl,
32 /// and is not a typedef, return the decl name.
33 /// Otherwise, return the serialization of type.
34 static std::string getPrettyTypeName(QualType QT) {
35   QualType PT = QT->getPointeeType();
36   if (!PT.isNull() && !QT->getAs<TypedefType>())
37     if (const auto *RD = PT->getAsCXXRecordDecl())
38       return RD->getName();
39   return QT.getAsString();
40 }
41 
42 /// Write information about the type state change to {@code os},
43 /// return whether the note should be generated.
44 static bool shouldGenerateNote(llvm::raw_string_ostream &os,
45                                const RefVal *PrevT, const RefVal &CurrV,
46                                bool DeallocSent) {
47   // Get the previous type state.
48   RefVal PrevV = *PrevT;
49 
50   // Specially handle -dealloc.
51   if (DeallocSent) {
52     // Determine if the object's reference count was pushed to zero.
53     assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
54     // We may not have transitioned to 'release' if we hit an error.
55     // This case is handled elsewhere.
56     if (CurrV.getKind() == RefVal::Released) {
57       assert(CurrV.getCombinedCounts() == 0);
58       os << "Object released by directly sending the '-dealloc' message";
59       return true;
60     }
61   }
62 
63   // Determine if the typestate has changed.
64   if (!PrevV.hasSameState(CurrV))
65     switch (CurrV.getKind()) {
66     case RefVal::Owned:
67     case RefVal::NotOwned:
68       if (PrevV.getCount() == CurrV.getCount()) {
69         // Did an autorelease message get sent?
70         if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
71           return false;
72 
73         assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
74         os << "Object autoreleased";
75         return true;
76       }
77 
78       if (PrevV.getCount() > CurrV.getCount())
79         os << "Reference count decremented.";
80       else
81         os << "Reference count incremented.";
82 
83       if (unsigned Count = CurrV.getCount())
84         os << " The object now has a +" << Count << " retain count.";
85 
86       return true;
87 
88     case RefVal::Released:
89       if (CurrV.getIvarAccessHistory() ==
90               RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
91           CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
92         os << "Strong instance variable relinquished. ";
93       }
94       os << "Object released.";
95       return true;
96 
97     case RefVal::ReturnedOwned:
98       // Autoreleases can be applied after marking a node ReturnedOwned.
99       if (CurrV.getAutoreleaseCount())
100         return false;
101 
102       os << "Object returned to caller as an owning reference (single "
103             "retain count transferred to caller)";
104       return true;
105 
106     case RefVal::ReturnedNotOwned:
107       os << "Object returned to caller with a +0 retain count";
108       return true;
109 
110     default:
111       return false;
112     }
113   return true;
114 }
115 
116 /// Finds argument index of the out paramter in the call {@code S}
117 /// corresponding to the symbol {@code Sym}.
118 /// If none found, returns None.
119 static Optional<unsigned> findArgIdxOfSymbol(ProgramStateRef CurrSt,
120                                              const LocationContext *LCtx,
121                                              SymbolRef &Sym,
122                                              Optional<CallEventRef<>> CE) {
123   if (!CE)
124     return None;
125 
126   for (unsigned Idx = 0; Idx < (*CE)->getNumArgs(); Idx++)
127     if (const MemRegion *MR = (*CE)->getArgSVal(Idx).getAsRegion())
128       if (const auto *TR = dyn_cast<TypedValueRegion>(MR))
129         if (CurrSt->getSVal(MR, TR->getValueType()).getAsSymExpr() == Sym)
130           return Idx;
131 
132   return None;
133 }
134 
135 static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
136                                            const LocationContext *LCtx,
137                                            const RefVal &CurrV, SymbolRef &Sym,
138                                            const Stmt *S,
139                                            llvm::raw_string_ostream &os) {
140   CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
141   if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
142     // Get the name of the callee (if it is available)
143     // from the tracked SVal.
144     SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
145     const FunctionDecl *FD = X.getAsFunctionDecl();
146 
147     // If failed, try to get it from AST.
148     if (!FD)
149       FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
150 
151     if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
152       os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
153     } else if (FD) {
154       os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
155     } else {
156       os << "function call";
157     }
158   } else if (isa<CXXNewExpr>(S)) {
159     os << "Operator 'new'";
160   } else {
161     assert(isa<ObjCMessageExpr>(S));
162     CallEventRef<ObjCMethodCall> Call =
163         Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
164 
165     switch (Call->getMessageKind()) {
166     case OCM_Message:
167       os << "Method";
168       break;
169     case OCM_PropertyAccess:
170       os << "Property";
171       break;
172     case OCM_Subscript:
173       os << "Subscript";
174       break;
175     }
176   }
177 
178   Optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx);
179   auto Idx = findArgIdxOfSymbol(CurrSt, LCtx, Sym, CE);
180 
181   // If index is not found, we assume that the symbol was returned.
182   if (!Idx) {
183     os << " returns ";
184   } else {
185     os << " writes ";
186   }
187 
188   if (CurrV.getObjKind() == ObjKind::CF) {
189     os << "a Core Foundation object of type '"
190        << Sym->getType().getAsString() << "' with a ";
191   } else if (CurrV.getObjKind() == ObjKind::OS) {
192     os << "an OSObject of type '" << getPrettyTypeName(Sym->getType())
193        << "' with a ";
194   } else if (CurrV.getObjKind() == ObjKind::Generalized) {
195     os << "an object of type '" << Sym->getType().getAsString()
196        << "' with a ";
197   } else {
198     assert(CurrV.getObjKind() == ObjKind::ObjC);
199     QualType T = Sym->getType();
200     if (!isa<ObjCObjectPointerType>(T)) {
201       os << "an Objective-C object with a ";
202     } else {
203       const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
204       os << "an instance of " << PT->getPointeeType().getAsString()
205          << " with a ";
206     }
207   }
208 
209   if (CurrV.isOwned()) {
210     os << "+1 retain count";
211   } else {
212     assert(CurrV.isNotOwned());
213     os << "+0 retain count";
214   }
215 
216   if (Idx) {
217     os << " into an out parameter '";
218     const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];
219     PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
220                               /*Qualified=*/false);
221     os << "'";
222 
223     QualType RT = (*CE)->getResultType();
224     if (!RT.isNull() && !RT->isVoidType()) {
225       SVal RV = (*CE)->getReturnValue();
226       if (CurrSt->isNull(RV).isConstrainedTrue()) {
227         os << " (assuming the call returns zero)";
228       } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {
229         os << " (assuming the call returns non-zero)";
230       }
231 
232     }
233   }
234 }
235 
236 namespace clang {
237 namespace ento {
238 namespace retaincountchecker {
239 
240 class RefCountReportVisitor : public BugReporterVisitor {
241 protected:
242   SymbolRef Sym;
243 
244 public:
245   RefCountReportVisitor(SymbolRef sym) : Sym(sym) {}
246 
247   void Profile(llvm::FoldingSetNodeID &ID) const override {
248     static int x = 0;
249     ID.AddPointer(&x);
250     ID.AddPointer(Sym);
251   }
252 
253   std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
254                                                  BugReporterContext &BRC,
255                                                  BugReport &BR) override;
256 
257   std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
258                                                   const ExplodedNode *N,
259                                                   BugReport &BR) override;
260 };
261 
262 class RefLeakReportVisitor : public RefCountReportVisitor {
263 public:
264   RefLeakReportVisitor(SymbolRef sym) : RefCountReportVisitor(sym) {}
265 
266   std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
267                                                   const ExplodedNode *N,
268                                                   BugReport &BR) override;
269 };
270 
271 } // end namespace retaincountchecker
272 } // end namespace ento
273 } // end namespace clang
274 
275 
276 /// Find the first node with the parent stack frame.
277 static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
278   const StackFrameContext *SC = Pred->getStackFrame();
279   if (SC->inTopFrame())
280     return nullptr;
281   const StackFrameContext *PC = SC->getParent()->getStackFrame();
282   if (!PC)
283     return nullptr;
284 
285   const ExplodedNode *N = Pred;
286   while (N && N->getStackFrame() != PC) {
287     N = N->getFirstPred();
288   }
289   return N;
290 }
291 
292 
293 /// Insert a diagnostic piece at function exit
294 /// if a function parameter is annotated as "os_consumed",
295 /// but it does not actually consume the reference.
296 static std::shared_ptr<PathDiagnosticEventPiece>
297 annotateConsumedSummaryMismatch(const ExplodedNode *N,
298                                 CallExitBegin &CallExitLoc,
299                                 const SourceManager &SM,
300                                 CallEventManager &CEMgr) {
301 
302   const ExplodedNode *CN = getCalleeNode(N);
303   if (!CN)
304     return nullptr;
305 
306   CallEventRef<> Call = CEMgr.getCaller(N->getStackFrame(), N->getState());
307 
308   std::string sbuf;
309   llvm::raw_string_ostream os(sbuf);
310   ArrayRef<const ParmVarDecl *> Parameters = Call->parameters();
311   for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {
312     const ParmVarDecl *PVD = Parameters[I];
313 
314     if (!PVD->hasAttr<OSConsumedAttr>())
315       continue;
316 
317     if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
318       const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
319       const RefVal *CountAtExit = getRefBinding(N->getState(), SR);
320 
321       if (!CountBeforeCall || !CountAtExit)
322         continue;
323 
324       unsigned CountBefore = CountBeforeCall->getCount();
325       unsigned CountAfter = CountAtExit->getCount();
326 
327       bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;
328       if (!AsExpected) {
329         os << "Parameter '";
330         PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
331                                   /*Qualified=*/false);
332         os << "' is marked as consuming, but the function did not consume "
333            << "the reference\n";
334       }
335     }
336   }
337 
338   if (os.str().empty())
339     return nullptr;
340 
341   // FIXME: remove the code duplication with NoStoreFuncVisitor.
342   PathDiagnosticLocation L;
343   if (const ReturnStmt *RS = CallExitLoc.getReturnStmt()) {
344     L = PathDiagnosticLocation::createBegin(RS, SM, N->getLocationContext());
345   } else {
346     L = PathDiagnosticLocation(
347         Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(), SM);
348   }
349 
350   return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
351 }
352 
353 std::shared_ptr<PathDiagnosticPiece>
354 RefCountReportVisitor::VisitNode(const ExplodedNode *N,
355                               BugReporterContext &BRC, BugReport &BR) {
356 
357   const SourceManager &SM = BRC.getSourceManager();
358   CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
359   if (auto CE = N->getLocationAs<CallExitBegin>())
360     if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
361       return PD;
362 
363   // FIXME: We will eventually need to handle non-statement-based events
364   // (__attribute__((cleanup))).
365   if (!N->getLocation().getAs<StmtPoint>())
366     return nullptr;
367 
368   // Check if the type state has changed.
369   const ExplodedNode *PrevNode = N->getFirstPred();
370   ProgramStateRef PrevSt = PrevNode->getState();
371   ProgramStateRef CurrSt = N->getState();
372   const LocationContext *LCtx = N->getLocationContext();
373 
374   const RefVal* CurrT = getRefBinding(CurrSt, Sym);
375   if (!CurrT) return nullptr;
376 
377   const RefVal &CurrV = *CurrT;
378   const RefVal *PrevT = getRefBinding(PrevSt, Sym);
379 
380   // Create a string buffer to constain all the useful things we want
381   // to tell the user.
382   std::string sbuf;
383   llvm::raw_string_ostream os(sbuf);
384 
385   // This is the allocation site since the previous node had no bindings
386   // for this symbol.
387   if (!PrevT) {
388     const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
389 
390     if (isa<ObjCIvarRefExpr>(S) &&
391         isSynthesizedAccessor(LCtx->getStackFrame())) {
392       S = LCtx->getStackFrame()->getCallSite();
393     }
394 
395     if (isa<ObjCArrayLiteral>(S)) {
396       os << "NSArray literal is an object with a +0 retain count";
397     } else if (isa<ObjCDictionaryLiteral>(S)) {
398       os << "NSDictionary literal is an object with a +0 retain count";
399     } else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
400       if (isNumericLiteralExpression(BL->getSubExpr()))
401         os << "NSNumber literal is an object with a +0 retain count";
402       else {
403         const ObjCInterfaceDecl *BoxClass = nullptr;
404         if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
405           BoxClass = Method->getClassInterface();
406 
407         // We should always be able to find the boxing class interface,
408         // but consider this future-proofing.
409         if (BoxClass) {
410           os << *BoxClass << " b";
411         } else {
412           os << "B";
413         }
414 
415         os << "oxed expression produces an object with a +0 retain count";
416       }
417     } else if (isa<ObjCIvarRefExpr>(S)) {
418       os << "Object loaded from instance variable";
419     } else {
420       generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
421     }
422 
423     PathDiagnosticLocation Pos(S, SM, N->getLocationContext());
424     return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
425   }
426 
427   // Gather up the effects that were performed on the object at this
428   // program point
429   bool DeallocSent = false;
430 
431   if (N->getLocation().getTag() &&
432       N->getLocation().getTag()->getTagDescription().contains(
433           RetainCountChecker::DeallocTagDescription)) {
434     // We only have summaries attached to nodes after evaluating CallExpr and
435     // ObjCMessageExprs.
436     const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
437 
438     if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
439       // Iterate through the parameter expressions and see if the symbol
440       // was ever passed as an argument.
441       unsigned i = 0;
442 
443       for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {
444 
445         // Retrieve the value of the argument.  Is it the symbol
446         // we are interested in?
447         if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
448           continue;
449 
450         // We have an argument.  Get the effect!
451         DeallocSent = true;
452       }
453     } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
454       if (const Expr *receiver = ME->getInstanceReceiver()) {
455         if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
456               .getAsLocSymbol() == Sym) {
457           // The symbol we are tracking is the receiver.
458           DeallocSent = true;
459         }
460       }
461     }
462   }
463 
464   if (!shouldGenerateNote(os, PrevT, CurrV, DeallocSent))
465     return nullptr;
466 
467   if (os.str().empty())
468     return nullptr; // We have nothing to say!
469 
470   const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
471   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
472                                 N->getLocationContext());
473   auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
474 
475   // Add the range by scanning the children of the statement for any bindings
476   // to Sym.
477   for (const Stmt *Child : S->children())
478     if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
479       if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
480         P->addRange(Exp->getSourceRange());
481         break;
482       }
483 
484   return std::move(P);
485 }
486 
487 static Optional<std::string> describeRegion(const MemRegion *MR) {
488   if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
489     return std::string(VR->getDecl()->getName());
490   // Once we support more storage locations for bindings,
491   // this would need to be improved.
492   return None;
493 }
494 
495 namespace {
496 // Find the first node in the current function context that referred to the
497 // tracked symbol and the memory location that value was stored to. Note, the
498 // value is only reported if the allocation occurred in the same function as
499 // the leak. The function can also return a location context, which should be
500 // treated as interesting.
501 struct AllocationInfo {
502   const ExplodedNode* N;
503   const MemRegion *R;
504   const LocationContext *InterestingMethodContext;
505   AllocationInfo(const ExplodedNode *InN,
506                  const MemRegion *InR,
507                  const LocationContext *InInterestingMethodContext) :
508     N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
509 };
510 } // end anonymous namespace
511 
512 static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
513                                         const ExplodedNode *N, SymbolRef Sym) {
514   const ExplodedNode *AllocationNode = N;
515   const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
516   const MemRegion *FirstBinding = nullptr;
517   const LocationContext *LeakContext = N->getLocationContext();
518 
519   // The location context of the init method called on the leaked object, if
520   // available.
521   const LocationContext *InitMethodContext = nullptr;
522 
523   while (N) {
524     ProgramStateRef St = N->getState();
525     const LocationContext *NContext = N->getLocationContext();
526 
527     if (!getRefBinding(St, Sym))
528       break;
529 
530     StoreManager::FindUniqueBinding FB(Sym);
531     StateMgr.iterBindings(St, FB);
532 
533     if (FB) {
534       const MemRegion *R = FB.getRegion();
535       // Do not show local variables belonging to a function other than
536       // where the error is reported.
537       if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace()))
538         if (MR->getStackFrame() == LeakContext->getStackFrame())
539           FirstBinding = R;
540     }
541 
542     // AllocationNode is the last node in which the symbol was tracked.
543     AllocationNode = N;
544 
545     // AllocationNodeInCurrentContext, is the last node in the current or
546     // parent context in which the symbol was tracked.
547     //
548     // Note that the allocation site might be in the parent context. For example,
549     // the case where an allocation happens in a block that captures a reference
550     // to it and that reference is overwritten/dropped by another call to
551     // the block.
552     if (NContext == LeakContext || NContext->isParentOf(LeakContext))
553       AllocationNodeInCurrentOrParentContext = N;
554 
555     // Find the last init that was called on the given symbol and store the
556     // init method's location context.
557     if (!InitMethodContext)
558       if (auto CEP = N->getLocation().getAs<CallEnter>()) {
559         const Stmt *CE = CEP->getCallExpr();
560         if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
561           const Stmt *RecExpr = ME->getInstanceReceiver();
562           if (RecExpr) {
563             SVal RecV = St->getSVal(RecExpr, NContext);
564             if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
565               InitMethodContext = CEP->getCalleeContext();
566           }
567         }
568       }
569 
570     N = N->getFirstPred();
571   }
572 
573   // If we are reporting a leak of the object that was allocated with alloc,
574   // mark its init method as interesting.
575   const LocationContext *InterestingMethodContext = nullptr;
576   if (InitMethodContext) {
577     const ProgramPoint AllocPP = AllocationNode->getLocation();
578     if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
579       if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
580         if (ME->getMethodFamily() == OMF_alloc)
581           InterestingMethodContext = InitMethodContext;
582   }
583 
584   // If allocation happened in a function different from the leak node context,
585   // do not report the binding.
586   assert(N && "Could not find allocation node");
587 
588   if (AllocationNodeInCurrentOrParentContext &&
589       AllocationNodeInCurrentOrParentContext->getLocationContext() !=
590           LeakContext)
591     FirstBinding = nullptr;
592 
593   return AllocationInfo(AllocationNodeInCurrentOrParentContext,
594                         FirstBinding,
595                         InterestingMethodContext);
596 }
597 
598 std::shared_ptr<PathDiagnosticPiece>
599 RefCountReportVisitor::getEndPath(BugReporterContext &BRC,
600                                const ExplodedNode *EndN, BugReport &BR) {
601   BR.markInteresting(Sym);
602   return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
603 }
604 
605 std::shared_ptr<PathDiagnosticPiece>
606 RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
607                                    const ExplodedNode *EndN, BugReport &BR) {
608 
609   // Tell the BugReporterContext to report cases when the tracked symbol is
610   // assigned to different variables, etc.
611   BR.markInteresting(Sym);
612 
613   // We are reporting a leak.  Walk up the graph to get to the first node where
614   // the symbol appeared, and also get the first VarDecl that tracked object
615   // is stored to.
616   AllocationInfo AllocI = GetAllocationSite(BRC.getStateManager(), EndN, Sym);
617 
618   const MemRegion* FirstBinding = AllocI.R;
619   BR.markInteresting(AllocI.InterestingMethodContext);
620 
621   SourceManager& SM = BRC.getSourceManager();
622 
623   // Compute an actual location for the leak.  Sometimes a leak doesn't
624   // occur at an actual statement (e.g., transition between blocks; end
625   // of function) so we need to walk the graph and compute a real location.
626   const ExplodedNode *LeakN = EndN;
627   PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
628 
629   std::string sbuf;
630   llvm::raw_string_ostream os(sbuf);
631 
632   os << "Object leaked: ";
633 
634   Optional<std::string> RegionDescription = describeRegion(FirstBinding);
635   if (RegionDescription) {
636     os << "object allocated and stored into '" << *RegionDescription << '\'';
637   } else {
638     os << "allocated object of type '" << getPrettyTypeName(Sym->getType())
639        << "'";
640   }
641 
642   // Get the retain count.
643   const RefVal* RV = getRefBinding(EndN->getState(), Sym);
644   assert(RV);
645 
646   if (RV->getKind() == RefVal::ErrorLeakReturned) {
647     // FIXME: Per comments in rdar://6320065, "create" only applies to CF
648     // objects.  Only "copy", "alloc", "retain" and "new" transfer ownership
649     // to the caller for NS objects.
650     const Decl *D = &EndN->getCodeDecl();
651 
652     os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
653                                   : " is returned from a function ");
654 
655     if (D->hasAttr<CFReturnsNotRetainedAttr>()) {
656       os << "that is annotated as CF_RETURNS_NOT_RETAINED";
657     } else if (D->hasAttr<NSReturnsNotRetainedAttr>()) {
658       os << "that is annotated as NS_RETURNS_NOT_RETAINED";
659     } else if (D->hasAttr<OSReturnsNotRetainedAttr>()) {
660       os << "that is annotated as OS_RETURNS_NOT_RETAINED";
661     } else {
662       if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
663         if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
664           os << "managed by Automatic Reference Counting";
665         } else {
666           os << "whose name ('" << MD->getSelector().getAsString()
667              << "') does not start with "
668                 "'copy', 'mutableCopy', 'alloc' or 'new'."
669                 "  This violates the naming convention rules"
670                 " given in the Memory Management Guide for Cocoa";
671         }
672       } else {
673         const FunctionDecl *FD = cast<FunctionDecl>(D);
674         os << "whose name ('" << *FD
675            << "') does not contain 'Copy' or 'Create'.  This violates the naming"
676               " convention rules given in the Memory Management Guide for Core"
677               " Foundation";
678       }
679     }
680   } else {
681     os << " is not referenced later in this execution path and has a retain "
682           "count of +" << RV->getCount();
683   }
684 
685   return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
686 }
687 
688 RefCountReport::RefCountReport(RefCountBug &D, const LangOptions &LOpts,
689                                ExplodedNode *n, SymbolRef sym,
690                                bool registerVisitor)
691     : BugReport(D, D.getDescription(), n), Sym(sym) {
692   if (registerVisitor)
693     addVisitor(llvm::make_unique<RefCountReportVisitor>(sym));
694 }
695 
696 RefCountReport::RefCountReport(RefCountBug &D, const LangOptions &LOpts,
697                                ExplodedNode *n, SymbolRef sym,
698                                StringRef endText)
699     : BugReport(D, D.getDescription(), endText, n) {
700 
701   addVisitor(llvm::make_unique<RefCountReportVisitor>(sym));
702 }
703 
704 void RefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
705   const SourceManager& SMgr = Ctx.getSourceManager();
706 
707   if (!sym->getOriginRegion())
708     return;
709 
710   auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
711   if (Region) {
712     const Decl *PDecl = Region->getDecl();
713     if (PDecl && isa<ParmVarDecl>(PDecl)) {
714       PathDiagnosticLocation ParamLocation =
715           PathDiagnosticLocation::create(PDecl, SMgr);
716       Location = ParamLocation;
717       UniqueingLocation = ParamLocation;
718       UniqueingDecl = Ctx.getLocationContext()->getDecl();
719     }
720   }
721 }
722 
723 void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx,
724                                           SymbolRef sym) {
725   // Most bug reports are cached at the location where they occurred.
726   // With leaks, we want to unique them by the location where they were
727   // allocated, and only report a single path.  To do this, we need to find
728   // the allocation site of a piece of tracked memory, which we do via a
729   // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
730   // Note that this is *not* the trimmed graph; we are guaranteed, however,
731   // that all ancestor nodes that represent the allocation site have the
732   // same SourceLocation.
733   const ExplodedNode *AllocNode = nullptr;
734 
735   const SourceManager& SMgr = Ctx.getSourceManager();
736 
737   AllocationInfo AllocI =
738       GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
739 
740   AllocNode = AllocI.N;
741   AllocBinding = AllocI.R;
742   markInteresting(AllocI.InterestingMethodContext);
743 
744   // Get the SourceLocation for the allocation site.
745   // FIXME: This will crash the analyzer if an allocation comes from an
746   // implicit call (ex: a destructor call).
747   // (Currently there are no such allocations in Cocoa, though.)
748   AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
749 
750   if (!AllocStmt) {
751     AllocBinding = nullptr;
752     return;
753   }
754 
755   PathDiagnosticLocation AllocLocation =
756     PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
757                                         AllocNode->getLocationContext());
758   Location = AllocLocation;
759 
760   // Set uniqieing info, which will be used for unique the bug reports. The
761   // leaks should be uniqued on the allocation site.
762   UniqueingLocation = AllocLocation;
763   UniqueingDecl = AllocNode->getLocationContext()->getDecl();
764 }
765 
766 void RefLeakReport::createDescription(CheckerContext &Ctx) {
767   assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
768   Description.clear();
769   llvm::raw_string_ostream os(Description);
770   os << "Potential leak of an object";
771 
772   Optional<std::string> RegionDescription = describeRegion(AllocBinding);
773   if (RegionDescription) {
774     os << " stored into '" << *RegionDescription << '\'';
775   } else {
776 
777     // If we can't figure out the name, just supply the type information.
778     os << " of type '" << getPrettyTypeName(Sym->getType()) << "'";
779   }
780 }
781 
782 RefLeakReport::RefLeakReport(RefCountBug &D, const LangOptions &LOpts,
783                              ExplodedNode *n, SymbolRef sym,
784                              CheckerContext &Ctx)
785     : RefCountReport(D, LOpts, n, sym, false) {
786 
787   deriveAllocLocation(Ctx, sym);
788   if (!AllocBinding)
789     deriveParamLocation(Ctx, sym);
790 
791   createDescription(Ctx);
792 
793   addVisitor(llvm::make_unique<RefLeakReportVisitor>(sym));
794 }
795