clang  14.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 '"
265  << Sym->getType().getAsString() << "' with a ";
266  } else if (CurrV.getObjKind() == ObjKind::OS) {
267  os << "an OSObject of type '" << findAllocatedObjectName(S, Sym->getType())
268  << "' with a ";
269  } else if (CurrV.getObjKind() == ObjKind::Generalized) {
270  os << "an object of type '" << Sym->getType().getAsString()
271  << "' with a ";
272  } else {
273  assert(CurrV.getObjKind() == ObjKind::ObjC);
274  QualType T = Sym->getType();
275  if (!isa<ObjCObjectPointerType>(T)) {
276  os << "an Objective-C object with a ";
277  } else {
278  const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
279  os << "an instance of " << PT->getPointeeType().getAsString()
280  << " with a ";
281  }
282  }
283 
284  if (CurrV.isOwned()) {
285  os << "+1 retain count";
286  } else {
287  assert(CurrV.isNotOwned());
288  os << "+0 retain count";
289  }
290 
291  if (Idx) {
292  os << " into an out parameter '";
293  const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];
295  /*Qualified=*/false);
296  os << "'";
297 
298  QualType RT = (*CE)->getResultType();
299  if (!RT.isNull() && !RT->isVoidType()) {
300  SVal RV = (*CE)->getReturnValue();
301  if (CurrSt->isNull(RV).isConstrainedTrue()) {
302  os << " (assuming the call returns zero)";
303  } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {
304  os << " (assuming the call returns non-zero)";
305  }
306 
307  }
308  }
309 }
310 
311 namespace clang {
312 namespace ento {
313 namespace retaincountchecker {
314 
316 protected:
318 
319 public:
320  RefCountReportVisitor(SymbolRef sym) : Sym(sym) {}
321 
322  void Profile(llvm::FoldingSetNodeID &ID) const override {
323  static int x = 0;
324  ID.AddPointer(&x);
325  ID.AddPointer(Sym);
326  }
327 
328  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
329  BugReporterContext &BRC,
330  PathSensitiveBugReport &BR) override;
331 
333  const ExplodedNode *N,
334  PathSensitiveBugReport &BR) override;
335 };
336 
338 public:
339  RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
340  : RefCountReportVisitor(Sym), LastBinding(LastBinding) {}
341 
343  const ExplodedNode *N,
344  PathSensitiveBugReport &BR) override;
345 
346 private:
347  const MemRegion *LastBinding;
348 };
349 
350 } // end namespace retaincountchecker
351 } // end namespace ento
352 } // end namespace clang
353 
354 
355 /// Find the first node with the parent stack frame.
356 static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
357  const StackFrameContext *SC = Pred->getStackFrame();
358  if (SC->inTopFrame())
359  return nullptr;
360  const StackFrameContext *PC = SC->getParent()->getStackFrame();
361  if (!PC)
362  return nullptr;
363 
364  const ExplodedNode *N = Pred;
365  while (N && N->getStackFrame() != PC) {
366  N = N->getFirstPred();
367  }
368  return N;
369 }
370 
371 
372 /// Insert a diagnostic piece at function exit
373 /// if a function parameter is annotated as "os_consumed",
374 /// but it does not actually consume the reference.
375 static std::shared_ptr<PathDiagnosticEventPiece>
377  CallExitBegin &CallExitLoc,
378  const SourceManager &SM,
379  CallEventManager &CEMgr) {
380 
381  const ExplodedNode *CN = getCalleeNode(N);
382  if (!CN)
383  return nullptr;
384 
385  CallEventRef<> Call = CEMgr.getCaller(N->getStackFrame(), N->getState());
386 
387  std::string sbuf;
388  llvm::raw_string_ostream os(sbuf);
389  ArrayRef<const ParmVarDecl *> Parameters = Call->parameters();
390  for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {
391  const ParmVarDecl *PVD = Parameters[I];
392 
393  if (!PVD->hasAttr<OSConsumedAttr>())
394  continue;
395 
396  if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
397  const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
398  const RefVal *CountAtExit = getRefBinding(N->getState(), SR);
399 
400  if (!CountBeforeCall || !CountAtExit)
401  continue;
402 
403  unsigned CountBefore = CountBeforeCall->getCount();
404  unsigned CountAfter = CountAtExit->getCount();
405 
406  bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;
407  if (!AsExpected) {
408  os << "Parameter '";
410  /*Qualified=*/false);
411  os << "' is marked as consuming, but the function did not consume "
412  << "the reference\n";
413  }
414  }
415  }
416 
417  if (os.str().empty())
418  return nullptr;
419 
421  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
422 }
423 
424 /// Annotate the parameter at the analysis entry point.
425 static std::shared_ptr<PathDiagnosticEventPiece>
427  const SourceManager &SM) {
428  auto PP = N->getLocationAs<BlockEdge>();
429  if (!PP)
430  return nullptr;
431 
432  const CFGBlock *Src = PP->getSrc();
433  const RefVal *CurrT = getRefBinding(N->getState(), Sym);
434 
435  if (&Src->getParent()->getEntry() != Src || !CurrT ||
436  getRefBinding(N->getFirstPred()->getState(), Sym))
437  return nullptr;
438 
439  const auto *VR = cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion());
440  const auto *PVD = cast<ParmVarDecl>(VR->getDecl());
442 
443  std::string s;
444  llvm::raw_string_ostream os(s);
445  os << "Parameter '" << PVD->getDeclName() << "' starts at +";
446  if (CurrT->getCount() == 1) {
447  os << "1, as it is marked as consuming";
448  } else {
449  assert(CurrT->getCount() == 0);
450  os << "0";
451  }
452  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
453 }
454 
458 
459  const auto &BT = static_cast<const RefCountBug&>(BR.getBugType());
460 
461  bool IsFreeUnowned = BT.getBugType() == RefCountBug::FreeNotOwned ||
462  BT.getBugType() == RefCountBug::DeallocNotOwned;
463 
464  const SourceManager &SM = BRC.getSourceManager();
466  if (auto CE = N->getLocationAs<CallExitBegin>())
467  if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
468  return PD;
469 
470  if (auto PD = annotateStartParameter(N, Sym, SM))
471  return PD;
472 
473  // FIXME: We will eventually need to handle non-statement-based events
474  // (__attribute__((cleanup))).
475  if (!N->getLocation().getAs<StmtPoint>())
476  return nullptr;
477 
478  // Check if the type state has changed.
479  const ExplodedNode *PrevNode = N->getFirstPred();
480  ProgramStateRef PrevSt = PrevNode->getState();
481  ProgramStateRef CurrSt = N->getState();
482  const LocationContext *LCtx = N->getLocationContext();
483 
484  const RefVal* CurrT = getRefBinding(CurrSt, Sym);
485  if (!CurrT)
486  return nullptr;
487 
488  const RefVal &CurrV = *CurrT;
489  const RefVal *PrevT = getRefBinding(PrevSt, Sym);
490 
491  // Create a string buffer to constain all the useful things we want
492  // to tell the user.
493  std::string sbuf;
494  llvm::raw_string_ostream os(sbuf);
495 
496  if (PrevT && IsFreeUnowned && CurrV.isNotOwned() && PrevT->isOwned()) {
497  os << "Object is now not exclusively owned";
499  return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
500  }
501 
502  // This is the allocation site since the previous node had no bindings
503  // for this symbol.
504  if (!PrevT) {
505  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
506 
507  if (isa<ObjCIvarRefExpr>(S) &&
509  S = LCtx->getStackFrame()->getCallSite();
510  }
511 
512  if (isa<ObjCArrayLiteral>(S)) {
513  os << "NSArray literal is an object with a +0 retain count";
514  } else if (isa<ObjCDictionaryLiteral>(S)) {
515  os << "NSDictionary literal is an object with a +0 retain count";
516  } else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
517  if (isNumericLiteralExpression(BL->getSubExpr()))
518  os << "NSNumber literal is an object with a +0 retain count";
519  else {
520  const ObjCInterfaceDecl *BoxClass = nullptr;
521  if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
522  BoxClass = Method->getClassInterface();
523 
524  // We should always be able to find the boxing class interface,
525  // but consider this future-proofing.
526  if (BoxClass) {
527  os << *BoxClass << " b";
528  } else {
529  os << "B";
530  }
531 
532  os << "oxed expression produces an object with a +0 retain count";
533  }
534  } else if (isa<ObjCIvarRefExpr>(S)) {
535  os << "Object loaded from instance variable";
536  } else {
537  generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
538  }
539 
541  return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
542  }
543 
544  // Gather up the effects that were performed on the object at this
545  // program point
546  bool DeallocSent = false;
547 
548  const ProgramPointTag *Tag = N->getLocation().getTag();
549 
550  if (Tag == &RetainCountChecker::getCastFailTag()) {
551  os << "Assuming dynamic cast returns null due to type mismatch";
552  }
553 
555  // We only have summaries attached to nodes after evaluating CallExpr and
556  // ObjCMessageExprs.
557  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
558 
559  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
560  // Iterate through the parameter expressions and see if the symbol
561  // was ever passed as an argument.
562  unsigned i = 0;
563 
564  for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {
565 
566  // Retrieve the value of the argument. Is it the symbol
567  // we are interested in?
568  if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
569  continue;
570 
571  // We have an argument. Get the effect!
572  DeallocSent = true;
573  }
574  } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
575  if (const Expr *receiver = ME->getInstanceReceiver()) {
576  if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
577  .getAsLocSymbol() == Sym) {
578  // The symbol we are tracking is the receiver.
579  DeallocSent = true;
580  }
581  }
582  }
583  }
584 
585  if (!shouldGenerateNote(os, PrevT, CurrV, DeallocSent))
586  return nullptr;
587 
588  if (os.str().empty())
589  return nullptr; // We have nothing to say!
590 
591  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
593  N->getLocationContext());
594  auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
595 
596  // Add the range by scanning the children of the statement for any bindings
597  // to Sym.
598  for (const Stmt *Child : S->children())
599  if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
600  if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
601  P->addRange(Exp->getSourceRange());
602  break;
603  }
604 
605  return std::move(P);
606 }
607 
609  if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
610  return std::string(VR->getDecl()->getName());
611  // Once we support more storage locations for bindings,
612  // this would need to be improved.
613  return None;
614 }
615 
617 
619  SymbolRef Sym;
620  Bindings &Result;
621 
622 public:
624  : Sym(Sym), Result(ToFill) {}
625 
627  SVal Val) override {
628  SymbolRef SymV = Val.getAsLocSymbol();
629  if (!SymV || SymV != Sym)
630  return true;
631 
632  if (isa<NonParamVarRegion>(R))
633  Result.emplace_back(R, Val);
634 
635  return true;
636  }
637 };
638 
640  const ExplodedNode *Node, SymbolRef Sym) {
641  Bindings Result;
642  VarBindingsCollector Collector{Sym, Result};
643  while (Result.empty() && Node) {
644  Manager.iterBindings(Node->getState(), Collector);
645  Node = Node->getFirstPred();
646  }
647 
648  return Result;
649 }
650 
651 namespace {
652 // Find the first node in the current function context that referred to the
653 // tracked symbol and the memory location that value was stored to. Note, the
654 // value is only reported if the allocation occurred in the same function as
655 // the leak. The function can also return a location context, which should be
656 // treated as interesting.
657 struct AllocationInfo {
658  const ExplodedNode* N;
659  const MemRegion *R;
660  const LocationContext *InterestingMethodContext;
661  AllocationInfo(const ExplodedNode *InN,
662  const MemRegion *InR,
663  const LocationContext *InInterestingMethodContext) :
664  N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
665 };
666 } // end anonymous namespace
667 
668 static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
669  const ExplodedNode *N, SymbolRef Sym) {
670  const ExplodedNode *AllocationNode = N;
671  const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
672  const MemRegion *FirstBinding = nullptr;
673  const LocationContext *LeakContext = N->getLocationContext();
674 
675  // The location context of the init method called on the leaked object, if
676  // available.
677  const LocationContext *InitMethodContext = nullptr;
678 
679  while (N) {
680  ProgramStateRef St = N->getState();
681  const LocationContext *NContext = N->getLocationContext();
682 
683  if (!getRefBinding(St, Sym))
684  break;
685 
687  StateMgr.iterBindings(St, FB);
688 
689  if (FB) {
690  const MemRegion *R = FB.getRegion();
691  // Do not show local variables belonging to a function other than
692  // where the error is reported.
693  if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace()))
694  if (MR->getStackFrame() == LeakContext->getStackFrame())
695  FirstBinding = R;
696  }
697 
698  // AllocationNode is the last node in which the symbol was tracked.
699  AllocationNode = N;
700 
701  // AllocationNodeInCurrentContext, is the last node in the current or
702  // parent context in which the symbol was tracked.
703  //
704  // Note that the allocation site might be in the parent context. For example,
705  // the case where an allocation happens in a block that captures a reference
706  // to it and that reference is overwritten/dropped by another call to
707  // the block.
708  if (NContext == LeakContext || NContext->isParentOf(LeakContext))
709  AllocationNodeInCurrentOrParentContext = N;
710 
711  // Find the last init that was called on the given symbol and store the
712  // init method's location context.
713  if (!InitMethodContext)
714  if (auto CEP = N->getLocation().getAs<CallEnter>()) {
715  const Stmt *CE = CEP->getCallExpr();
716  if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
717  const Stmt *RecExpr = ME->getInstanceReceiver();
718  if (RecExpr) {
719  SVal RecV = St->getSVal(RecExpr, NContext);
720  if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
721  InitMethodContext = CEP->getCalleeContext();
722  }
723  }
724  }
725 
726  N = N->getFirstPred();
727  }
728 
729  // If we are reporting a leak of the object that was allocated with alloc,
730  // mark its init method as interesting.
731  const LocationContext *InterestingMethodContext = nullptr;
732  if (InitMethodContext) {
733  const ProgramPoint AllocPP = AllocationNode->getLocation();
734  if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
735  if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
736  if (ME->getMethodFamily() == OMF_alloc)
737  InterestingMethodContext = InitMethodContext;
738  }
739 
740  // If allocation happened in a function different from the leak node context,
741  // do not report the binding.
742  assert(N && "Could not find allocation node");
743 
744  if (AllocationNodeInCurrentOrParentContext &&
745  AllocationNodeInCurrentOrParentContext->getLocationContext() !=
746  LeakContext)
747  FirstBinding = nullptr;
748 
749  return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,
750  InterestingMethodContext);
751 }
752 
755  const ExplodedNode *EndN,
757  BR.markInteresting(Sym);
758  return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
759 }
760 
763  const ExplodedNode *EndN,
765 
766  // Tell the BugReporterContext to report cases when the tracked symbol is
767  // assigned to different variables, etc.
768  BR.markInteresting(Sym);
769 
770  PathDiagnosticLocation L = cast<RefLeakReport>(BR).getEndOfPath();
771 
772  std::string sbuf;
773  llvm::raw_string_ostream os(sbuf);
774 
775  os << "Object leaked: ";
776 
777  Optional<std::string> RegionDescription = describeRegion(LastBinding);
778  if (RegionDescription) {
779  os << "object allocated and stored into '" << *RegionDescription << '\'';
780  } else {
781  os << "allocated object of type '" << getPrettyTypeName(Sym->getType())
782  << "'";
783  }
784 
785  // Get the retain count.
786  const RefVal *RV = getRefBinding(EndN->getState(), Sym);
787  assert(RV);
788 
789  if (RV->getKind() == RefVal::ErrorLeakReturned) {
790  // FIXME: Per comments in rdar://6320065, "create" only applies to CF
791  // objects. Only "copy", "alloc", "retain" and "new" transfer ownership
792  // to the caller for NS objects.
793  const Decl *D = &EndN->getCodeDecl();
794 
795  os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
796  : " is returned from a function ");
797 
798  if (D->hasAttr<CFReturnsNotRetainedAttr>()) {
799  os << "that is annotated as CF_RETURNS_NOT_RETAINED";
800  } else if (D->hasAttr<NSReturnsNotRetainedAttr>()) {
801  os << "that is annotated as NS_RETURNS_NOT_RETAINED";
802  } else if (D->hasAttr<OSReturnsNotRetainedAttr>()) {
803  os << "that is annotated as OS_RETURNS_NOT_RETAINED";
804  } else {
805  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
806  if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
807  os << "managed by Automatic Reference Counting";
808  } else {
809  os << "whose name ('" << MD->getSelector().getAsString()
810  << "') does not start with "
811  "'copy', 'mutableCopy', 'alloc' or 'new'."
812  " This violates the naming convention rules"
813  " given in the Memory Management Guide for Cocoa";
814  }
815  } else {
816  const FunctionDecl *FD = cast<FunctionDecl>(D);
817  ObjKind K = RV->getObjKind();
818  if (K == ObjKind::ObjC || K == ObjKind::CF) {
819  os << "whose name ('" << *FD
820  << "') does not contain 'Copy' or 'Create'. This violates the "
821  "naming"
822  " convention rules given in the Memory Management Guide for "
823  "Core"
824  " Foundation";
825  } else if (RV->getObjKind() == ObjKind::OS) {
826  std::string FuncName = FD->getNameAsString();
827  os << "whose name ('" << FuncName << "') starts with '"
828  << StringRef(FuncName).substr(0, 3) << "'";
829  }
830  }
831  }
832  } else {
833  os << " is not referenced later in this execution path and has a retain "
834  "count of +"
835  << RV->getCount();
836  }
837 
838  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
839 }
840 
842  ExplodedNode *n, SymbolRef sym, bool isLeak)
843  : PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym),
844  isLeak(isLeak) {
845  if (!isLeak)
846  addVisitor<RefCountReportVisitor>(sym);
847 }
848 
850  ExplodedNode *n, SymbolRef sym,
851  StringRef endText)
852  : PathSensitiveBugReport(D, D.getDescription(), endText, n) {
853 
854  addVisitor<RefCountReportVisitor>(sym);
855 }
856 
857 void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {
858  const SourceManager &SMgr = Ctx.getSourceManager();
859 
860  if (!Sym->getOriginRegion())
861  return;
862 
863  auto *Region = dyn_cast<DeclRegion>(Sym->getOriginRegion());
864  if (Region) {
865  const Decl *PDecl = Region->getDecl();
866  if (isa_and_nonnull<ParmVarDecl>(PDecl)) {
867  PathDiagnosticLocation ParamLocation =
868  PathDiagnosticLocation::create(PDecl, SMgr);
869  Location = ParamLocation;
870  UniqueingLocation = ParamLocation;
872  }
873  }
874 }
875 
876 void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
877  // Most bug reports are cached at the location where they occurred.
878  // With leaks, we want to unique them by the location where they were
879  // allocated, and only report a single path. To do this, we need to find
880  // the allocation site of a piece of tracked memory, which we do via a
881  // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
882  // Note that this is *not* the trimmed graph; we are guaranteed, however,
883  // that all ancestor nodes that represent the allocation site have the
884  // same SourceLocation.
885  const ExplodedNode *AllocNode = nullptr;
886 
887  const SourceManager &SMgr = Ctx.getSourceManager();
888 
889  AllocationInfo AllocI =
891 
892  AllocNode = AllocI.N;
893  AllocFirstBinding = AllocI.R;
894  markInteresting(AllocI.InterestingMethodContext);
895 
896  // Get the SourceLocation for the allocation site.
897  // FIXME: This will crash the analyzer if an allocation comes from an
898  // implicit call (ex: a destructor call).
899  // (Currently there are no such allocations in Cocoa, though.)
900  AllocStmt = AllocNode->getStmtForDiagnostics();
901 
902  if (!AllocStmt) {
903  AllocFirstBinding = nullptr;
904  return;
905  }
906 
908  AllocStmt, SMgr, AllocNode->getLocationContext());
909  Location = AllocLocation;
910 
911  // Set uniqieing info, which will be used for unique the bug reports. The
912  // leaks should be uniqued on the allocation site.
913  UniqueingLocation = AllocLocation;
914  UniqueingDecl = AllocNode->getLocationContext()->getDecl();
915 }
916 
917 void RefLeakReport::createDescription(CheckerContext &Ctx) {
918  assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
919  Description.clear();
920  llvm::raw_string_ostream os(Description);
921  os << "Potential leak of an object";
922 
923  Optional<std::string> RegionDescription =
924  describeRegion(AllocBindingToReport);
925  if (RegionDescription) {
926  os << " stored into '" << *RegionDescription << '\'';
927  } else {
928 
929  // If we can't figure out the name, just supply the type information.
930  os << " of type '" << getPrettyTypeName(Sym->getType()) << "'";
931  }
932 }
933 
934 void RefLeakReport::findBindingToReport(CheckerContext &Ctx,
935  ExplodedNode *Node) {
936  if (!AllocFirstBinding)
937  // If we don't have any bindings, we won't be able to find any
938  // better binding to report.
939  return;
940 
941  // If the original region still contains the leaking symbol...
942  if (Node->getState()->getSVal(AllocFirstBinding).getAsSymbol() == Sym) {
943  // ...it is the best binding to report.
944  AllocBindingToReport = AllocFirstBinding;
945  return;
946  }
947 
948  // At this point, we know that the original region doesn't contain the leaking
949  // when the actual leak happens. It means that it can be confusing for the
950  // user to see such description in the message.
951  //
952  // Let's consider the following example:
953  // Object *Original = allocate(...);
954  // Object *New = Original;
955  // Original = allocate(...);
956  // Original->release();
957  //
958  // Complaining about a leaking object "stored into Original" might cause a
959  // rightful confusion because 'Original' is actually released.
960  // We should complain about 'New' instead.
961  Bindings AllVarBindings =
963 
964  // While looking for the last var bindings, we can still find
965  // `AllocFirstBinding` to be one of them. In situations like this,
966  // it would still be the easiest case to explain to our users.
967  if (!AllVarBindings.empty() &&
968  llvm::count_if(AllVarBindings,
969  [this](const std::pair<const MemRegion *, SVal> Binding) {
970  return Binding.first == AllocFirstBinding;
971  }) == 0) {
972  // Let's pick one of them at random (if there is something to pick from).
973  AllocBindingToReport = AllVarBindings[0].first;
974 
975  // Because 'AllocBindingToReport' is not the the same as
976  // 'AllocFirstBinding', we need to explain how the leaking object
977  // got from one to another.
978  //
979  // NOTE: We use the actual SVal stored in AllocBindingToReport here because
980  // trackStoredValue compares SVal's and it can get trickier for
981  // something like derived regions if we want to construct SVal from
982  // Sym. Instead, we take the value that is definitely stored in that
983  // region, thus guaranteeing that trackStoredValue will work.
984  bugreporter::trackStoredValue(AllVarBindings[0].second.castAs<KnownSVal>(),
985  AllocBindingToReport, *this);
986  } else {
987  AllocBindingToReport = AllocFirstBinding;
988  }
989 }
990 
992  ExplodedNode *N, SymbolRef Sym,
993  CheckerContext &Ctx)
994  : RefCountReport(D, LOpts, N, Sym, /*isLeak=*/true) {
995 
996  deriveAllocLocation(Ctx);
997  findBindingToReport(Ctx, N);
998 
999  if (!AllocFirstBinding)
1000  deriveParamLocation(Ctx);
1001 
1002  createDescription(Ctx);
1003 
1004  addVisitor<RefLeakReportVisitor>(Sym, AllocBindingToReport);
1005 }
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:626
clang::ento::retaincountchecker::RefCountReportVisitor::Profile
void Profile(llvm::FoldingSetNodeID &ID) const override
Definition: RetainCountDiagnostics.cpp:322
clang::ento::retaincountchecker::RefLeakReportVisitor
Definition: RetainCountDiagnostics.cpp:337
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:376
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:356
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, or a 'new' call.
Definition: CallEvent.cpp:1405
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:315
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:1098
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:541
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:608
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:91
findAllocatedObjectName
static std::string findAllocatedObjectName(const Stmt *S, QualType QT)
Definition: RetainCountDiagnostics.cpp:203
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:674
clang::ento::CallEventManager::getObjCMethodCall
CallEventRef< ObjCMethodCall > getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, const LocationContext *LCtx)
Definition: CallEvent.h:1289
clang::OMF_init
@ OMF_init
Definition: IdentifierTable.h:696
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:1663
clang::ObjCObjectPointerType::getPointeeType
QualType getPointeeType() const
Gets the type pointed to by this ObjC pointer.
Definition: Type.h:6110
llvm::Optional< unsigned >
clang::QualType::getAsString
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:1016
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:295
clang::ento::retaincountchecker::RefVal::isOwned
bool isOwned() const
Definition: RetainCountChecker.h:152
clang::Type::isVoidType
bool isVoidType() const
Definition: Type.h:6981
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:991
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:1731
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:626
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:762
clang::ObjCBoolLiteralExpr
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
Definition: ExprObjC.h:88
VarBindingsCollector
Definition: RetainCountDiagnostics.cpp:618
clang::TypedefType
Definition: Type.h:4393
clang::ento::MemRegion
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:94
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:325
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:87
clang::IntegerLiteral
Definition: Expr.h:1494
clang::ento::ExplodedNode::getState
const ProgramStateRef & getState() const
Definition: ExplodedGraph.h:169
clang::ento::OCM_PropertyAccess
@ OCM_PropertyAccess
Definition: CallEvent.h:1097
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:67
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:101
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:7187
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:135
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::ExplodedNode::getLocationAs
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Definition: ExplodedGraph.h:172
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:1760
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:120
clang::ento::CheckerContext::getSourceManager
const SourceManager & getSourceManager()
Definition: CheckerContext.h:106
clang::ento::CallEventManager::getCaller
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
Definition: CallEvent.cpp:1352
clang::ento::KnownSVal
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:290
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:456
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:639
clang::ento::retaincountchecker::RefCountReport
Definition: RetainCountDiagnostics.h:49
clang::ento::retaincountchecker::RefLeakReportVisitor::RefLeakReportVisitor
RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
Definition: RetainCountDiagnostics.cpp:339
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
Definition: AnalysisDeclContext.h:243
clang::ObjCObjectPointerType
Represents a pointer to an Objective C object.
Definition: Type.h:6098
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 MemSpaceRegion * getMemorySpace() const
Definition: MemRegion.cpp:1262
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:1220
clang::ento::BugReport::Description
std::string Description
Definition: BugReporter.h:130
clang::ento::ProgramStateManager
Definition: ProgramState.h:461
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:535
GetAllocationSite
static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym)
Definition: RetainCountDiagnostics.cpp:668
clang::ASTContext::getPrintingPolicy
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:685
clang::ento::ExplodedNode::getFirstPred
ExplodedNode * getFirstPred()
Definition: ExplodedGraph.h:210
clang::QualType::isNull
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:739
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:321
VarBindingsCollector::VarBindingsCollector
VarBindingsCollector(SymbolRef Sym, Bindings &ToFill)
Definition: RetainCountDiagnostics.cpp:623
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:317
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:1588
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:58
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:754
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:1099
clang::Builtin::ID
ID
Definition: Builtins.h:48
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:330
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::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:694
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:16
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:123
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:320
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:426
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:247
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1855
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:763
llvm::IntrusiveRefCntPtr< const ProgramState >
clang::ento::ProgramStateManager::iterBindings
void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)
Definition: ProgramState.h:558
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:433