clang  9.0.0svn
RetainCountChecker.cpp
Go to the documentation of this file.
1 //==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the methods for RetainCountChecker, which implements
11 // a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "RetainCountChecker.h"
16 
17 using namespace clang;
18 using namespace ento;
19 using namespace retaincountchecker;
20 using llvm::StrInStrNoCase;
21 
22 REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
23 
24 namespace clang {
25 namespace ento {
26 namespace retaincountchecker {
27 
29  return State->get<RefBindings>(Sym);
30 }
31 
32 } // end namespace retaincountchecker
33 } // end namespace ento
34 } // end namespace clang
35 
37  RefVal Val) {
38  assert(Sym != nullptr);
39  return State->set<RefBindings>(Sym, Val);
40 }
41 
43  return State->remove<RefBindings>(Sym);
44 }
45 
46 void RefVal::print(raw_ostream &Out) const {
47  if (!T.isNull())
48  Out << "Tracked " << T.getAsString() << " | ";
49 
50  switch (getKind()) {
51  default: llvm_unreachable("Invalid RefVal kind");
52  case Owned: {
53  Out << "Owned";
54  unsigned cnt = getCount();
55  if (cnt) Out << " (+ " << cnt << ")";
56  break;
57  }
58 
59  case NotOwned: {
60  Out << "NotOwned";
61  unsigned cnt = getCount();
62  if (cnt) Out << " (+ " << cnt << ")";
63  break;
64  }
65 
66  case ReturnedOwned: {
67  Out << "ReturnedOwned";
68  unsigned cnt = getCount();
69  if (cnt) Out << " (+ " << cnt << ")";
70  break;
71  }
72 
73  case ReturnedNotOwned: {
74  Out << "ReturnedNotOwned";
75  unsigned cnt = getCount();
76  if (cnt) Out << " (+ " << cnt << ")";
77  break;
78  }
79 
80  case Released:
81  Out << "Released";
82  break;
83 
84  case ErrorDeallocNotOwned:
85  Out << "-dealloc (not-owned)";
86  break;
87 
88  case ErrorLeak:
89  Out << "Leaked";
90  break;
91 
92  case ErrorLeakReturned:
93  Out << "Leaked (Bad naming)";
94  break;
95 
96  case ErrorUseAfterRelease:
97  Out << "Use-After-Release [ERROR]";
98  break;
99 
100  case ErrorReleaseNotOwned:
101  Out << "Release of Not-Owned [ERROR]";
102  break;
103 
105  Out << "Over-autoreleased";
106  break;
107 
109  Out << "Non-owned object returned instead of owned";
110  break;
111  }
112 
113  switch (getIvarAccessHistory()) {
115  break;
116  case IvarAccessHistory::AccessedDirectly:
117  Out << " [direct ivar access]";
118  break;
119  case IvarAccessHistory::ReleasedAfterDirectAccess:
120  Out << " [released after direct ivar access]";
121  }
122 
123  if (ACnt) {
124  Out << " [autorelease -" << ACnt << ']';
125  }
126 }
127 
128 namespace {
129 class StopTrackingCallback final : public SymbolVisitor {
131 public:
132  StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
133  ProgramStateRef getState() const { return state; }
134 
135  bool VisitSymbol(SymbolRef sym) override {
136  state = removeRefBinding(state, sym);
137  return true;
138  }
139 };
140 } // end anonymous namespace
141 
142 //===----------------------------------------------------------------------===//
143 // Handle statements that may have an effect on refcounts.
144 //===----------------------------------------------------------------------===//
145 
147  CheckerContext &C) const {
148 
149  // Scan the BlockDecRefExprs for any object the retain count checker
150  // may be tracking.
151  if (!BE->getBlockDecl()->hasCaptures())
152  return;
153 
155  auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
156 
157  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
158  E = R->referenced_vars_end();
159 
160  if (I == E)
161  return;
162 
163  // FIXME: For now we invalidate the tracking of all symbols passed to blocks
164  // via captured variables, even though captured variables result in a copy
165  // and in implicit increment/decrement of a retain count.
167  const LocationContext *LC = C.getLocationContext();
169 
170  for ( ; I != E; ++I) {
171  const VarRegion *VR = I.getCapturedRegion();
172  if (VR->getSuperRegion() == R) {
173  VR = MemMgr.getVarRegion(VR->getDecl(), LC);
174  }
175  Regions.push_back(VR);
176  }
177 
178  state = state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
179  C.addTransition(state);
180 }
181 
183  CheckerContext &C) const {
184  const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
185  if (!BE)
186  return;
187 
189 
190  switch (BE->getBridgeKind()) {
191  case OBC_Bridge:
192  // Do nothing.
193  return;
194  case OBC_BridgeRetained:
195  AE = AE.withKind(IncRef);
196  break;
197  case OBC_BridgeTransfer:
199  break;
200  }
201 
203  SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
204  if (!Sym)
205  return;
206  const RefVal* T = getRefBinding(state, Sym);
207  if (!T)
208  return;
209 
210  RefVal::Kind hasErr = (RefVal::Kind) 0;
211  state = updateSymbol(state, Sym, *T, AE, hasErr, C);
212 
213  if (hasErr) {
214  // FIXME: If we get an error during a bridge cast, should we report it?
215  return;
216  }
217 
218  C.addTransition(state);
219 }
220 
222  const Expr *Ex) const {
224  const ExplodedNode *pred = C.getPredecessor();
225  for (const Stmt *Child : Ex->children()) {
226  SVal V = pred->getSVal(Child);
227  if (SymbolRef sym = V.getAsSymbol())
228  if (const RefVal* T = getRefBinding(state, sym)) {
229  RefVal::Kind hasErr = (RefVal::Kind) 0;
230  state = updateSymbol(state, sym, *T,
231  ArgEffect(MayEscape, ObjKind::ObjC), hasErr, C);
232  if (hasErr) {
233  processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
234  return;
235  }
236  }
237  }
238 
239  // Return the object as autoreleased.
240  // RetEffect RE = RetEffect::MakeNotOwned(ObjKind::ObjC);
241  if (SymbolRef sym =
242  state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
243  QualType ResultTy = Ex->getType();
244  state = setRefBinding(state, sym,
246  }
247 
248  C.addTransition(state);
249 }
250 
252  CheckerContext &C) const {
253  // Apply the 'MayEscape' to all values.
254  processObjCLiterals(C, AL);
255 }
256 
258  CheckerContext &C) const {
259  // Apply the 'MayEscape' to all keys and values.
260  processObjCLiterals(C, DL);
261 }
262 
264  CheckerContext &C) const {
265  const ExplodedNode *Pred = C.getPredecessor();
266  ProgramStateRef State = Pred->getState();
267 
268  if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) {
269  QualType ResultTy = Ex->getType();
270  State = setRefBinding(State, Sym,
272  }
273 
274  C.addTransition(State);
275 }
276 
278  CheckerContext &C) const {
279  Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
280  if (!IVarLoc)
281  return;
282 
284  SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
285  if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion()))
286  return;
287 
288  // Accessing an ivar directly is unusual. If we've done that, be more
289  // forgiving about what the surrounding code is allowed to do.
290 
291  QualType Ty = Sym->getType();
292  ObjKind Kind;
293  if (Ty->isObjCRetainableType())
294  Kind = ObjKind::ObjC;
295  else if (coreFoundation::isCFObjectRef(Ty))
296  Kind = ObjKind::CF;
297  else
298  return;
299 
300  // If the value is already known to be nil, don't bother tracking it.
301  ConstraintManager &CMgr = State->getConstraintManager();
302  if (CMgr.isNull(State, Sym).isConstrainedTrue())
303  return;
304 
305  if (const RefVal *RV = getRefBinding(State, Sym)) {
306  // If we've seen this symbol before, or we're only seeing it now because
307  // of something the analyzer has synthesized, don't do anything.
308  if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
310  return;
311  }
312 
313  // Note that this value has been loaded from an ivar.
314  C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
315  return;
316  }
317 
318  RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
319 
320  // In a synthesized accessor, the effective retain count is +0.
322  C.addTransition(setRefBinding(State, Sym, PlusZero));
323  return;
324  }
325 
326  State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
327  C.addTransition(State);
328 }
329 
331  CheckerContext &C) const {
332  RetainSummaryManager &Summaries = getSummaryManager(C);
333 
334  // Leave null if no receiver.
335  QualType ReceiverType;
336  if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
337  if (MC->isInstanceMessage()) {
338  SVal ReceiverV = MC->getReceiverSVal();
339  if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
340  if (const RefVal *T = getRefBinding(C.getState(), Sym))
341  ReceiverType = T->getType();
342  }
343  }
344 
345  const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
346 
347  if (C.wasInlined) {
348  processSummaryOfInlined(*Summ, Call, C);
349  return;
350  }
351  checkSummary(*Summ, Call, C);
352 }
353 
354 /// GetReturnType - Used to get the return type of a message expression or
355 /// function call with the intention of affixing that type to a tracked symbol.
356 /// While the return type can be queried directly from RetEx, when
357 /// invoking class methods we augment to the return type to be that of
358 /// a pointer to the class (as opposed it just being id).
359 // FIXME: We may be able to do this with related result types instead.
360 // This function is probably overestimating.
361 static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
362  QualType RetTy = RetE->getType();
363  // If RetE is not a message expression just return its type.
364  // If RetE is a message expression, return its types if it is something
365  /// more specific than id.
366  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
367  if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
368  if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
369  PT->isObjCClassType()) {
370  // At this point we know the return type of the message expression is
371  // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
372  // is a call to a class method whose type we can resolve. In such
373  // cases, promote the return type to XXX* (where XXX is the class).
374  const ObjCInterfaceDecl *D = ME->getReceiverInterface();
375  return !D ? RetTy :
377  }
378 
379  return RetTy;
380 }
381 
383  QualType ResultTy) {
384  if (RE.isOwned()) {
385  return RefVal::makeOwned(RE.getObjKind(), ResultTy);
386  } else if (RE.notOwned()) {
387  return RefVal::makeNotOwned(RE.getObjKind(), ResultTy);
388  }
389 
390  return None;
391 }
392 
393 static bool isPointerToObject(QualType QT) {
394  QualType PT = QT->getPointeeType();
395  if (!PT.isNull())
396  if (PT->getAsCXXRecordDecl())
397  return true;
398  return false;
399 }
400 
401 /// Whether the tracked value should be escaped on a given call.
402 /// OSObjects are escaped when passed to void * / etc.
403 static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
404  const RefVal *TrackedValue) {
405  if (TrackedValue->getObjKind() != ObjKind::OS)
406  return false;
407  if (ArgIdx >= CE.parameters().size())
408  return false;
409  return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
410 }
411 
412 // We don't always get the exact modeling of the function with regards to the
413 // retain count checker even when the function is inlined. For example, we need
414 // to stop tracking the symbols which were marked with StopTrackingHard.
415 void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
416  const CallEvent &CallOrMsg,
417  CheckerContext &C) const {
419 
420  // Evaluate the effect of the arguments.
421  for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
422  SVal V = CallOrMsg.getArgSVal(idx);
423 
424  if (SymbolRef Sym = V.getAsLocSymbol()) {
425  bool ShouldRemoveBinding = Summ.getArg(idx).getKind() == StopTrackingHard;
426  if (const RefVal *T = getRefBinding(state, Sym))
427  if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
428  ShouldRemoveBinding = true;
429 
430  if (ShouldRemoveBinding)
431  state = removeRefBinding(state, Sym);
432  }
433  }
434 
435  // Evaluate the effect on the message receiver.
436  if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
437  if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
438  if (Summ.getReceiverEffect().getKind() == StopTrackingHard) {
439  state = removeRefBinding(state, Sym);
440  }
441  }
442  }
443 
444  // Consult the summary for the return value.
445  RetEffect RE = Summ.getRetEffect();
446 
447  if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
448  if (RE.getKind() == RetEffect::NoRetHard)
449  state = removeRefBinding(state, Sym);
450  }
451 
452  C.addTransition(state);
453 }
454 
455 static bool isSmartPtrField(const MemRegion *MR) {
456  const auto *TR = dyn_cast<TypedValueRegion>(
457  cast<SubRegion>(MR)->getSuperRegion());
458  return TR && RetainSummaryManager::isKnownSmartPointer(TR->getValueType());
459 }
460 
461 
462 /// A value escapes in these possible cases:
463 ///
464 /// - binding to something that is not a memory region.
465 /// - binding to a memregion that does not have stack storage
466 /// - binding to a variable that has a destructor attached using CleanupAttr
467 ///
468 /// We do not currently model what happens when a symbol is
469 /// assigned to a struct field, unless it is a known smart pointer
470 /// implementation, about which we know that it is inlined.
471 /// FIXME: This could definitely be improved upon.
472 static bool shouldEscapeRegion(const MemRegion *R) {
473  if (isSmartPtrField(R))
474  return false;
475 
476  const auto *VR = dyn_cast<VarRegion>(R);
477 
478  if (!R->hasStackStorage() || !VR)
479  return true;
480 
481  const VarDecl *VD = VR->getDecl();
482  if (!VD->hasAttr<CleanupAttr>())
483  return false; // CleanupAttr attaches destructors, which cause escaping.
484  return true;
485 }
486 
488 updateOutParameters(ProgramStateRef State, const RetainSummary &Summ,
489  const CallEvent &CE) {
490 
491  SVal L = CE.getReturnValue();
492 
493  // Splitting is required to support out parameters,
494  // as out parameters might be created only on the "success" branch.
495  // We want to avoid eagerly splitting unless out parameters are actually
496  // needed.
497  bool SplitNecessary = false;
498  for (auto &P : Summ.getArgEffects())
499  if (P.second.getKind() == RetainedOutParameterOnNonZero ||
500  P.second.getKind() == RetainedOutParameterOnZero)
501  SplitNecessary = true;
502 
503  ProgramStateRef AssumeNonZeroReturn = State;
504  ProgramStateRef AssumeZeroReturn = State;
505 
506  if (SplitNecessary) {
507  if (auto DL = L.getAs<DefinedOrUnknownSVal>()) {
508  AssumeNonZeroReturn = AssumeNonZeroReturn->assume(*DL, true);
509  AssumeZeroReturn = AssumeZeroReturn->assume(*DL, false);
510  }
511  }
512 
513  for (unsigned idx = 0, e = CE.getNumArgs(); idx != e; ++idx) {
514  SVal ArgVal = CE.getArgSVal(idx);
515  ArgEffect AE = Summ.getArg(idx);
516 
517  auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
518  if (!ArgRegion)
519  continue;
520 
521  QualType PointeeTy = ArgRegion->getValueType();
522  SVal PointeeVal = State->getSVal(ArgRegion);
523  SymbolRef Pointee = PointeeVal.getAsLocSymbol();
524  if (!Pointee)
525  continue;
526 
527  if (shouldEscapeRegion(ArgRegion))
528  continue;
529 
530  auto makeNotOwnedParameter = [&](ProgramStateRef St) {
531  return setRefBinding(St, Pointee,
532  RefVal::makeNotOwned(AE.getObjKind(), PointeeTy));
533  };
534  auto makeOwnedParameter = [&](ProgramStateRef St) {
535  return setRefBinding(St, Pointee,
536  RefVal::makeOwned(ObjKind::OS, PointeeTy));
537  };
538 
539  switch (AE.getKind()) {
541  AssumeNonZeroReturn = makeNotOwnedParameter(AssumeNonZeroReturn);
542  AssumeZeroReturn = makeNotOwnedParameter(AssumeZeroReturn);
543  break;
545  AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
546  AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
547  break;
549  AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
550  break;
552  AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
553  break;
554  default:
555  break;
556  }
557  }
558 
559  if (SplitNecessary) {
560  return {AssumeNonZeroReturn, AssumeZeroReturn};
561  } else {
562  assert(AssumeZeroReturn == AssumeNonZeroReturn);
563  return {AssumeZeroReturn};
564  }
565 }
566 
567 void RetainCountChecker::checkSummary(const RetainSummary &Summ,
568  const CallEvent &CallOrMsg,
569  CheckerContext &C) const {
571 
572  // Evaluate the effect of the arguments.
573  RefVal::Kind hasErr = (RefVal::Kind) 0;
574  SourceRange ErrorRange;
575  SymbolRef ErrorSym = nullptr;
576 
577  // Helper tag for providing diagnostics: indicate whether dealloc was sent
578  // at this location.
579  static CheckerProgramPointTag DeallocSentTag(this, DeallocTagDescription);
580  bool DeallocSent = false;
581 
582  for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
583  SVal V = CallOrMsg.getArgSVal(idx);
584 
585  ArgEffect Effect = Summ.getArg(idx);
586  if (SymbolRef Sym = V.getAsLocSymbol()) {
587  if (const RefVal *T = getRefBinding(state, Sym)) {
588 
589  if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
591 
592  state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
593  if (hasErr) {
594  ErrorRange = CallOrMsg.getArgSourceRange(idx);
595  ErrorSym = Sym;
596  break;
597  } else if (Effect.getKind() == Dealloc) {
598  DeallocSent = true;
599  }
600  }
601  }
602  }
603 
604  // Evaluate the effect on the message receiver / `this` argument.
605  bool ReceiverIsTracked = false;
606  if (!hasErr) {
607  if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
608  if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
609  if (const RefVal *T = getRefBinding(state, Sym)) {
610  ReceiverIsTracked = true;
611  state = updateSymbol(state, Sym, *T,
612  Summ.getReceiverEffect(), hasErr, C);
613  if (hasErr) {
614  ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
615  ErrorSym = Sym;
616  } else if (Summ.getReceiverEffect().getKind() == Dealloc) {
617  DeallocSent = true;
618  }
619  }
620  }
621  } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
622  if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
623  if (const RefVal *T = getRefBinding(state, Sym)) {
624  state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
625  hasErr, C);
626  if (hasErr) {
627  ErrorRange = MCall->getOriginExpr()->getSourceRange();
628  ErrorSym = Sym;
629  }
630  }
631  }
632  }
633  }
634 
635  // Process any errors.
636  if (hasErr) {
637  processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
638  return;
639  }
640 
641  // Consult the summary for the return value.
642  RetEffect RE = Summ.getRetEffect();
643 
645  if (ReceiverIsTracked)
646  RE = getSummaryManager(C).getObjAllocRetEffect();
647  else
648  RE = RetEffect::MakeNoRet();
649  }
650 
651  if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
652  QualType ResultTy = CallOrMsg.getResultType();
653  if (RE.notOwned()) {
654  const Expr *Ex = CallOrMsg.getOriginExpr();
655  assert(Ex);
656  ResultTy = GetReturnType(Ex, C.getASTContext());
657  }
658  if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
659  state = setRefBinding(state, Sym, *updatedRefVal);
660  }
661 
663  updateOutParameters(state, Summ, CallOrMsg);
664 
665  for (ProgramStateRef St : Out) {
666  if (DeallocSent) {
667  C.addTransition(St, C.getPredecessor(), &DeallocSentTag);
668  } else {
669  C.addTransition(St);
670  }
671  }
672 }
673 
675  SymbolRef sym, RefVal V,
676  ArgEffect AE,
677  RefVal::Kind &hasErr,
678  CheckerContext &C) const {
679  bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
680  if (AE.getObjKind() == ObjKind::ObjC && IgnoreRetainMsg) {
681  switch (AE.getKind()) {
682  default:
683  break;
684  case IncRef:
685  AE = AE.withKind(DoNothing);
686  break;
687  case DecRef:
688  AE = AE.withKind(DoNothing);
689  break;
691  AE = AE.withKind(StopTracking);
692  break;
693  }
694  }
695 
696  // Handle all use-after-releases.
697  if (V.getKind() == RefVal::Released) {
699  hasErr = V.getKind();
700  return setRefBinding(state, sym, V);
701  }
702 
703  switch (AE.getKind()) {
708  llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
709  "not have ref state.");
710 
711  case Dealloc: // NB. we only need to add a note in a non-error case.
712  switch (V.getKind()) {
713  default:
714  llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
715  case RefVal::Owned:
716  // The object immediately transitions to the released state.
717  V = V ^ RefVal::Released;
718  V.clearCounts();
719  return setRefBinding(state, sym, V);
720  case RefVal::NotOwned:
722  hasErr = V.getKind();
723  break;
724  }
725  break;
726 
727  case MayEscape:
728  if (V.getKind() == RefVal::Owned) {
729  V = V ^ RefVal::NotOwned;
730  break;
731  }
732 
733  LLVM_FALLTHROUGH;
734 
735  case DoNothing:
736  return state;
737 
738  case Autorelease:
739  // Update the autorelease counts.
740  V = V.autorelease();
741  break;
742 
743  case StopTracking:
744  case StopTrackingHard:
745  return removeRefBinding(state, sym);
746 
747  case IncRef:
748  switch (V.getKind()) {
749  default:
750  llvm_unreachable("Invalid RefVal state for a retain.");
751  case RefVal::Owned:
752  case RefVal::NotOwned:
753  V = V + 1;
754  break;
755  }
756  break;
757 
758  case DecRef:
761  switch (V.getKind()) {
762  default:
763  // case 'RefVal::Released' handled above.
764  llvm_unreachable("Invalid RefVal state for a release.");
765 
766  case RefVal::Owned:
767  assert(V.getCount() > 0);
768  if (V.getCount() == 1) {
769  if (AE.getKind() == DecRefBridgedTransferred ||
770  V.getIvarAccessHistory() ==
772  V = V ^ RefVal::NotOwned;
773  else
774  V = V ^ RefVal::Released;
775  } else if (AE.getKind() == DecRefAndStopTrackingHard) {
776  return removeRefBinding(state, sym);
777  }
778 
779  V = V - 1;
780  break;
781 
782  case RefVal::NotOwned:
783  if (V.getCount() > 0) {
785  return removeRefBinding(state, sym);
786  V = V - 1;
787  } else if (V.getIvarAccessHistory() ==
789  // Assume that the instance variable was holding on the object at
790  // +1, and we just didn't know.
792  return removeRefBinding(state, sym);
794  } else {
796  hasErr = V.getKind();
797  }
798  break;
799  }
800  break;
801  }
802  return setRefBinding(state, sym, V);
803 }
804 
805 const RefCountBug &
807  SymbolRef Sym) const {
808  switch (ErrorKind) {
810  return useAfterRelease;
812  return releaseNotOwned;
814  if (Sym->getType()->getPointeeCXXRecordDecl())
815  return freeNotOwned;
816  return deallocNotOwned;
817  default:
818  llvm_unreachable("Unhandled error.");
819  }
820 }
821 
823  SourceRange ErrorRange,
825  SymbolRef Sym,
826  CheckerContext &C) const {
827  // HACK: Ignore retain-count issues on values accessed through ivars,
828  // because of cases like this:
829  // [_contentView retain];
830  // [_contentView removeFromSuperview];
831  // [self addSubview:_contentView]; // invalidates 'self'
832  // [_contentView release];
833  if (const RefVal *RV = getRefBinding(St, Sym))
834  if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
835  return;
836 
837  ExplodedNode *N = C.generateErrorNode(St);
838  if (!N)
839  return;
840 
841  auto report = llvm::make_unique<RefCountReport>(
842  errorKindToBugKind(ErrorKind, Sym),
843  C.getASTContext().getLangOpts(), N, Sym);
844  report->addRange(ErrorRange);
845  C.emitReport(std::move(report));
846 }
847 
848 //===----------------------------------------------------------------------===//
849 // Handle the return values of retain-count-related functions.
850 //===----------------------------------------------------------------------===//
851 
853  // Get the callee. We're only interested in simple C functions.
855  const FunctionDecl *FD = C.getCalleeDecl(CE);
856  if (!FD)
857  return false;
858 
859  RetainSummaryManager &SmrMgr = getSummaryManager(C);
860  QualType ResultTy = CE->getCallReturnType(C.getASTContext());
861 
862  // See if the function has 'rc_ownership_trusted_implementation'
863  // annotate attribute. If it does, we will not inline it.
864  bool hasTrustedImplementationAnnotation = false;
865 
866  const LocationContext *LCtx = C.getLocationContext();
867 
868  using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
870  SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
871 
872  // See if it's one of the specific functions we know how to eval.
873  if (!BSmr)
874  return false;
875 
876  // Bind the return value.
877  if (BSmr == BehaviorSummary::Identity ||
878  BSmr == BehaviorSummary::IdentityOrZero) {
879  SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
880 
881  // If the receiver is unknown or the function has
882  // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
883  // return value.
884  if (RetVal.isUnknown() ||
885  (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
886  SValBuilder &SVB = C.getSValBuilder();
887  RetVal =
888  SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
889  }
890  state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
891 
892  if (BSmr == BehaviorSummary::IdentityOrZero) {
893  // Add a branch where the output is zero.
894  ProgramStateRef NullOutputState = C.getState();
895 
896  // Assume that output is zero on the other branch.
897  NullOutputState = NullOutputState->BindExpr(
898  CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
899 
900  C.addTransition(NullOutputState);
901 
902  // And on the original branch assume that both input and
903  // output are non-zero.
904  if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
905  state = state->assume(*L, /*Assumption=*/true);
906 
907  }
908  }
909 
910  C.addTransition(state);
911  return true;
912 }
913 
914 ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
915  CheckerContext &C) const {
916  ExplodedNode *Pred = C.getPredecessor();
917 
918  // Only adjust the reference count if this is the top-level call frame,
919  // and not the result of inlining. In the future, we should do
920  // better checking even for inlined calls, and see if they match
921  // with their expected semantics (e.g., the method should return a retained
922  // object, etc.).
923  if (!C.inTopFrame())
924  return Pred;
925 
926  if (!S)
927  return Pred;
928 
929  const Expr *RetE = S->getRetValue();
930  if (!RetE)
931  return Pred;
932 
934  SymbolRef Sym =
935  state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
936  if (!Sym)
937  return Pred;
938 
939  // Get the reference count binding (if any).
940  const RefVal *T = getRefBinding(state, Sym);
941  if (!T)
942  return Pred;
943 
944  // Change the reference count.
945  RefVal X = *T;
946 
947  switch (X.getKind()) {
948  case RefVal::Owned: {
949  unsigned cnt = X.getCount();
950  assert(cnt > 0);
951  X.setCount(cnt - 1);
952  X = X ^ RefVal::ReturnedOwned;
953  break;
954  }
955 
956  case RefVal::NotOwned: {
957  unsigned cnt = X.getCount();
958  if (cnt) {
959  X.setCount(cnt - 1);
960  X = X ^ RefVal::ReturnedOwned;
961  } else {
962  X = X ^ RefVal::ReturnedNotOwned;
963  }
964  break;
965  }
966 
967  default:
968  return Pred;
969  }
970 
971  // Update the binding.
972  state = setRefBinding(state, Sym, X);
973  Pred = C.addTransition(state);
974 
975  // At this point we have updated the state properly.
976  // Everything after this is merely checking to see if the return value has
977  // been over- or under-retained.
978 
979  // Did we cache out?
980  if (!Pred)
981  return nullptr;
982 
983  // Update the autorelease counts.
984  static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
985  state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
986 
987  // Have we generated a sink node?
988  if (!state)
989  return nullptr;
990 
991  // Get the updated binding.
992  T = getRefBinding(state, Sym);
993  assert(T);
994  X = *T;
995 
996  // Consult the summary of the enclosing method.
997  RetainSummaryManager &Summaries = getSummaryManager(C);
998  const Decl *CD = &Pred->getCodeDecl();
1000 
1001  // FIXME: What is the convention for blocks? Is there one?
1002  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
1003  const RetainSummary *Summ = Summaries.getMethodSummary(MD);
1004  RE = Summ->getRetEffect();
1005  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
1006  if (!isa<CXXMethodDecl>(FD)) {
1007  const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
1008  RE = Summ->getRetEffect();
1009  }
1010  }
1011 
1012  return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
1013 }
1014 
1016  CheckerContext &C,
1017  ExplodedNode *Pred,
1018  RetEffect RE, RefVal X,
1019  SymbolRef Sym,
1020  ProgramStateRef state) const {
1021  // HACK: Ignore retain-count issues on values accessed through ivars,
1022  // because of cases like this:
1023  // [_contentView retain];
1024  // [_contentView removeFromSuperview];
1025  // [self addSubview:_contentView]; // invalidates 'self'
1026  // [_contentView release];
1028  return Pred;
1029 
1030  // Any leaks or other errors?
1031  if (X.isReturnedOwned() && X.getCount() == 0) {
1032  if (RE.getKind() != RetEffect::NoRet) {
1033  if (!RE.isOwned()) {
1034 
1035  // The returning type is a CF, we expect the enclosing method should
1036  // return ownership.
1037  X = X ^ RefVal::ErrorLeakReturned;
1038 
1039  // Generate an error node.
1040  state = setRefBinding(state, Sym, X);
1041 
1042  static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
1043  ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
1044  if (N) {
1045  const LangOptions &LOpts = C.getASTContext().getLangOpts();
1046  auto R =
1047  llvm::make_unique<RefLeakReport>(leakAtReturn, LOpts, N, Sym, C);
1048  C.emitReport(std::move(R));
1049  }
1050  return N;
1051  }
1052  }
1053  } else if (X.isReturnedNotOwned()) {
1054  if (RE.isOwned()) {
1055  if (X.getIvarAccessHistory() ==
1057  // Assume the method was trying to transfer a +1 reference from a
1058  // strong ivar to the caller.
1059  state = setRefBinding(state, Sym,
1061  } else {
1062  // Trying to return a not owned object to a caller expecting an
1063  // owned object.
1064  state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
1065 
1066  static CheckerProgramPointTag
1067  ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
1068 
1069  ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
1070  if (N) {
1071  auto R = llvm::make_unique<RefCountReport>(
1072  returnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym);
1073  C.emitReport(std::move(R));
1074  }
1075  return N;
1076  }
1077  }
1078  }
1079  return Pred;
1080 }
1081 
1082 //===----------------------------------------------------------------------===//
1083 // Check various ways a symbol can be invalidated.
1084 //===----------------------------------------------------------------------===//
1085 
1087  CheckerContext &C) const {
1089  const MemRegion *MR = loc.getAsRegion();
1090 
1091  // Find all symbols referenced by 'val' that we are tracking
1092  // and stop tracking them.
1093  if (MR && shouldEscapeRegion(MR)) {
1094  state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1095  C.addTransition(state);
1096  }
1097 }
1098 
1100  SVal Cond,
1101  bool Assumption) const {
1102  // FIXME: We may add to the interface of evalAssume the list of symbols
1103  // whose assumptions have changed. For now we just iterate through the
1104  // bindings and check if any of the tracked symbols are NULL. This isn't
1105  // too bad since the number of symbols we will track in practice are
1106  // probably small and evalAssume is only called at branches and a few
1107  // other places.
1108  RefBindingsTy B = state->get<RefBindings>();
1109 
1110  if (B.isEmpty())
1111  return state;
1112 
1113  bool changed = false;
1114  RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1115  ConstraintManager &CMgr = state->getConstraintManager();
1116 
1117  for (auto &I : B) {
1118  // Check if the symbol is null stop tracking the symbol.
1119  ConditionTruthVal AllocFailed = CMgr.isNull(state, I.first);
1120  if (AllocFailed.isConstrainedTrue()) {
1121  changed = true;
1122  B = RefBFactory.remove(B, I.first);
1123  }
1124  }
1125 
1126  if (changed)
1127  state = state->set<RefBindings>(B);
1128 
1129  return state;
1130 }
1131 
1133  ProgramStateRef state, const InvalidatedSymbols *invalidated,
1134  ArrayRef<const MemRegion *> ExplicitRegions,
1135  ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
1136  const CallEvent *Call) const {
1137  if (!invalidated)
1138  return state;
1139 
1140  llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
1141 
1142  for (const MemRegion *I : ExplicitRegions)
1143  if (const SymbolicRegion *SR = I->StripCasts()->getAs<SymbolicRegion>())
1144  WhitelistedSymbols.insert(SR->getSymbol());
1145 
1146  for (SymbolRef sym : *invalidated) {
1147  if (WhitelistedSymbols.count(sym))
1148  continue;
1149  // Remove any existing reference-count binding.
1150  state = removeRefBinding(state, sym);
1151  }
1152  return state;
1153 }
1154 
1157  ExplodedNode *Pred,
1158  const ProgramPointTag *Tag,
1159  CheckerContext &Ctx,
1160  SymbolRef Sym,
1161  RefVal V,
1162  const ReturnStmt *S) const {
1163  unsigned ACnt = V.getAutoreleaseCount();
1164 
1165  // No autorelease counts? Nothing to be done.
1166  if (!ACnt)
1167  return state;
1168 
1169  unsigned Cnt = V.getCount();
1170 
1171  // FIXME: Handle sending 'autorelease' to already released object.
1172 
1173  if (V.getKind() == RefVal::ReturnedOwned)
1174  ++Cnt;
1175 
1176  // If we would over-release here, but we know the value came from an ivar,
1177  // assume it was a strong ivar that's just been relinquished.
1178  if (ACnt > Cnt &&
1180  V = V.releaseViaIvar();
1181  --ACnt;
1182  }
1183 
1184  if (ACnt <= Cnt) {
1185  if (ACnt == Cnt) {
1186  V.clearCounts();
1187  if (V.getKind() == RefVal::ReturnedOwned) {
1188  V = V ^ RefVal::ReturnedNotOwned;
1189  } else {
1190  V = V ^ RefVal::NotOwned;
1191  }
1192  } else {
1193  V.setCount(V.getCount() - ACnt);
1194  V.setAutoreleaseCount(0);
1195  }
1196  return setRefBinding(state, Sym, V);
1197  }
1198 
1199  // HACK: Ignore retain-count issues on values accessed through ivars,
1200  // because of cases like this:
1201  // [_contentView retain];
1202  // [_contentView removeFromSuperview];
1203  // [self addSubview:_contentView]; // invalidates 'self'
1204  // [_contentView release];
1206  return state;
1207 
1208  // Woah! More autorelease counts then retain counts left.
1209  // Emit hard error.
1211  state = setRefBinding(state, Sym, V);
1212 
1213  ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1214  if (N) {
1215  SmallString<128> sbuf;
1216  llvm::raw_svector_ostream os(sbuf);
1217  os << "Object was autoreleased ";
1218  if (V.getAutoreleaseCount() > 1)
1219  os << V.getAutoreleaseCount() << " times but the object ";
1220  else
1221  os << "but ";
1222  os << "has a +" << V.getCount() << " retain count";
1223 
1224  const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1225  auto R = llvm::make_unique<RefCountReport>(overAutorelease, LOpts, N, Sym,
1226  os.str());
1227  Ctx.emitReport(std::move(R));
1228  }
1229 
1230  return nullptr;
1231 }
1232 
1235  SymbolRef sid, RefVal V,
1236  SmallVectorImpl<SymbolRef> &Leaked) const {
1237  bool hasLeak;
1238 
1239  // HACK: Ignore retain-count issues on values accessed through ivars,
1240  // because of cases like this:
1241  // [_contentView retain];
1242  // [_contentView removeFromSuperview];
1243  // [self addSubview:_contentView]; // invalidates 'self'
1244  // [_contentView release];
1246  hasLeak = false;
1247  else if (V.isOwned())
1248  hasLeak = true;
1249  else if (V.isNotOwned() || V.isReturnedOwned())
1250  hasLeak = (V.getCount() > 0);
1251  else
1252  hasLeak = false;
1253 
1254  if (!hasLeak)
1255  return removeRefBinding(state, sid);
1256 
1257  Leaked.push_back(sid);
1258  return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1259 }
1260 
1261 ExplodedNode *
1264  CheckerContext &Ctx,
1265  ExplodedNode *Pred) const {
1266  // Generate an intermediate node representing the leak point.
1267  ExplodedNode *N = Ctx.addTransition(state, Pred);
1268  const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1269 
1270  if (N) {
1271  for (SymbolRef L : Leaked) {
1272  const RefCountBug &BT = Pred ? leakWithinFunction : leakAtReturn;
1273  Ctx.emitReport(llvm::make_unique<RefLeakReport>(BT, LOpts, N, L, Ctx));
1274  }
1275  }
1276 
1277  return N;
1278 }
1279 
1280 static bool isISLObjectRef(QualType Ty) {
1281  return StringRef(Ty.getAsString()).startswith("isl_");
1282 }
1283 
1285  if (!Ctx.inTopFrame())
1286  return;
1287 
1288  RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
1289  const LocationContext *LCtx = Ctx.getLocationContext();
1290  const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
1291 
1292  if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
1293  return;
1294 
1295  ProgramStateRef state = Ctx.getState();
1296  const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
1297  ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1298 
1299  for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
1300  const ParmVarDecl *Param = FD->getParamDecl(idx);
1301  SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1302 
1303  QualType Ty = Param->getType();
1304  const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
1305  if (AE && AE->getKind() == DecRef && isISLObjectRef(Ty)) {
1306  state = setRefBinding(
1307  state, Sym, RefVal::makeOwned(ObjKind::Generalized, Ty));
1308  } else if (isISLObjectRef(Ty)) {
1309  state = setRefBinding(
1310  state, Sym,
1312  }
1313  }
1314 
1315  Ctx.addTransition(state);
1316 }
1317 
1319  CheckerContext &Ctx) const {
1320  ExplodedNode *Pred = processReturn(RS, Ctx);
1321 
1322  // Created state cached out.
1323  if (!Pred) {
1324  return;
1325  }
1326 
1327  ProgramStateRef state = Pred->getState();
1328  RefBindingsTy B = state->get<RefBindings>();
1329 
1330  // Don't process anything within synthesized bodies.
1331  const LocationContext *LCtx = Pred->getLocationContext();
1332  if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1333  assert(!LCtx->inTopFrame());
1334  return;
1335  }
1336 
1337  for (auto &I : B) {
1338  state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1339  I.first, I.second);
1340  if (!state)
1341  return;
1342  }
1343 
1344  // If the current LocationContext has a parent, don't check for leaks.
1345  // We will do that later.
1346  // FIXME: we should instead check for imbalances of the retain/releases,
1347  // and suggest annotations.
1348  if (LCtx->getParent())
1349  return;
1350 
1351  B = state->get<RefBindings>();
1353 
1354  for (auto &I : B)
1355  state = handleSymbolDeath(state, I.first, I.second, Leaked);
1356 
1357  processLeaks(state, Leaked, Ctx, Pred);
1358 }
1359 
1361  CheckerContext &C) const {
1362  ExplodedNode *Pred = C.getPredecessor();
1363 
1366 
1367  // Update counts from autorelease pools
1368  for (const auto &I: state->get<RefBindings>()) {
1369  SymbolRef Sym = I.first;
1370  if (SymReaper.isDead(Sym)) {
1371  static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
1372  const RefVal &V = I.second;
1373  state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V);
1374  if (!state)
1375  return;
1376 
1377  // Fetch the new reference count from the state, and use it to handle
1378  // this symbol.
1379  state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked);
1380  }
1381  }
1382 
1383  if (Leaked.empty()) {
1384  C.addTransition(state);
1385  return;
1386  }
1387 
1388  Pred = processLeaks(state, Leaked, C, Pred);
1389 
1390  // Did we cache out?
1391  if (!Pred)
1392  return;
1393 
1394  // Now generate a new node that nukes the old bindings.
1395  // The only bindings left at this point are the leaked symbols.
1396  RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1397  RefBindingsTy B = state->get<RefBindings>();
1398 
1399  for (SymbolRef L : Leaked)
1400  B = F.remove(B, L);
1401 
1402  state = state->set<RefBindings>(B);
1403  C.addTransition(state, Pred);
1404 }
1405 
1407  const char *NL, const char *Sep) const {
1408 
1409  RefBindingsTy B = State->get<RefBindings>();
1410 
1411  if (B.isEmpty())
1412  return;
1413 
1414  Out << Sep << NL;
1415 
1416  for (auto &I : B) {
1417  Out << I.first << " : ";
1418  I.second.print(Out);
1419  Out << NL;
1420  }
1421 }
1422 
1423 //===----------------------------------------------------------------------===//
1424 // Checker registration.
1425 //===----------------------------------------------------------------------===//
1426 
1427 void ento::registerRetainCountChecker(CheckerManager &Mgr) {
1428  auto *Chk = Mgr.registerChecker<RetainCountChecker>();
1429  Chk->TrackObjCAndCFObjects = true;
1430 }
1431 
1432 // FIXME: remove this, hack for backwards compatibility:
1433 // it should be possible to enable the NS/CF retain count checker as
1434 // osx.cocoa.RetainCount, and it should be possible to disable
1435 // osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false.
1437  auto I = Options.Config.find("osx.cocoa.RetainCount:CheckOSObject");
1438  if (I != Options.Config.end())
1439  return I->getValue() == "false";
1440  return false;
1441 }
1442 
1443 void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
1444  auto *Chk = Mgr.registerChecker<RetainCountChecker>();
1446  Chk->TrackOSObjects = true;
1447 }
Indicates that the tracked object is a generalized object.
Indicates that the tracked object is a CF object.
const BlockDecl * getBlockDecl() const
Definition: Expr.h:5198
ProgramStateRef handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred, const ProgramPointTag *Tag, CheckerContext &Ctx, SymbolRef Sym, RefVal V, const ReturnStmt *S=nullptr) const
Represents a function declaration or definition.
Definition: Decl.h:1738
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:530
There is no effect.
ObjKind
Determines the object kind of a tracked object.
A (possibly-)qualified type.
Definition: Type.h:638
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:95
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2560
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
Definition: Decl.h:3977
ProgramStateRef handleSymbolDeath(ProgramStateRef state, SymbolRef sid, RefVal V, SmallVectorImpl< SymbolRef > &Leaked) const
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
The argument has its reference count decreased by 1 to model a transferred bridge cast under ARC...
bool evalCall(const CallExpr *CE, CheckerContext &C) const
Stmt - This represents one statement.
Definition: Stmt.h:66
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:505
Bridging via __bridge, which does nothing but reinterpret the bits.
static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym)
All typestate tracking of the object ceases.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
The argument has its reference count increased by 1.
StringRef P
static SmallVector< ProgramStateRef, 2 > updateOutParameters(ProgramStateRef State, const RetainSummary &Summ, const CallEvent &CE)
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const
The argument is treated as if an -autorelease message had been sent to the referenced object...
const ProgramStateRef & getState() const
Indicates that no retain count information is tracked for the return value.
static bool isSmartPtrField(const MemRegion *MR)
static bool isPointerToObject(QualType QT)
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
Definition: CallEvent.h:255
static RetEffect MakeNoRet()
Represents a variable declaration or definition.
Definition: Decl.h:813
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:85
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6755
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
const Decl & getCodeDecl() const
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
virtual const MemRegion * getOriginRegion() const
Find the region from which this symbol originates.
Definition: SymExpr.h:102
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
Represents a parameter to a function.
Definition: Decl.h:1550
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
Symbolic value.
Definition: SymExpr.h:30
const MemRegion * getSuperRegion() const
Definition: MemRegion.h:448
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...
MemRegionManager & getRegionManager()
Definition: SValBuilder.h:175
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
LineState State
void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange, RefVal::Kind ErrorKind, SymbolRef Sym, CheckerContext &C) const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:50
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
Definition: ExprObjC.h:171
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
The argument has its reference count decreased by 1.
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +0 v...
void checkPostCall(const CallEvent &Call, CheckerContext &C) const
Indicates that the return value is an owned object when the receiver is also a tracked object...
child_range children()
Definition: Stmt.cpp:237
const LocationContext * getLocationContext() const
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...
bool isUnknown() const
Definition: SVals.h:137
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:415
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3005
Represents an ObjC class declaration.
Definition: DeclObjC.h:1172
Bridging via __bridge_transfer, which transfers ownership of an Objective-C pointer into ARC...
static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx, const RefVal *TrackedValue)
Whether the tracked value should be escaped on a given call.
virtual QualType getType() const =0
virtual ArrayRef< ParmVarDecl * > parameters() const =0
Return call&#39;s formal parameters.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:127
bool hasAttr() const
Definition: DeclBase.h:531
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to &#39;true&#39;.
void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1613
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...
IvarAccessHistory getIvarAccessHistory() const
Returns what the analyzer knows about direct accesses to a particular instance variable.
const RegionTy * getAs() const
Definition: MemRegion.h:1231
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:764
The argument is treated as potentially escaping, meaning that even when its reference count hits 0 it...
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const
This represents one expression.
Definition: Expr.h:107
static bool shouldEscapeRegion(const MemRegion *R)
A value escapes in these possible cases:
bool TrackObjCAndCFObjects
Track Objective-C and CoreFoundation objects.
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to...
Definition: Type.cpp:1598
bool isObjCRetainableType() const
Definition: Type.cpp:3921
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:5184
#define bool
Definition: stdbool.h:31
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:288
void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const override
See CheckerManager::runCheckersForPrintState.
QualType getType() const
Definition: Expr.h:129
The argument is treated as if the referenced object was deallocated.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2443
ExplodedNode * checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C, ExplodedNode *Pred, RetEffect RE, RefVal X, SymbolRef Sym, ProgramStateRef state) const
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:904
void processObjCLiterals(CheckerContext &C, const Expr *Ex) const
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl...
ObjCBridgeCastKind getBridgeKind() const
Determine which kind of bridge is being performed via this cast.
Definition: ExprObjC.h:1602
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:703
ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym, RefVal V, ArgEffect E, RefVal::Kind &hasErr, CheckerContext &C) const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:112
const VarDecl * getDecl() const
Definition: MemRegion.h:953
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
static bool isISLObjectRef(QualType Ty)
Kind
ArgEffectKind getKind() const
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique &#39;name&#39;.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
Expr * getRetValue()
Definition: Stmt.h:2476
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
Definition: ProgramPoint.h:40
Indicates that the tracked object is an Objective-C object.
const MemRegion * getAsRegion() const
Definition: SVals.cpp:151
ConfigTable Config
A key-value table of use-specified configuration values.
ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, bool Assumption) const
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2285
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
Performs the combined functionality of DecRef and StopTrackingHard.
A class responsible for cleaning up unused symbols.
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:117
static bool hasPrevCheckOSObjectOptionDisabled(AnalyzerOptions &Options)
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
An Objective-C "bridged" cast expression, which casts between Objective-C pointers and C pointers...
Definition: ExprObjC.h:1575
static ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, RefVal Val)
Dataflow Directional Tag Classes.
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
Definition: CallEvent.cpp:408
const VarRegion * getVarRegion(const VarDecl *D, const LocationContext *LC)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...
Definition: MemRegion.cpp:846
static Optional< RefVal > refValFromRetEffect(RetEffect RE, QualType ResultTy)
ProgramStateRef checkRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion *> ExplicitRegions, ArrayRef< const MemRegion *> Regions, const LocationContext *LCtx, const CallEvent *Call) const
ExplodedNode * processLeaks(ProgramStateRef state, SmallVectorImpl< SymbolRef > &Leaked, CheckerContext &Ctx, ExplodedNode *Pred=nullptr) const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:971
const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
Definition: MemRegion.cpp:1194
static RefVal makeOwned(ObjKind o, QualType t)
Create a state for an object whose lifetime is the responsibility of the current function, at least partially.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition: Expr.cpp:1396
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:171
Bridging via __bridge_retain, which makes an ARC object available as a +1 C pointer.
AnalyzerOptions & getAnalyzerOptions()
const Decl * getDecl() const
Represents a pointer to an Objective C object.
Definition: Type.h:5797
const StackFrameContext * getStackFrame() const
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
const ProgramStateRef & getState() const
void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const
const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)
bool hasStackStorage() const
Definition: MemRegion.cpp:1138
Stores options for the analyzer from the command line.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:513
QualType getResultType() const
Returns the result type, adjusted for references.
Definition: CallEvent.cpp:70
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:13969
ArgEffect withKind(ArgEffectKind NewK)
All typestate tracking of the object ceases.
static RefVal makeNotOwned(ObjKind o, QualType t)
Create a state for an object whose lifetime is not the responsibility of the current function...
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...
void checkSummary(const RetainSummary &Summ, const CallEvent &Call, CheckerContext &C) const
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2403
const RefCountBug & errorKindToBugKind(RefVal::Kind ErrorKind, SymbolRef Sym) const
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:954
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Definition: CallEvent.cpp:401
QualType getType() const
Definition: Decl.h:648
void processSummaryOfInlined(const RetainSummary &Summ, const CallEvent &Call, CheckerContext &C) const
A trivial tuple used to represent a source range.
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Definition: Checker.h:509
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
const LocationContext * getLocationContext() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3055
const LangOptions & getLangOpts() const
Definition: ASTContext.h:707
static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx)
GetReturnType - Used to get the return type of a message expression or function call with the intenti...
RetEffect summarizes a call&#39;s retain/release behavior with respect to its return value.