clang  15.0.0git
RetainCountDiagnostics.cpp
Go to the documentation of this file.
1 // RetainCountDiagnostics.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 diagnostics for RetainCountChecker, which implements
10 // a reference count checker for Core Foundation and Cocoa on (Mac OS X).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RetainCountDiagnostics.h"
15 #include "RetainCountChecker.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 
19 using namespace clang;
20 using namespace ento;
21 using namespace retaincountchecker;
22 
23 StringRef RefCountBug::bugTypeToName(RefCountBug::RefCountBugKind BT) {
24  switch (BT) {
25  case UseAfterRelease:
26  return "Use-after-release";
27  case ReleaseNotOwned:
28  return "Bad release";
29  case DeallocNotOwned:
30  return "-dealloc sent to non-exclusively owned object";
31  case FreeNotOwned:
32  return "freeing non-exclusively owned object";
33  case OverAutorelease:
34  return "Object autoreleased too many times";
36  return "Method should return an owned object";
37  case LeakWithinFunction:
38  return "Leak";
39  case LeakAtReturn:
40  return "Leak of returned object";
41  }
42  llvm_unreachable("Unknown RefCountBugKind");
43 }
44 
45 StringRef RefCountBug::getDescription() const {
46  switch (BT) {
47  case UseAfterRelease:
48  return "Reference-counted object is used after it is released";
49  case ReleaseNotOwned:
50  return "Incorrect decrement of the reference count of an object that is "
51  "not owned at this point by the caller";
52  case DeallocNotOwned:
53  return "-dealloc sent to object that may be referenced elsewhere";
54  case FreeNotOwned:
55  return "'free' called on an object that may be referenced elsewhere";
56  case OverAutorelease:
57  return "Object autoreleased too many times";
59  return "Object with a +0 retain count returned to caller where a +1 "
60  "(owning) retain count is expected";
61  case LeakWithinFunction:
62  case LeakAtReturn:
63  return "";
64  }
65  llvm_unreachable("Unknown RefCountBugKind");
66 }
67 
69  : BugType(Checker, bugTypeToName(BT), categories::MemoryRefCount,
70  /*SuppressOnSink=*/BT == LeakWithinFunction ||
71  BT == LeakAtReturn),
72  BT(BT) {}
73 
74 static bool isNumericLiteralExpression(const Expr *E) {
75  // FIXME: This set of cases was copied from SemaExprObjC.
78 }
79 
80 /// If type represents a pointer to CXXRecordDecl,
81 /// and is not a typedef, return the decl name.
82 /// Otherwise, return the serialization of type.
84  QualType PT = QT->getPointeeType();
85  if (!PT.isNull() && !QT->getAs<TypedefType>())
86  if (const auto *RD = PT->getAsCXXRecordDecl())
87  return std::string(RD->getName());
88  return QT.getAsString();
89 }
90 
91 /// Write information about the type state change to @c os,
92 /// return whether the note should be generated.
93 static bool shouldGenerateNote(llvm::raw_string_ostream &os,
94  const RefVal *PrevT,
95  const RefVal &CurrV,
96  bool DeallocSent) {
97  // Get the previous type state.
98  RefVal PrevV = *PrevT;
99 
100  // Specially handle -dealloc.
101  if (DeallocSent) {
102  // Determine if the object's reference count was pushed to zero.
103  assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
104  // We may not have transitioned to 'release' if we hit an error.
105  // This case is handled elsewhere.
106  if (CurrV.getKind() == RefVal::Released) {
107  assert(CurrV.getCombinedCounts() == 0);
108  os << "Object released by directly sending the '-dealloc' message";
109  return true;
110  }
111  }
112 
113  // Determine if the typestate has changed.
114  if (!PrevV.hasSameState(CurrV))
115  switch (CurrV.getKind()) {
116  case RefVal::Owned:
117  case RefVal::NotOwned:
118  if (PrevV.getCount() == CurrV.getCount()) {
119  // Did an autorelease message get sent?
120  if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
121  return false;
122 
123  assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
124  os << "Object autoreleased";
125  return true;
126  }
127 
128  if (PrevV.getCount() > CurrV.getCount())
129  os << "Reference count decremented.";
130  else
131  os << "Reference count incremented.";
132 
133  if (unsigned Count = CurrV.getCount())
134  os << " The object now has a +" << Count << " retain count.";
135 
136  return true;
137 
138  case RefVal::Released:
139  if (CurrV.getIvarAccessHistory() ==
141  CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
142  os << "Strong instance variable relinquished. ";
143  }
144  os << "Object released.";
145  return true;
146 
148  // Autoreleases can be applied after marking a node ReturnedOwned.
149  if (CurrV.getAutoreleaseCount())
150  return false;
151 
152  os << "Object returned to caller as an owning reference (single "
153  "retain count transferred to caller)";
154  return true;
155 
157  os << "Object returned to caller with a +0 retain count";
158  return true;
159 
160  default:
161  return false;
162  }
163  return true;
164 }
165 
166 /// Finds argument index of the out paramter in the call @c S
167 /// corresponding to the symbol @c Sym.
168 /// If none found, returns None.
170  const LocationContext *LCtx,
171  SymbolRef &Sym,
172  Optional<CallEventRef<>> CE) {
173  if (!CE)
174  return None;
175 
176  for (unsigned Idx = 0; Idx < (*CE)->getNumArgs(); Idx++)
177  if (const MemRegion *MR = (*CE)->getArgSVal(Idx).getAsRegion())
178  if (const auto *TR = dyn_cast<TypedValueRegion>(MR))
179  if (CurrSt->getSVal(MR, TR->getValueType()).getAsSymbol() == Sym)
180  return Idx;
181 
182  return None;
183 }
184 
186  if (const auto *ME = dyn_cast<MemberExpr>(Callee)) {
187  if (ME->getMemberDecl()->getNameAsString() != "alloc")
188  return None;
189  const Expr *This = ME->getBase()->IgnoreParenImpCasts();
190  if (const auto *DRE = dyn_cast<DeclRefExpr>(This)) {
191  const ValueDecl *VD = DRE->getDecl();
192  if (VD->getNameAsString() != "metaClass")
193  return None;
194 
195  if (const auto *RD = dyn_cast<CXXRecordDecl>(VD->getDeclContext()))
196  return RD->getNameAsString();
197 
198  }
199  }
200  return None;
201 }
202 
204  if (const auto *CE = dyn_cast<CallExpr>(S))
205  if (auto Out = findMetaClassAlloc(CE->getCallee()))
206  return *Out;
207  return getPrettyTypeName(QT);
208 }
209 
211  const LocationContext *LCtx,
212  const RefVal &CurrV, SymbolRef &Sym,
213  const Stmt *S,
214  llvm::raw_string_ostream &os) {
215  CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
216  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
217  // Get the name of the callee (if it is available)
218  // from the tracked SVal.
219  SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
220  const FunctionDecl *FD = X.getAsFunctionDecl();
221 
222  // If failed, try to get it from AST.
223  if (!FD)
224  FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
225 
226  if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
227  os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
228  } else if (FD) {
229  os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
230  } else {
231  os << "function call";
232  }
233  } else if (isa<CXXNewExpr>(S)) {
234  os << "Operator 'new'";
235  } else {
236  assert(isa<ObjCMessageExpr>(S));
238  Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
239 
240  switch (Call->getMessageKind()) {
241  case OCM_Message:
242  os << "Method";
243  break;
244  case OCM_PropertyAccess:
245  os << "Property";
246  break;
247  case OCM_Subscript:
248  os << "Subscript";
249  break;
250  }
251  }
252 
253  Optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx);
254  auto Idx = findArgIdxOfSymbol(CurrSt, LCtx, Sym, CE);
255 
256  // If index is not found, we assume that the symbol was returned.
257  if (!Idx) {
258  os << " returns ";
259  } else {
260  os << " writes ";
261  }
262 
263  if (CurrV.getObjKind() == ObjKind::CF) {
264  os << "a Core Foundation object of type '" << Sym->getType() << "' with a ";
265  } else if (CurrV.getObjKind() == ObjKind::OS) {
266  os << "an OSObject of type '" << findAllocatedObjectName(S, Sym->getType())
267  << "' with a ";
268  } else if (CurrV.getObjKind() == ObjKind::Generalized) {
269  os << "an object of type '" << Sym->getType() << "' with a ";
270  } else {
271  assert(CurrV.getObjKind() == ObjKind::ObjC);
272  QualType T = Sym->getType();
273  if (!isa<ObjCObjectPointerType>(T)) {
274  os << "an Objective-C object with a ";
275  } else {
276  const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
277  os << "an instance of " << PT->getPointeeType() << " with a ";
278  }
279  }
280 
281  if (CurrV.isOwned()) {
282  os << "+1 retain count";
283  } else {
284  assert(CurrV.isNotOwned());
285  os << "+0 retain count";
286  }
287 
288  if (Idx) {
289  os << " into an out parameter '";
290  const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];
292  /*Qualified=*/false);
293  os << "'";
294 
295  QualType RT = (*CE)->getResultType();
296  if (!RT.isNull() && !RT->isVoidType()) {
297  SVal RV = (*CE)->getReturnValue();
298  if (CurrSt->isNull(RV).isConstrainedTrue()) {
299  os << " (assuming the call returns zero)";
300  } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {
301  os << " (assuming the call returns non-zero)";
302  }
303 
304  }
305  }
306 }
307 
308 namespace clang {
309 namespace ento {
310 namespace retaincountchecker {
311 
313 protected:
315 
316 public:
317  RefCountReportVisitor(SymbolRef sym) : Sym(sym) {}
318 
319  void Profile(llvm::FoldingSetNodeID &ID) const override {
320  static int x = 0;
321  ID.AddPointer(&x);
322  ID.AddPointer(Sym);
323  }
324 
325  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
326  BugReporterContext &BRC,
327  PathSensitiveBugReport &BR) override;
328 
330  const ExplodedNode *N,
331  PathSensitiveBugReport &BR) override;
332 };
333 
335 public:
336  RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
337  : RefCountReportVisitor(Sym), LastBinding(LastBinding) {}
338 
340  const ExplodedNode *N,
341  PathSensitiveBugReport &BR) override;
342 
343 private:
344  const MemRegion *LastBinding;
345 };
346 
347 } // end namespace retaincountchecker
348 } // end namespace ento
349 } // end namespace clang
350 
351 
352 /// Find the first node with the parent stack frame.
353 static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
354  const StackFrameContext *SC = Pred->getStackFrame();
355  if (SC->inTopFrame())
356  return nullptr;
357  const StackFrameContext *PC = SC->getParent()->getStackFrame();
358  if (!PC)
359  return nullptr;
360 
361  const ExplodedNode *N = Pred;
362  while (N && N->getStackFrame() != PC) {
363  N = N->getFirstPred();
364  }
365  return N;
366 }
367 
368 
369 /// Insert a diagnostic piece at function exit
370 /// if a function parameter is annotated as "os_consumed",
371 /// but it does not actually consume the reference.
372 static std::shared_ptr<PathDiagnosticEventPiece>
374  CallExitBegin &CallExitLoc,
375  const SourceManager &SM,
376  CallEventManager &CEMgr) {
377 
378  const ExplodedNode *CN = getCalleeNode(N);
379  if (!CN)
380  return nullptr;
381 
382  CallEventRef<> Call = CEMgr.getCaller(N->getStackFrame(), N->getState());
383 
384  std::string sbuf;
385  llvm::raw_string_ostream os(sbuf);
386  ArrayRef<const ParmVarDecl *> Parameters = Call->parameters();
387  for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {
388  const ParmVarDecl *PVD = Parameters[I];
389 
390  if (!PVD->hasAttr<OSConsumedAttr>())
391  continue;
392 
393  if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
394  const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
395  const RefVal *CountAtExit = getRefBinding(N->getState(), SR);
396 
397  if (!CountBeforeCall || !CountAtExit)
398  continue;
399 
400  unsigned CountBefore = CountBeforeCall->getCount();
401  unsigned CountAfter = CountAtExit->getCount();
402 
403  bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;
404  if (!AsExpected) {
405  os << "Parameter '";
407  /*Qualified=*/false);
408  os << "' is marked as consuming, but the function did not consume "
409  << "the reference\n";
410  }
411  }
412  }
413 
414  if (os.str().empty())
415  return nullptr;
416 
418  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
419 }
420 
421 /// Annotate the parameter at the analysis entry point.
422 static std::shared_ptr<PathDiagnosticEventPiece>
424  const SourceManager &SM) {
425  auto PP = N->getLocationAs<BlockEdge>();
426  if (!PP)
427  return nullptr;
428 
429  const CFGBlock *Src = PP->getSrc();
430  const RefVal *CurrT = getRefBinding(N->getState(), Sym);
431 
432  if (&Src->getParent()->getEntry() != Src || !CurrT ||
433  getRefBinding(N->getFirstPred()->getState(), Sym))
434  return nullptr;
435 
436  const auto *VR = cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion());
437  const auto *PVD = cast<ParmVarDecl>(VR->getDecl());
439 
440  std::string s;
441  llvm::raw_string_ostream os(s);
442  os << "Parameter '" << PVD->getDeclName() << "' starts at +";
443  if (CurrT->getCount() == 1) {
444  os << "1, as it is marked as consuming";
445  } else {
446  assert(CurrT->getCount() == 0);
447  os << "0";
448  }
449  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
450 }
451 
455 
456  const auto &BT = static_cast<const RefCountBug&>(BR.getBugType());
457 
458  bool IsFreeUnowned = BT.getBugType() == RefCountBug::FreeNotOwned ||
459  BT.getBugType() == RefCountBug::DeallocNotOwned;
460 
461  const SourceManager &SM = BRC.getSourceManager();
463  if (auto CE = N->getLocationAs<CallExitBegin>())
464  if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
465  return PD;
466 
467  if (auto PD = annotateStartParameter(N, Sym, SM))
468  return PD;
469 
470  // FIXME: We will eventually need to handle non-statement-based events
471  // (__attribute__((cleanup))).
472  if (!N->getLocation().getAs<StmtPoint>())
473  return nullptr;
474 
475  // Check if the type state has changed.
476  const ExplodedNode *PrevNode = N->getFirstPred();
477  ProgramStateRef PrevSt = PrevNode->getState();
478  ProgramStateRef CurrSt = N->getState();
479  const LocationContext *LCtx = N->getLocationContext();
480 
481  const RefVal* CurrT = getRefBinding(CurrSt, Sym);
482  if (!CurrT)
483  return nullptr;
484 
485  const RefVal &CurrV = *CurrT;
486  const RefVal *PrevT = getRefBinding(PrevSt, Sym);
487 
488  // Create a string buffer to constain all the useful things we want
489  // to tell the user.
490  std::string sbuf;
491  llvm::raw_string_ostream os(sbuf);
492 
493  if (PrevT && IsFreeUnowned && CurrV.isNotOwned() && PrevT->isOwned()) {
494  os << "Object is now not exclusively owned";
496  return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
497  }
498 
499  // This is the allocation site since the previous node had no bindings
500  // for this symbol.
501  if (!PrevT) {
502  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
503 
504  if (isa<ObjCIvarRefExpr>(S) &&
506  S = LCtx->getStackFrame()->getCallSite();
507  }
508 
509  if (isa<ObjCArrayLiteral>(S)) {
510  os << "NSArray literal is an object with a +0 retain count";
511  } else if (isa<ObjCDictionaryLiteral>(S)) {
512  os << "NSDictionary literal is an object with a +0 retain count";
513  } else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
514  if (isNumericLiteralExpression(BL->getSubExpr()))
515  os << "NSNumber literal is an object with a +0 retain count";
516  else {
517  const ObjCInterfaceDecl *BoxClass = nullptr;
518  if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
519  BoxClass = Method->getClassInterface();
520 
521  // We should always be able to find the boxing class interface,
522  // but consider this future-proofing.
523  if (BoxClass) {
524  os << *BoxClass << " b";
525  } else {
526  os << "B";
527  }
528 
529  os << "oxed expression produces an object with a +0 retain count";
530  }
531  } else if (isa<ObjCIvarRefExpr>(S)) {
532  os << "Object loaded from instance variable";
533  } else {
534  generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
535  }
536 
538  return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
539  }
540 
541  // Gather up the effects that were performed on the object at this
542  // program point
543  bool DeallocSent = false;
544 
545  const ProgramPointTag *Tag = N->getLocation().getTag();
546 
547  if (Tag == &RetainCountChecker::getCastFailTag()) {
548  os << "Assuming dynamic cast returns null due to type mismatch";
549  }
550 
552  // We only have summaries attached to nodes after evaluating CallExpr and
553  // ObjCMessageExprs.
554  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
555 
556  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
557  // Iterate through the parameter expressions and see if the symbol
558  // was ever passed as an argument.
559  unsigned i = 0;
560 
561  for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {
562 
563  // Retrieve the value of the argument. Is it the symbol
564  // we are interested in?
565  if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
566  continue;
567 
568  // We have an argument. Get the effect!
569  DeallocSent = true;
570  }
571  } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
572  if (const Expr *receiver = ME->getInstanceReceiver()) {
573  if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
574  .getAsLocSymbol() == Sym) {
575  // The symbol we are tracking is the receiver.
576  DeallocSent = true;
577  }
578  }
579  }
580  }
581 
582  if (!shouldGenerateNote(os, PrevT, CurrV, DeallocSent))
583  return nullptr;
584 
585  if (os.str().empty())
586  return nullptr; // We have nothing to say!
587 
588  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
590  N->getLocationContext());
591  auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
592 
593  // Add the range by scanning the children of the statement for any bindings
594  // to Sym.
595  for (const Stmt *Child : S->children())
596  if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
597  if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
598  P->addRange(Exp->getSourceRange());
599  break;
600  }
601 
602  return std::move(P);
603 }
604 
606  if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
607  return std::string(VR->getDecl()->getName());
608  // Once we support more storage locations for bindings,
609  // this would need to be improved.
610  return None;
611 }
612 
614 
616  SymbolRef Sym;
617  Bindings &Result;
618 
619 public:
621  : Sym(Sym), Result(ToFill) {}
622 
624  SVal Val) override {
625  SymbolRef SymV = Val.getAsLocSymbol();
626  if (!SymV || SymV != Sym)
627  return true;
628 
629  if (isa<NonParamVarRegion>(R))
630  Result.emplace_back(R, Val);
631 
632  return true;
633  }
634 };
635 
637  const ExplodedNode *Node, SymbolRef Sym) {
638  Bindings Result;
639  VarBindingsCollector Collector{Sym, Result};
640  while (Result.empty() && Node) {
641  Manager.iterBindings(Node->getState(), Collector);
642  Node = Node->getFirstPred();
643  }
644 
645  return Result;
646 }
647 
648 namespace {
649 // Find the first node in the current function context that referred to the
650 // tracked symbol and the memory location that value was stored to. Note, the
651 // value is only reported if the allocation occurred in the same function as
652 // the leak. The function can also return a location context, which should be
653 // treated as interesting.
654 struct AllocationInfo {
655  const ExplodedNode* N;
656  const MemRegion *R;
657  const LocationContext *InterestingMethodContext;
658  AllocationInfo(const ExplodedNode *InN,
659  const MemRegion *InR,
660  const LocationContext *InInterestingMethodContext) :
661  N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
662 };
663 } // end anonymous namespace
664 
665 static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
666  const ExplodedNode *N, SymbolRef Sym) {
667  const ExplodedNode *AllocationNode = N;
668  const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
669  const MemRegion *FirstBinding = nullptr;
670  const LocationContext *LeakContext = N->getLocationContext();
671 
672  // The location context of the init method called on the leaked object, if
673  // available.
674  const LocationContext *InitMethodContext = nullptr;
675 
676  while (N) {
677  ProgramStateRef St = N->getState();
678  const LocationContext *NContext = N->getLocationContext();
679 
680  if (!getRefBinding(St, Sym))
681  break;
682 
684  StateMgr.iterBindings(St, FB);
685 
686  if (FB) {
687  const MemRegion *R = FB.getRegion();
688  // Do not show local variables belonging to a function other than
689  // where the error is reported.
690  if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace()))
691  if (MR->getStackFrame() == LeakContext->getStackFrame())
692  FirstBinding = R;
693  }
694 
695  // AllocationNode is the last node in which the symbol was tracked.
696  AllocationNode = N;
697 
698  // AllocationNodeInCurrentContext, is the last node in the current or
699  // parent context in which the symbol was tracked.
700  //
701  // Note that the allocation site might be in the parent context. For example,
702  // the case where an allocation happens in a block that captures a reference
703  // to it and that reference is overwritten/dropped by another call to
704  // the block.
705  if (NContext == LeakContext || NContext->isParentOf(LeakContext))
706  AllocationNodeInCurrentOrParentContext = N;
707 
708  // Find the last init that was called on the given symbol and store the
709  // init method's location context.
710  if (!InitMethodContext)
711  if (auto CEP = N->getLocation().getAs<CallEnter>()) {
712  const Stmt *CE = CEP->getCallExpr();
713  if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
714  const Stmt *RecExpr = ME->getInstanceReceiver();
715  if (RecExpr) {
716  SVal RecV = St->getSVal(RecExpr, NContext);
717  if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
718  InitMethodContext = CEP->getCalleeContext();
719  }
720  }
721  }
722 
723  N = N->getFirstPred();
724  }
725 
726  // If we are reporting a leak of the object that was allocated with alloc,
727  // mark its init method as interesting.
728  const LocationContext *InterestingMethodContext = nullptr;
729  if (InitMethodContext) {
730  const ProgramPoint AllocPP = AllocationNode->getLocation();
731  if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
732  if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
733  if (ME->getMethodFamily() == OMF_alloc)
734  InterestingMethodContext = InitMethodContext;
735  }
736 
737  // If allocation happened in a function different from the leak node context,
738  // do not report the binding.
739  assert(N && "Could not find allocation node");
740 
741  if (AllocationNodeInCurrentOrParentContext &&
742  AllocationNodeInCurrentOrParentContext->getLocationContext() !=
743  LeakContext)
744  FirstBinding = nullptr;
745 
746  return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,
747  InterestingMethodContext);
748 }
749 
752  const ExplodedNode *EndN,
754  BR.markInteresting(Sym);
755  return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
756 }
757 
760  const ExplodedNode *EndN,
762 
763  // Tell the BugReporterContext to report cases when the tracked symbol is
764  // assigned to different variables, etc.
765  BR.markInteresting(Sym);
766 
767  PathDiagnosticLocation L = cast<RefLeakReport>(BR).getEndOfPath();
768 
769  std::string sbuf;
770  llvm::raw_string_ostream os(sbuf);
771 
772  os << "Object leaked: ";
773 
774  Optional<std::string> RegionDescription = describeRegion(LastBinding);
775  if (RegionDescription) {
776  os << "object allocated and stored into '" << *RegionDescription << '\'';
777  } else {
778  os << "allocated object of type '" << getPrettyTypeName(Sym->getType())
779  << "'";
780  }
781 
782  // Get the retain count.
783  const RefVal *RV = getRefBinding(EndN->getState(), Sym);
784  assert(RV);
785 
786  if (RV->getKind() == RefVal::ErrorLeakReturned) {
787  // FIXME: Per comments in rdar://6320065, "create" only applies to CF
788  // objects. Only "copy", "alloc", "retain" and "new" transfer ownership
789  // to the caller for NS objects.
790  const Decl *D = &EndN->getCodeDecl();
791 
792  os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
793  : " is returned from a function ");
794 
795  if (D->hasAttr<CFReturnsNotRetainedAttr>()) {
796  os << "that is annotated as CF_RETURNS_NOT_RETAINED";
797  } else if (D->hasAttr<NSReturnsNotRetainedAttr>()) {
798  os << "that is annotated as NS_RETURNS_NOT_RETAINED";
799  } else if (D->hasAttr<OSReturnsNotRetainedAttr>()) {
800  os << "that is annotated as OS_RETURNS_NOT_RETAINED";
801  } else {
802  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
803  if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
804  os << "managed by Automatic Reference Counting";
805  } else {
806  os << "whose name ('" << MD->getSelector().getAsString()
807  << "') does not start with "
808  "'copy', 'mutableCopy', 'alloc' or 'new'."
809  " This violates the naming convention rules"
810  " given in the Memory Management Guide for Cocoa";
811  }
812  } else {
813  const FunctionDecl *FD = cast<FunctionDecl>(D);
814  ObjKind K = RV->getObjKind();
815  if (K == ObjKind::ObjC || K == ObjKind::CF) {
816  os << "whose name ('" << *FD
817  << "') does not contain 'Copy' or 'Create'. This violates the "
818  "naming"
819  " convention rules given in the Memory Management Guide for "
820  "Core"
821  " Foundation";
822  } else if (RV->getObjKind() == ObjKind::OS) {
823  std::string FuncName = FD->getNameAsString();
824  os << "whose name ('" << FuncName << "') starts with '"
825  << StringRef(FuncName).substr(0, 3) << "'";
826  }
827  }
828  }
829  } else {
830  os << " is not referenced later in this execution path and has a retain "
831  "count of +"
832  << RV->getCount();
833  }
834 
835  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
836 }
837 
839  ExplodedNode *n, SymbolRef sym, bool isLeak)
840  : PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym),
841  isLeak(isLeak) {
842  if (!isLeak)
843  addVisitor<RefCountReportVisitor>(sym);
844 }
845 
847  ExplodedNode *n, SymbolRef sym,
848  StringRef endText)
849  : PathSensitiveBugReport(D, D.getDescription(), endText, n) {
850 
851  addVisitor<RefCountReportVisitor>(sym);
852 }
853 
854 void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {
855  const SourceManager &SMgr = Ctx.getSourceManager();
856 
857  if (!Sym->getOriginRegion())
858  return;
859 
860  auto *Region = dyn_cast<DeclRegion>(Sym->getOriginRegion());
861  if (Region) {
862  const Decl *PDecl = Region->getDecl();
863  if (isa_and_nonnull<ParmVarDecl>(PDecl)) {
864  PathDiagnosticLocation ParamLocation =
865  PathDiagnosticLocation::create(PDecl, SMgr);
866  Location = ParamLocation;
867  UniqueingLocation = ParamLocation;
869  }
870  }
871 }
872 
873 void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
874  // Most bug reports are cached at the location where they occurred.
875  // With leaks, we want to unique them by the location where they were
876  // allocated, and only report a single path. To do this, we need to find
877  // the allocation site of a piece of tracked memory, which we do via a
878  // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
879  // Note that this is *not* the trimmed graph; we are guaranteed, however,
880  // that all ancestor nodes that represent the allocation site have the
881  // same SourceLocation.
882  const ExplodedNode *AllocNode = nullptr;
883 
884  const SourceManager &SMgr = Ctx.getSourceManager();
885 
886  AllocationInfo AllocI =
888 
889  AllocNode = AllocI.N;
890  AllocFirstBinding = AllocI.R;
891  markInteresting(AllocI.InterestingMethodContext);
892 
893  // Get the SourceLocation for the allocation site.
894  // FIXME: This will crash the analyzer if an allocation comes from an
895  // implicit call (ex: a destructor call).
896  // (Currently there are no such allocations in Cocoa, though.)
897  AllocStmt = AllocNode->getStmtForDiagnostics();
898 
899  if (!AllocStmt) {
900  AllocFirstBinding = nullptr;
901  return;
902  }
903 
905  AllocStmt, SMgr, AllocNode->getLocationContext());
906  Location = AllocLocation;
907 
908  // Set uniqieing info, which will be used for unique the bug reports. The
909  // leaks should be uniqued on the allocation site.
910  UniqueingLocation = AllocLocation;
911  UniqueingDecl = AllocNode->getLocationContext()->getDecl();
912 }
913 
914 void RefLeakReport::createDescription(CheckerContext &Ctx) {
915  assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
916  Description.clear();
917  llvm::raw_string_ostream os(Description);
918  os << "Potential leak of an object";
919 
920  Optional<std::string> RegionDescription =
921  describeRegion(AllocBindingToReport);
922  if (RegionDescription) {
923  os << " stored into '" << *RegionDescription << '\'';
924  } else {
925 
926  // If we can't figure out the name, just supply the type information.
927  os << " of type '" << getPrettyTypeName(Sym->getType()) << "'";
928  }
929 }
930 
931 void RefLeakReport::findBindingToReport(CheckerContext &Ctx,
932  ExplodedNode *Node) {
933  if (!AllocFirstBinding)
934  // If we don't have any bindings, we won't be able to find any
935  // better binding to report.
936  return;
937 
938  // If the original region still contains the leaking symbol...
939  if (Node->getState()->getSVal(AllocFirstBinding).getAsSymbol() == Sym) {
940  // ...it is the best binding to report.
941  AllocBindingToReport = AllocFirstBinding;
942  return;
943  }
944 
945  // At this point, we know that the original region doesn't contain the leaking
946  // when the actual leak happens. It means that it can be confusing for the
947  // user to see such description in the message.
948  //
949  // Let's consider the following example:
950  // Object *Original = allocate(...);
951  // Object *New = Original;
952  // Original = allocate(...);
953  // Original->release();
954  //
955  // Complaining about a leaking object "stored into Original" might cause a
956  // rightful confusion because 'Original' is actually released.
957  // We should complain about 'New' instead.
958  Bindings AllVarBindings =
960 
961  // While looking for the last var bindings, we can still find
962  // `AllocFirstBinding` to be one of them. In situations like this,
963  // it would still be the easiest case to explain to our users.
964  if (!AllVarBindings.empty() &&
965  llvm::count_if(AllVarBindings,
966  [this](const std::pair<const MemRegion *, SVal> Binding) {
967  return Binding.first == AllocFirstBinding;
968  }) == 0) {
969  // Let's pick one of them at random (if there is something to pick from).
970  AllocBindingToReport = AllVarBindings[0].first;
971 
972  // Because 'AllocBindingToReport' is not the the same as
973  // 'AllocFirstBinding', we need to explain how the leaking object
974  // got from one to another.
975  //
976  // NOTE: We use the actual SVal stored in AllocBindingToReport here because
977  // trackStoredValue compares SVal's and it can get trickier for
978  // something like derived regions if we want to construct SVal from
979  // Sym. Instead, we take the value that is definitely stored in that
980  // region, thus guaranteeing that trackStoredValue will work.
981  bugreporter::trackStoredValue(AllVarBindings[0].second.castAs<KnownSVal>(),
982  AllocBindingToReport, *this);
983  } else {
984  AllocBindingToReport = AllocFirstBinding;
985  }
986 }
987 
989  ExplodedNode *N, SymbolRef Sym,
990  CheckerContext &Ctx)
991  : RefCountReport(D, LOpts, N, Sym, /*isLeak=*/true) {
992 
993  deriveAllocLocation(Ctx);
994  findBindingToReport(Ctx, N);
995 
996  if (!AllocFirstBinding)
997  deriveParamLocation(Ctx);
998 
999  createDescription(Ctx);
1000 
1001  addVisitor<RefLeakReportVisitor>(Sym, AllocBindingToReport);
1002 }
clang::CallExitBegin
Represents a point when we start the call exit sequence (for inlined call).
Definition: ProgramPoint.h:667
clang::ObjCInterfaceDecl
Represents an ObjC class declaration.
Definition: DeclObjC.h:1150
VarBindingsCollector::HandleBinding
bool HandleBinding(StoreManager &SMgr, Store Store, const MemRegion *R, SVal Val) override
Definition: RetainCountDiagnostics.cpp:623
clang::ento::retaincountchecker::RefCountReportVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: RetainCountDiagnostics.cpp:319
clang::ento::retaincountchecker::RefLeakReportVisitor
Definition: RetainCountDiagnostics.cpp:334
annotateConsumedSummaryMismatch
static std::shared_ptr< PathDiagnosticEventPiece > annotateConsumedSummaryMismatch(const ExplodedNode *N, CallExitBegin &CallExitLoc, const SourceManager &SM, CallEventManager &CEMgr)
Insert a diagnostic piece at function exit if a function parameter is annotated as "os_consumed",...
Definition: RetainCountDiagnostics.cpp:373
clang::Decl::getASTContext
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:414
generateDiagnosticsForCallLike
static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt, const LocationContext *LCtx, const RefVal &CurrV, SymbolRef &Sym, const Stmt *S, llvm::raw_string_ostream &os)
Definition: RetainCountDiagnostics.cpp:210
clang::ento::PathSensitiveBugReport::UniqueingLocation
PathDiagnosticLocation UniqueingLocation
Reports with different uniqueing locations are considered to be different for the purposes of dedupli...
Definition: BugReporter.h:355
getCalleeNode
static const ExplodedNode * getCalleeNode(const ExplodedNode *Pred)
Find the first node with the parent stack frame.
Definition: RetainCountDiagnostics.cpp:353
clang::ObjCBoxedExpr
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:128
clang::ento::CallEventManager::getCall
CallEventRef getCall(const Stmt *S, ProgramStateRef State, const LocationContext *LC)
Gets a call event for a function call, Objective-C method call, a 'new', or a 'delete' call.
Definition: CallEvent.cpp:1413
clang::ento::PathDiagnosticLocation
Definition: PathDiagnostic.h:195
clang::CXXBoolLiteralExpr
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition: ExprCXX.h:721
clang::ento::ObjKind::CF
@ CF
Indicates that the tracked object is a CF object.
clang::ento::ExplodedNode::getLocationContext
const LocationContext * getLocationContext() const
Definition: ExplodedGraph.h:146
clang::ento::CallEventRef
Definition: CallEvent.h:81
clang::ento::retaincountchecker::RefCountReportVisitor
Definition: RetainCountDiagnostics.cpp:312
clang::LocationContext
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
Definition: AnalysisDeclContext.h:215
clang::ento::OCM_Subscript
@ OCM_Subscript
Definition: CallEvent.h:1111
clang::LocationContext::getStackFrame
const StackFrameContext * getStackFrame() const
Definition: AnalysisDeclContext.cpp:463
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::Decl::hasAttr
bool hasAttr() const
Definition: DeclBase.h:542
clang::ento::PathDiagnosticPieceRef
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
Definition: PathDiagnostic.h:492
clang::ento::retaincountchecker::RetainCountChecker::getDeallocSentTag
static const CheckerProgramPointTag & getDeallocSentTag()
Definition: RetainCountChecker.h:363
describeRegion
static Optional< std::string > describeRegion(const MemRegion *MR)
Definition: RetainCountDiagnostics.cpp:605
clang::ento::ObjKind
ObjKind
Determines the object kind of a tracked object.
Definition: RetainSummaryManager.h:35
clang::ProgramPointTag
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
Definition: ProgramPoint.h:38
llvm::SmallVector
Definition: LLVM.h:38
clang::ento::retaincountchecker::RefCountBug::RefCountBugKind
RefCountBugKind
Definition: RetainCountDiagnostics.h:29
clang::ento::CheckerContext::getLocationContext
const LocationContext * getLocationContext() const
Definition: CheckerContext.h:93
findAllocatedObjectName
static std::string findAllocatedObjectName(const Stmt *S, QualType QT)
Definition: RetainCountDiagnostics.cpp:203
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:731
clang::ento::CallEventManager::getObjCMethodCall
CallEventRef< ObjCMethodCall > getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, const LocationContext *LCtx)
Definition: CallEvent.h:1302
clang::OMF_init
@ OMF_init
Definition: IdentifierTable.h:700
clang::ento::ExplodedNode::getStackFrame
const StackFrameContext * getStackFrame() const
Definition: ExplodedGraph.h:150
clang::ento::ExplodedNode
Definition: ExplodedGraph.h:65
clang::ParmVarDecl
Represents a parameter to a function.
Definition: Decl.h:1680
clang::ObjCObjectPointerType::getPointeeType
QualType getPointeeType() const
Gets the type pointed to by this ObjC pointer.
Definition: Type.h:6219
llvm::Optional< unsigned >
clang::QualType::getAsString
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:1079
isNumericLiteralExpression
static bool isNumericLiteralExpression(const Expr *E)
Definition: RetainCountDiagnostics.cpp:74
clang::StackFrameContext
It represents a stack frame of the call stack (based on CallEvent).
Definition: AnalysisDeclContext.h:299
clang::ento::retaincountchecker::RefVal::isOwned
bool isOwned() const
Definition: RetainCountChecker.h:152
clang::Type::isVoidType
bool isVoidType() const
Definition: Type.h:7096
clang::ento::retaincountchecker::RefVal::ErrorLeakReturned
@ ErrorLeakReturned
Definition: RetainCountChecker.h:65
clang::ento::retaincountchecker::RefLeakReport::RefLeakReport
RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n, SymbolRef sym, CheckerContext &Ctx)
Definition: RetainCountDiagnostics.cpp:988
clang::tooling::X
static ToolExecutorPluginRegistry::Add< AllTUsToolExecutorPlugin > X("all-TUs", "Runs FrontendActions on all TUs in the compilation database. " "Tool results are stored in memory.")
clang::ento::BugReporterVisitor
BugReporterVisitors are used to add custom diagnostics along a path.
Definition: BugReporterVisitors.h:48
RetainCountDiagnostics.h
clang::NamedDecl::getNameForDiagnostic
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition: Decl.cpp:1748
clang::ento::Store
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
Definition: StoreRef.h:27
clang::ento::retaincountchecker::RefCountReport::Sym
SymbolRef Sym
Definition: RetainCountDiagnostics.h:51
clang::ento::StoreManager
Definition: Store.h:53
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:627
clang::ento::retaincountchecker::getRefBinding
const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)
Definition: RetainCountChecker.cpp:28
clang::ento::retaincountchecker::RefLeakReportVisitor::getEndPath
PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR) override
Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...
Definition: RetainCountDiagnostics.cpp:759
clang::ObjCBoolLiteralExpr
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
Definition: ExprObjC.h:88
VarBindingsCollector
Definition: RetainCountDiagnostics.cpp:615
clang::TypedefType
Definition: Type.h:4464
clang::ento::MemRegion
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:95
clang::CFGBlock
Represents a single basic block in a source-level CFG.
Definition: CFG.h:576
clang::StackFrameContext::inTopFrame
bool inTopFrame() const override
Definition: AnalysisDeclContext.h:329
clang::ento::SVal::getAsLocSymbol
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:68
clang::IntegerLiteral
Definition: Expr.h:1494
clang::ento::ExplodedNode::getState
const ProgramStateRef & getState() const
Definition: ExplodedGraph.h:168
clang::ento::OCM_PropertyAccess
@ OCM_PropertyAccess
Definition: CallEvent.h:1110
clang::FloatingLiteral
Definition: Expr.h:1639
clang::ento::retaincountchecker::RefCountReport::RefCountReport
RefCountReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n, SymbolRef sym, bool isLeak=false)
findArgIdxOfSymbol
static Optional< unsigned > findArgIdxOfSymbol(ProgramStateRef CurrSt, const LocationContext *LCtx, SymbolRef &Sym, Optional< CallEventRef<>> CE)
Finds argument index of the out paramter in the call S corresponding to the symbol Sym.
Definition: RetainCountDiagnostics.cpp:169
clang::StmtPoint
Definition: ProgramPoint.h:270
clang::ento::SymExpr::getType
virtual QualType getType() const =0
Node
DynTypedNode Node
Definition: ASTMatchFinder.cpp:68
clang::ento::PathDiagnosticLocation::create
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
Definition: PathDiagnostic.h:248
clang::ento::SymExpr::getOriginRegion
virtual const MemRegion * getOriginRegion() const
Find the region from which this symbol originates.
Definition: SymExpr.h:102
clang::ento::retaincountchecker::RefVal::getCount
unsigned getCount() const
Definition: RetainCountChecker.h:127
clang::ento::retaincountchecker::RefCountBug::LeakAtReturn
@ LeakAtReturn
Definition: RetainCountDiagnostics.h:37
clang::ento::retaincountchecker::RefCountBug::DeallocNotOwned
@ DeallocNotOwned
Definition: RetainCountDiagnostics.h:32
clang::ento::BugReporterContext::getSourceManager
const SourceManager & getSourceManager() const
Definition: BugReporter.h:721
clang::ento::retaincountchecker::RefCountBug::FreeNotOwned
@ FreeNotOwned
Definition: RetainCountDiagnostics.h:33
clang::ProgramPoint::getAs
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
clang::ento::SymExpr
Symbolic value.
Definition: SymExpr.h:29
clang::ProgramPoint::getTag
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:176
clang::ento::PathDiagnosticLocation::isValid
bool isValid() const
Definition: PathDiagnostic.h:335
clang::ento::retaincountchecker::RefVal::Owned
@ Owned
Definition: RetainCountChecker.h:54
clang::Type::getAs
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7302
clang::ento::PathSensitiveBugReport::getErrorNode
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:402
clang::ento::BugType
Definition: BugType.h:27
clang::LocationContext::isParentOf
bool isParentOf(const LocationContext *LC) const
Definition: AnalysisDeclContext.cpp:477
clang::ento::retaincountchecker::RefVal::getKind
Kind getKind() const
Definition: RetainCountChecker.h:121
clang::isa
bool isa(CodeGen::Address addr)
Definition: Address.h:177
clang::ProgramPoint::castAs
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.
Definition: ProgramPoint.h:139
findMetaClassAlloc
static Optional< std::string > findMetaClassAlloc(const Expr *Callee)
Definition: RetainCountDiagnostics.cpp:185
clang::ento::CheckerNameRef
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
Definition: CheckerManager.h:106
clang::CFGBlock::getParent
CFG * getParent() const
Definition: CFG.h:1076
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:625
clang::ento::BugReporterContext
Definition: BugReporter.h:701
clang::Type::getAsCXXRecordDecl
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1759
clang::ento::categories::MemoryRefCount
const char *const MemoryRefCount
Definition: CommonBugCategories.cpp:18
clang::ento::retaincountchecker::RefCountBug::OverAutorelease
@ OverAutorelease
Definition: RetainCountDiagnostics.h:34
shouldGenerateNote
static bool shouldGenerateNote(llvm::raw_string_ostream &os, const RefVal *PrevT, const RefVal &CurrV, bool DeallocSent)
Write information about the type state change to os, return whether the note should be generated.
Definition: RetainCountDiagnostics.cpp:93
clang::ento::CheckerContext::getStateManager
ProgramStateManager & getStateManager()
Definition: CheckerContext.h:122
clang::ento::CheckerContext::getSourceManager
const SourceManager & getSourceManager()
Definition: CheckerContext.h:108
clang::ento::CallEventManager::getCaller
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
Definition: CallEvent.cpp:1360
clang::ento::KnownSVal
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:255
clang::ento::retaincountchecker::RefCountBug::getBugType
RefCountBugKind getBugType() const
Definition: RetainCountDiagnostics.h:42
x
IRgen optimization opportunities The common pattern of short x
Definition: README.txt:7
clang::ento::retaincountchecker::RefCountReportVisitor::VisitNode
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
Definition: RetainCountDiagnostics.cpp:453
clang::ObjCMessageExpr
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:940
getAllVarBindingsForSymbol
Bindings getAllVarBindingsForSymbol(ProgramStateManager &Manager, const ExplodedNode *Node, SymbolRef Sym)
Definition: RetainCountDiagnostics.cpp:636
clang::ento::retaincountchecker::RefCountReport
Definition: RetainCountDiagnostics.h:49
clang::ento::retaincountchecker::RefLeakReportVisitor::RefLeakReportVisitor
RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
Definition: RetainCountDiagnostics.cpp:336
clang::CharacterLiteral
Definition: Expr.h:1584
RetainCountChecker.h
clang::ento::StoreManager::FindUniqueBinding::getRegion
const MemRegion * getRegion()
Definition: Store.h:273
clang::LocationContext::getParent
const LocationContext * getParent() const
It might return null.
Definition: AnalysisDeclContext.h:247
clang::ObjCObjectPointerType
Represents a pointer to an Objective C object.
Definition: Type.h:6207
clang::ento::retaincountchecker::isSynthesizedAccessor
bool isSynthesizedAccessor(const StackFrameContext *SFC)
Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...
Definition: RetainCountChecker.h:384
clang::ento::retaincountchecker::RefVal::IvarAccessHistory::ReleasedAfterDirectAccess
@ ReleasedAfterDirectAccess
clang::ento::MemRegion::getMemorySpace
const LLVM_ATTRIBUTE_RETURNS_NONNULL MemSpaceRegion * getMemorySpace() const
Definition: MemRegion.cpp:1257
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::ento::retaincountchecker::RefCountBug::ReturnNotOwnedForOwned
@ ReturnNotOwnedForOwned
Definition: RetainCountDiagnostics.h:35
clang::ento::CallEventManager
Manages the lifetime of CallEvent objects.
Definition: CallEvent.h:1233
clang::ento::BugReport::Description
std::string Description
Definition: BugReporter.h:130
clang::ento::ProgramStateManager
Definition: ProgramState.h:503
clang::ValueDecl
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:674
clang::ento::ProgramStateManager::getCallEventManager
CallEventManager & getCallEventManager()
Definition: ProgramState.h:577
GetAllocationSite
static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym)
Definition: RetainCountDiagnostics.cpp:665
clang::ASTContext::getPrintingPolicy
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:708
clang::ento::ExplodedNode::getFirstPred
ExplodedNode * getFirstPred()
Definition: ExplodedGraph.h:208
clang::QualType::isNull
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:796
llvm::ArrayRef
Definition: LLVM.h:34
clang::ento::ObjKind::Generalized
@ Generalized
Indicates that the tracked object is a generalized object.
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
clang::StackFrameContext::getCallSite
const Stmt * getCallSite() const
Definition: AnalysisDeclContext.h:325
VarBindingsCollector::VarBindingsCollector
VarBindingsCollector(SymbolRef Sym, Bindings &ToFill)
Definition: RetainCountDiagnostics.cpp:620
clang::ento::ObjKind::ObjC
@ ObjC
Indicates that the tracked object is an Objective-C object.
clang::ento::bugreporter::trackStoredValue
void trackStoredValue(KnownSVal V, const MemRegion *R, PathSensitiveBugReport &Report, TrackingOptions Opts={}, const StackFrameContext *Origin=nullptr)
Track how the value got stored into the given region and where it came from.
clang::ento::retaincountchecker::RefCountReportVisitor::Sym
SymbolRef Sym
Definition: RetainCountDiagnostics.cpp:314
clang::ento::retaincountchecker::RefVal
Metadata on reference.
Definition: RetainCountChecker.h:51
clang::CFG::getEntry
CFGBlock & getEntry()
Definition: CFG.h:1331
clang::ento::retaincountchecker::RefVal::ReturnedNotOwned
@ ReturnedNotOwned
Definition: RetainCountChecker.h:58
clang::NamedDecl::getQualifiedNameAsString
std::string getQualifiedNameAsString() const
Definition: Decl.cpp:1605
clang::ento::retaincountchecker::RefVal::NotOwned
@ NotOwned
Definition: RetainCountChecker.h:55
clang::NamedDecl::getNameAsString
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:290
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:78
clang::ento::retaincountchecker::RefCountReportVisitor::getEndPath
PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR) override
Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...
Definition: RetainCountDiagnostics.cpp:751
clang::ento::StoreManager::BindingsHandler
Definition: Store.h:252
clang::ento::PathSensitiveBugReport
Definition: BugReporter.h:289
clang::ObjCMethodDecl
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
getPrettyTypeName
static std::string getPrettyTypeName(QualType QT)
If type represents a pointer to CXXRecordDecl, and is not a typedef, return the decl name.
Definition: RetainCountDiagnostics.cpp:83
clang::interp::This
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:829
clang::ento::OCM_Message
@ OCM_Message
Definition: CallEvent.h:1112
clang::Builtin::ID
ID
Definition: Builtins.h:52
clang::ento::BugReporterVisitor::getDefaultEndPath
static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N, const PathSensitiveBugReport &BR)
Generates the default final diagnostic piece.
Definition: BugReporterVisitors.cpp:334
clang
Definition: CalledOnceCheck.h:17
clang::ento::ExplodedNode::getLocation
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
Definition: ExplodedGraph.h:144
clang::ento::PathSensitiveBugReport::UniqueingDecl
const Decl * UniqueingDecl
Definition: BugReporter.h:356
clang::ento::ExplodedNode::getLocationAs
Optional< T > getLocationAs() const &
Definition: ExplodedGraph.h:170
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:69
clang::ento::retaincountchecker::RefCountBug::UseAfterRelease
@ UseAfterRelease
Definition: RetainCountDiagnostics.h:30
clang::OMF_alloc
@ OMF_alloc
Definition: IdentifierTable.h:698
clang::ento::retaincountchecker::RefVal::getObjKind
ObjKind getObjKind() const
Definition: RetainCountChecker.h:123
clang::ento::PathDiagnosticLocation::createBegin
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Definition: PathDiagnostic.cpp:580
s
__device__ __2f16 float bool s
Definition: __clang_hip_libdevice_declares.h:315
clang::ento::retaincountchecker::RefCountBug
Definition: RetainCountDiagnostics.h:27
clang::ento::PathSensitiveBugReport::markInteresting
void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)
Marks a symbol as interesting.
clang::ento::retaincountchecker::RefVal::isNotOwned
bool isNotOwned() const
Definition: RetainCountChecker.h:156
clang::ento::ExplodedNode::getStmtForDiagnostics
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
Definition: ExplodedGraph.cpp:320
clang::ento::CheckerContext
Definition: CheckerContext.h:23
clang::CallEnter
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:629
clang::BlockEdge
Definition: ProgramPoint.h:502
clang::ento::retaincountchecker::RefCountBug::RefCountBug
RefCountBug(CheckerNameRef Checker, RefCountBugKind BT)
Definition: RetainCountDiagnostics.cpp:68
clang::ento::Checker
Definition: Checker.h:517
clang::ento::SVal
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:74
clang::ento::retaincountchecker::RefVal::ReturnedOwned
@ ReturnedOwned
Definition: RetainCountChecker.h:57
clang::ento::ExplodedNode::getCodeDecl
const Decl & getCodeDecl() const
Definition: ExplodedGraph.h:154
true
#define true
Definition: stdbool.h:21
clang::ento::StoreManager::FindUniqueBinding
Definition: Store.h:261
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::ento::SVal::getAsSymbol
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:104
SM
#define SM(sm)
Definition: Cuda.cpp:81
clang::ento::retaincountchecker::RefCountBug::ReleaseNotOwned
@ ReleaseNotOwned
Definition: RetainCountDiagnostics.h:31
clang::ento::retaincountchecker::RefCountReportVisitor::RefCountReportVisitor
RefCountReportVisitor(SymbolRef sym)
Definition: RetainCountDiagnostics.cpp:317
clang::ento::BugReporterContext::getASTContext
ASTContext & getASTContext() const
Definition: BugReporter.h:717
clang::ento::retaincountchecker::RefCountBug::LeakWithinFunction
@ LeakWithinFunction
Definition: RetainCountDiagnostics.h:36
annotateStartParameter
static std::shared_ptr< PathDiagnosticEventPiece > annotateStartParameter(const ExplodedNode *N, SymbolRef Sym, const SourceManager &SM)
Annotate the parameter at the analysis entry point.
Definition: RetainCountDiagnostics.cpp:423
clang::ento::BugReporterContext::getStateManager
ProgramStateManager & getStateManager() const
Definition: BugReporter.h:713
clang::ento::BugReport::getBugType
const BugType & getBugType() const
Definition: BugReporter.h:149
clang::LocationContext::getDecl
const Decl * getDecl() const
Definition: AnalysisDeclContext.h:251
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1872
clang::ProgramPoint
Definition: ProgramPoint.h:58
clang::CallExpr
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2801
clang::ento::retaincountchecker::RetainCountChecker::getCastFailTag
static const CheckerProgramPointTag & getCastFailTag()
Definition: RetainCountChecker.h:367
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:786
llvm::IntrusiveRefCntPtr< const ProgramState >
clang::ento::ProgramStateManager::iterBindings
void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)
Definition: ProgramState.h:600
clang::ento::retaincountchecker::RefCountBug::getDescription
StringRef getDescription() const
Definition: RetainCountDiagnostics.cpp:45
clang::ento::ObjKind::OS
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
clang::ento::retaincountchecker::RefVal::Released
@ Released
Definition: RetainCountChecker.h:56
clang::Decl::getDeclContext
DeclContext * getDeclContext()
Definition: DeclBase.h:434