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