1226586Sdim//==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
2226586Sdim//
3226586Sdim//                     The LLVM Compiler Infrastructure
4226586Sdim//
5226586Sdim// This file is distributed under the University of Illinois Open Source
6226586Sdim// License. See LICENSE.TXT for details.
7226586Sdim//
8226586Sdim//===----------------------------------------------------------------------===//
9226586Sdim//
10226586Sdim//  This file defines the methods for RetainCountChecker, which implements
11226586Sdim//  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12226586Sdim//
13226586Sdim//===----------------------------------------------------------------------===//
14226586Sdim
15226586Sdim#include "ClangSACheckers.h"
16249423Sdim#include "clang/AST/Attr.h"
17249423Sdim#include "clang/AST/DeclCXX.h"
18226586Sdim#include "clang/AST/DeclObjC.h"
19249423Sdim#include "clang/AST/ParentMap.h"
20249423Sdim#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
21226586Sdim#include "clang/Basic/LangOptions.h"
22226586Sdim#include "clang/Basic/SourceManager.h"
23249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
24249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
25226586Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
26226586Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h"
27239462Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
28226586Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
29226586Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
30226586Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
31226586Sdim#include "llvm/ADT/DenseMap.h"
32226586Sdim#include "llvm/ADT/FoldingSet.h"
33226586Sdim#include "llvm/ADT/ImmutableList.h"
34226586Sdim#include "llvm/ADT/ImmutableMap.h"
35249423Sdim#include "llvm/ADT/STLExtras.h"
36234353Sdim#include "llvm/ADT/SmallString.h"
37226586Sdim#include "llvm/ADT/StringExtras.h"
38226586Sdim#include <cstdarg>
39226586Sdim
40251662Sdim#include "AllocationDiagnostics.h"
41251662Sdim
42226586Sdimusing namespace clang;
43226586Sdimusing namespace ento;
44226586Sdimusing llvm::StrInStrNoCase;
45226586Sdim
46226586Sdim//===----------------------------------------------------------------------===//
47226586Sdim// Primitives used for constructing summaries for function/method calls.
48226586Sdim//===----------------------------------------------------------------------===//
49226586Sdim
50226586Sdim/// ArgEffect is used to summarize a function/method call's effect on a
51226586Sdim/// particular argument.
52226586Sdimenum ArgEffect { DoNothing, Autorelease, Dealloc, DecRef, DecRefMsg,
53226586Sdim                 DecRefBridgedTransfered,
54226586Sdim                 IncRefMsg, IncRef, MakeCollectable, MayEscape,
55226586Sdim
56243830Sdim                 // Stop tracking the argument - the effect of the call is
57243830Sdim                 // unknown.
58243830Sdim                 StopTracking,
59243830Sdim
60243830Sdim                 // In some cases, we obtain a better summary for this checker
61243830Sdim                 // by looking at the call site than by inlining the function.
62243830Sdim                 // Signifies that we should stop tracking the symbol even if
63243830Sdim                 // the function is inlined.
64243830Sdim                 StopTrackingHard,
65243830Sdim
66243830Sdim                 // The function decrements the reference count and the checker
67243830Sdim                 // should stop tracking the argument.
68243830Sdim                 DecRefAndStopTrackingHard, DecRefMsgAndStopTrackingHard
69243830Sdim               };
70243830Sdim
71226586Sdimnamespace llvm {
72226586Sdimtemplate <> struct FoldingSetTrait<ArgEffect> {
73226586Sdimstatic inline void Profile(const ArgEffect X, FoldingSetNodeID& ID) {
74226586Sdim  ID.AddInteger((unsigned) X);
75226586Sdim}
76226586Sdim};
77226586Sdim} // end llvm namespace
78226586Sdim
79226586Sdim/// ArgEffects summarizes the effects of a function/method call on all of
80226586Sdim/// its arguments.
81226586Sdimtypedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
82226586Sdim
83226586Sdimnamespace {
84226586Sdim
85226586Sdim///  RetEffect is used to summarize a function/method call's behavior with
86226586Sdim///  respect to its return value.
87226586Sdimclass RetEffect {
88226586Sdimpublic:
89226586Sdim  enum Kind { NoRet, OwnedSymbol, OwnedAllocatedSymbol,
90226586Sdim              NotOwnedSymbol, GCNotOwnedSymbol, ARCNotOwnedSymbol,
91243830Sdim              OwnedWhenTrackedReceiver,
92243830Sdim              // Treat this function as returning a non-tracked symbol even if
93243830Sdim              // the function has been inlined. This is used where the call
94243830Sdim              // site summary is more presise than the summary indirectly produced
95243830Sdim              // by inlining the function
96243830Sdim              NoRetHard
97243830Sdim            };
98226586Sdim
99226586Sdim  enum ObjKind { CF, ObjC, AnyObj };
100226586Sdim
101226586Sdimprivate:
102226586Sdim  Kind K;
103226586Sdim  ObjKind O;
104226586Sdim
105226586Sdim  RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
106226586Sdim
107226586Sdimpublic:
108226586Sdim  Kind getKind() const { return K; }
109226586Sdim
110226586Sdim  ObjKind getObjKind() const { return O; }
111226586Sdim
112226586Sdim  bool isOwned() const {
113226586Sdim    return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
114226586Sdim           K == OwnedWhenTrackedReceiver;
115226586Sdim  }
116226586Sdim
117226586Sdim  bool operator==(const RetEffect &Other) const {
118226586Sdim    return K == Other.K && O == Other.O;
119226586Sdim  }
120226586Sdim
121226586Sdim  static RetEffect MakeOwnedWhenTrackedReceiver() {
122226586Sdim    return RetEffect(OwnedWhenTrackedReceiver, ObjC);
123226586Sdim  }
124226586Sdim
125226586Sdim  static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
126226586Sdim    return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
127226586Sdim  }
128226586Sdim  static RetEffect MakeNotOwned(ObjKind o) {
129226586Sdim    return RetEffect(NotOwnedSymbol, o);
130226586Sdim  }
131226586Sdim  static RetEffect MakeGCNotOwned() {
132226586Sdim    return RetEffect(GCNotOwnedSymbol, ObjC);
133226586Sdim  }
134226586Sdim  static RetEffect MakeARCNotOwned() {
135226586Sdim    return RetEffect(ARCNotOwnedSymbol, ObjC);
136226586Sdim  }
137226586Sdim  static RetEffect MakeNoRet() {
138226586Sdim    return RetEffect(NoRet);
139226586Sdim  }
140243830Sdim  static RetEffect MakeNoRetHard() {
141243830Sdim    return RetEffect(NoRetHard);
142243830Sdim  }
143234353Sdim
144234353Sdim  void Profile(llvm::FoldingSetNodeID& ID) const {
145234353Sdim    ID.AddInteger((unsigned) K);
146234353Sdim    ID.AddInteger((unsigned) O);
147234353Sdim  }
148226586Sdim};
149226586Sdim
150226586Sdim//===----------------------------------------------------------------------===//
151226586Sdim// Reference-counting logic (typestate + counts).
152226586Sdim//===----------------------------------------------------------------------===//
153226586Sdim
154226586Sdimclass RefVal {
155226586Sdimpublic:
156226586Sdim  enum Kind {
157226586Sdim    Owned = 0, // Owning reference.
158226586Sdim    NotOwned,  // Reference is not owned by still valid (not freed).
159226586Sdim    Released,  // Object has been released.
160226586Sdim    ReturnedOwned, // Returned object passes ownership to caller.
161226586Sdim    ReturnedNotOwned, // Return object does not pass ownership to caller.
162226586Sdim    ERROR_START,
163226586Sdim    ErrorDeallocNotOwned, // -dealloc called on non-owned object.
164226586Sdim    ErrorDeallocGC, // Calling -dealloc with GC enabled.
165226586Sdim    ErrorUseAfterRelease, // Object used after released.
166226586Sdim    ErrorReleaseNotOwned, // Release of an object that was not owned.
167226586Sdim    ERROR_LEAK_START,
168226586Sdim    ErrorLeak,  // A memory leak due to excessive reference counts.
169226586Sdim    ErrorLeakReturned, // A memory leak due to the returning method not having
170226586Sdim                       // the correct naming conventions.
171226586Sdim    ErrorGCLeakReturned,
172226586Sdim    ErrorOverAutorelease,
173226586Sdim    ErrorReturnedNotOwned
174226586Sdim  };
175226586Sdim
176226586Sdimprivate:
177226586Sdim  Kind kind;
178226586Sdim  RetEffect::ObjKind okind;
179226586Sdim  unsigned Cnt;
180226586Sdim  unsigned ACnt;
181226586Sdim  QualType T;
182226586Sdim
183226586Sdim  RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
184226586Sdim  : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
185226586Sdim
186226586Sdimpublic:
187226586Sdim  Kind getKind() const { return kind; }
188226586Sdim
189226586Sdim  RetEffect::ObjKind getObjKind() const { return okind; }
190226586Sdim
191226586Sdim  unsigned getCount() const { return Cnt; }
192226586Sdim  unsigned getAutoreleaseCount() const { return ACnt; }
193226586Sdim  unsigned getCombinedCounts() const { return Cnt + ACnt; }
194226586Sdim  void clearCounts() { Cnt = 0; ACnt = 0; }
195226586Sdim  void setCount(unsigned i) { Cnt = i; }
196226586Sdim  void setAutoreleaseCount(unsigned i) { ACnt = i; }
197226586Sdim
198226586Sdim  QualType getType() const { return T; }
199226586Sdim
200226586Sdim  bool isOwned() const {
201226586Sdim    return getKind() == Owned;
202226586Sdim  }
203226586Sdim
204226586Sdim  bool isNotOwned() const {
205226586Sdim    return getKind() == NotOwned;
206226586Sdim  }
207226586Sdim
208226586Sdim  bool isReturnedOwned() const {
209226586Sdim    return getKind() == ReturnedOwned;
210226586Sdim  }
211226586Sdim
212226586Sdim  bool isReturnedNotOwned() const {
213226586Sdim    return getKind() == ReturnedNotOwned;
214226586Sdim  }
215226586Sdim
216226586Sdim  static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
217226586Sdim                          unsigned Count = 1) {
218226586Sdim    return RefVal(Owned, o, Count, 0, t);
219226586Sdim  }
220226586Sdim
221226586Sdim  static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
222226586Sdim                             unsigned Count = 0) {
223226586Sdim    return RefVal(NotOwned, o, Count, 0, t);
224226586Sdim  }
225226586Sdim
226226586Sdim  // Comparison, profiling, and pretty-printing.
227226586Sdim
228226586Sdim  bool operator==(const RefVal& X) const {
229226586Sdim    return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
230226586Sdim  }
231226586Sdim
232226586Sdim  RefVal operator-(size_t i) const {
233226586Sdim    return RefVal(getKind(), getObjKind(), getCount() - i,
234226586Sdim                  getAutoreleaseCount(), getType());
235226586Sdim  }
236226586Sdim
237226586Sdim  RefVal operator+(size_t i) const {
238226586Sdim    return RefVal(getKind(), getObjKind(), getCount() + i,
239226586Sdim                  getAutoreleaseCount(), getType());
240226586Sdim  }
241226586Sdim
242226586Sdim  RefVal operator^(Kind k) const {
243226586Sdim    return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
244226586Sdim                  getType());
245226586Sdim  }
246226586Sdim
247226586Sdim  RefVal autorelease() const {
248226586Sdim    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
249226586Sdim                  getType());
250226586Sdim  }
251226586Sdim
252226586Sdim  void Profile(llvm::FoldingSetNodeID& ID) const {
253226586Sdim    ID.AddInteger((unsigned) kind);
254226586Sdim    ID.AddInteger(Cnt);
255226586Sdim    ID.AddInteger(ACnt);
256226586Sdim    ID.Add(T);
257226586Sdim  }
258226586Sdim
259226586Sdim  void print(raw_ostream &Out) const;
260226586Sdim};
261226586Sdim
262226586Sdimvoid RefVal::print(raw_ostream &Out) const {
263226586Sdim  if (!T.isNull())
264226586Sdim    Out << "Tracked " << T.getAsString() << '/';
265226586Sdim
266226586Sdim  switch (getKind()) {
267226586Sdim    default: llvm_unreachable("Invalid RefVal kind");
268226586Sdim    case Owned: {
269226586Sdim      Out << "Owned";
270226586Sdim      unsigned cnt = getCount();
271226586Sdim      if (cnt) Out << " (+ " << cnt << ")";
272226586Sdim      break;
273226586Sdim    }
274226586Sdim
275226586Sdim    case NotOwned: {
276226586Sdim      Out << "NotOwned";
277226586Sdim      unsigned cnt = getCount();
278226586Sdim      if (cnt) Out << " (+ " << cnt << ")";
279226586Sdim      break;
280226586Sdim    }
281226586Sdim
282226586Sdim    case ReturnedOwned: {
283226586Sdim      Out << "ReturnedOwned";
284226586Sdim      unsigned cnt = getCount();
285226586Sdim      if (cnt) Out << " (+ " << cnt << ")";
286226586Sdim      break;
287226586Sdim    }
288226586Sdim
289226586Sdim    case ReturnedNotOwned: {
290226586Sdim      Out << "ReturnedNotOwned";
291226586Sdim      unsigned cnt = getCount();
292226586Sdim      if (cnt) Out << " (+ " << cnt << ")";
293226586Sdim      break;
294226586Sdim    }
295226586Sdim
296226586Sdim    case Released:
297226586Sdim      Out << "Released";
298226586Sdim      break;
299226586Sdim
300226586Sdim    case ErrorDeallocGC:
301226586Sdim      Out << "-dealloc (GC)";
302226586Sdim      break;
303226586Sdim
304226586Sdim    case ErrorDeallocNotOwned:
305226586Sdim      Out << "-dealloc (not-owned)";
306226586Sdim      break;
307226586Sdim
308226586Sdim    case ErrorLeak:
309226586Sdim      Out << "Leaked";
310226586Sdim      break;
311226586Sdim
312226586Sdim    case ErrorLeakReturned:
313226586Sdim      Out << "Leaked (Bad naming)";
314226586Sdim      break;
315226586Sdim
316226586Sdim    case ErrorGCLeakReturned:
317226586Sdim      Out << "Leaked (GC-ed at return)";
318226586Sdim      break;
319226586Sdim
320226586Sdim    case ErrorUseAfterRelease:
321226586Sdim      Out << "Use-After-Release [ERROR]";
322226586Sdim      break;
323226586Sdim
324226586Sdim    case ErrorReleaseNotOwned:
325226586Sdim      Out << "Release of Not-Owned [ERROR]";
326226586Sdim      break;
327226586Sdim
328226586Sdim    case RefVal::ErrorOverAutorelease:
329251662Sdim      Out << "Over-autoreleased";
330226586Sdim      break;
331226586Sdim
332226586Sdim    case RefVal::ErrorReturnedNotOwned:
333226586Sdim      Out << "Non-owned object returned instead of owned";
334226586Sdim      break;
335226586Sdim  }
336226586Sdim
337226586Sdim  if (ACnt) {
338226586Sdim    Out << " [ARC +" << ACnt << ']';
339226586Sdim  }
340226586Sdim}
341226586Sdim} //end anonymous namespace
342226586Sdim
343226586Sdim//===----------------------------------------------------------------------===//
344226586Sdim// RefBindings - State used to track object reference counts.
345226586Sdim//===----------------------------------------------------------------------===//
346226586Sdim
347243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
348226586Sdim
349239462Sdimstatic inline const RefVal *getRefBinding(ProgramStateRef State,
350239462Sdim                                          SymbolRef Sym) {
351239462Sdim  return State->get<RefBindings>(Sym);
352239462Sdim}
353239462Sdim
354239462Sdimstatic inline ProgramStateRef setRefBinding(ProgramStateRef State,
355239462Sdim                                            SymbolRef Sym, RefVal Val) {
356239462Sdim  return State->set<RefBindings>(Sym, Val);
357239462Sdim}
358239462Sdim
359239462Sdimstatic ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
360239462Sdim  return State->remove<RefBindings>(Sym);
361239462Sdim}
362239462Sdim
363226586Sdim//===----------------------------------------------------------------------===//
364226586Sdim// Function/Method behavior summaries.
365226586Sdim//===----------------------------------------------------------------------===//
366226586Sdim
367226586Sdimnamespace {
368226586Sdimclass RetainSummary {
369234353Sdim  /// Args - a map of (index, ArgEffect) pairs, where index
370226586Sdim  ///  specifies the argument (starting from 0).  This can be sparsely
371226586Sdim  ///  populated; arguments with no entry in Args use 'DefaultArgEffect'.
372226586Sdim  ArgEffects Args;
373226586Sdim
374226586Sdim  /// DefaultArgEffect - The default ArgEffect to apply to arguments that
375226586Sdim  ///  do not have an entry in Args.
376234353Sdim  ArgEffect DefaultArgEffect;
377226586Sdim
378226586Sdim  /// Receiver - If this summary applies to an Objective-C message expression,
379226586Sdim  ///  this is the effect applied to the state of the receiver.
380234353Sdim  ArgEffect Receiver;
381226586Sdim
382226586Sdim  /// Ret - The effect on the return value.  Used to indicate if the
383226586Sdim  ///  function/method call returns a new tracked symbol.
384234353Sdim  RetEffect Ret;
385226586Sdim
386226586Sdimpublic:
387226586Sdim  RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
388226586Sdim                ArgEffect ReceiverEff)
389226586Sdim    : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
390226586Sdim
391226586Sdim  /// getArg - Return the argument effect on the argument specified by
392226586Sdim  ///  idx (starting from 0).
393226586Sdim  ArgEffect getArg(unsigned idx) const {
394226586Sdim    if (const ArgEffect *AE = Args.lookup(idx))
395226586Sdim      return *AE;
396226586Sdim
397226586Sdim    return DefaultArgEffect;
398226586Sdim  }
399226586Sdim
400226586Sdim  void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
401226586Sdim    Args = af.add(Args, idx, e);
402226586Sdim  }
403226586Sdim
404226586Sdim  /// setDefaultArgEffect - Set the default argument effect.
405226586Sdim  void setDefaultArgEffect(ArgEffect E) {
406226586Sdim    DefaultArgEffect = E;
407226586Sdim  }
408226586Sdim
409226586Sdim  /// getRetEffect - Returns the effect on the return value of the call.
410226586Sdim  RetEffect getRetEffect() const { return Ret; }
411226586Sdim
412226586Sdim  /// setRetEffect - Set the effect of the return value of the call.
413226586Sdim  void setRetEffect(RetEffect E) { Ret = E; }
414226586Sdim
415226586Sdim
416226586Sdim  /// Sets the effect on the receiver of the message.
417226586Sdim  void setReceiverEffect(ArgEffect e) { Receiver = e; }
418226586Sdim
419226586Sdim  /// getReceiverEffect - Returns the effect on the receiver of the call.
420226586Sdim  ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
421226586Sdim  ArgEffect getReceiverEffect() const { return Receiver; }
422226586Sdim
423226586Sdim  /// Test if two retain summaries are identical. Note that merely equivalent
424226586Sdim  /// summaries are not necessarily identical (for example, if an explicit
425226586Sdim  /// argument effect matches the default effect).
426226586Sdim  bool operator==(const RetainSummary &Other) const {
427226586Sdim    return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
428226586Sdim           Receiver == Other.Receiver && Ret == Other.Ret;
429226586Sdim  }
430234353Sdim
431234353Sdim  /// Profile this summary for inclusion in a FoldingSet.
432234353Sdim  void Profile(llvm::FoldingSetNodeID& ID) const {
433234353Sdim    ID.Add(Args);
434234353Sdim    ID.Add(DefaultArgEffect);
435234353Sdim    ID.Add(Receiver);
436234353Sdim    ID.Add(Ret);
437234353Sdim  }
438234353Sdim
439234353Sdim  /// A retain summary is simple if it has no ArgEffects other than the default.
440234353Sdim  bool isSimple() const {
441234353Sdim    return Args.isEmpty();
442234353Sdim  }
443239462Sdim
444239462Sdimprivate:
445239462Sdim  ArgEffects getArgEffects() const { return Args; }
446239462Sdim  ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
447239462Sdim
448239462Sdim  friend class RetainSummaryManager;
449226586Sdim};
450226586Sdim} // end anonymous namespace
451226586Sdim
452226586Sdim//===----------------------------------------------------------------------===//
453226586Sdim// Data structures for constructing summaries.
454226586Sdim//===----------------------------------------------------------------------===//
455226586Sdim
456226586Sdimnamespace {
457226586Sdimclass ObjCSummaryKey {
458226586Sdim  IdentifierInfo* II;
459226586Sdim  Selector S;
460226586Sdimpublic:
461226586Sdim  ObjCSummaryKey(IdentifierInfo* ii, Selector s)
462226586Sdim    : II(ii), S(s) {}
463226586Sdim
464226586Sdim  ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
465226586Sdim    : II(d ? d->getIdentifier() : 0), S(s) {}
466226586Sdim
467226586Sdim  ObjCSummaryKey(Selector s)
468226586Sdim    : II(0), S(s) {}
469226586Sdim
470234353Sdim  IdentifierInfo *getIdentifier() const { return II; }
471226586Sdim  Selector getSelector() const { return S; }
472226586Sdim};
473226586Sdim}
474226586Sdim
475226586Sdimnamespace llvm {
476226586Sdimtemplate <> struct DenseMapInfo<ObjCSummaryKey> {
477226586Sdim  static inline ObjCSummaryKey getEmptyKey() {
478226586Sdim    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
479226586Sdim                          DenseMapInfo<Selector>::getEmptyKey());
480226586Sdim  }
481226586Sdim
482226586Sdim  static inline ObjCSummaryKey getTombstoneKey() {
483226586Sdim    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
484226586Sdim                          DenseMapInfo<Selector>::getTombstoneKey());
485226586Sdim  }
486226586Sdim
487226586Sdim  static unsigned getHashValue(const ObjCSummaryKey &V) {
488239462Sdim    typedef std::pair<IdentifierInfo*, Selector> PairTy;
489239462Sdim    return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
490239462Sdim                                                     V.getSelector()));
491226586Sdim  }
492226586Sdim
493226586Sdim  static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
494239462Sdim    return LHS.getIdentifier() == RHS.getIdentifier() &&
495239462Sdim           LHS.getSelector() == RHS.getSelector();
496226586Sdim  }
497226586Sdim
498226586Sdim};
499226586Sdimtemplate <>
500226586Sdimstruct isPodLike<ObjCSummaryKey> { static const bool value = true; };
501226586Sdim} // end llvm namespace
502226586Sdim
503226586Sdimnamespace {
504226586Sdimclass ObjCSummaryCache {
505226586Sdim  typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
506226586Sdim  MapTy M;
507226586Sdimpublic:
508226586Sdim  ObjCSummaryCache() {}
509226586Sdim
510226586Sdim  const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
511226586Sdim    // Do a lookup with the (D,S) pair.  If we find a match return
512226586Sdim    // the iterator.
513226586Sdim    ObjCSummaryKey K(D, S);
514226586Sdim    MapTy::iterator I = M.find(K);
515226586Sdim
516239462Sdim    if (I != M.end())
517226586Sdim      return I->second;
518239462Sdim    if (!D)
519239462Sdim      return NULL;
520226586Sdim
521226586Sdim    // Walk the super chain.  If we find a hit with a parent, we'll end
522226586Sdim    // up returning that summary.  We actually allow that key (null,S), as
523226586Sdim    // we cache summaries for the null ObjCInterfaceDecl* to allow us to
524226586Sdim    // generate initial summaries without having to worry about NSObject
525226586Sdim    // being declared.
526226586Sdim    // FIXME: We may change this at some point.
527226586Sdim    for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
528226586Sdim      if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
529226586Sdim        break;
530226586Sdim
531226586Sdim      if (!C)
532226586Sdim        return NULL;
533226586Sdim    }
534226586Sdim
535226586Sdim    // Cache the summary with original key to make the next lookup faster
536226586Sdim    // and return the iterator.
537226586Sdim    const RetainSummary *Summ = I->second;
538226586Sdim    M[K] = Summ;
539226586Sdim    return Summ;
540226586Sdim  }
541226586Sdim
542234353Sdim  const RetainSummary *find(IdentifierInfo* II, Selector S) {
543226586Sdim    // FIXME: Class method lookup.  Right now we dont' have a good way
544226586Sdim    // of going between IdentifierInfo* and the class hierarchy.
545226586Sdim    MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
546226586Sdim
547226586Sdim    if (I == M.end())
548226586Sdim      I = M.find(ObjCSummaryKey(S));
549226586Sdim
550226586Sdim    return I == M.end() ? NULL : I->second;
551226586Sdim  }
552226586Sdim
553226586Sdim  const RetainSummary *& operator[](ObjCSummaryKey K) {
554226586Sdim    return M[K];
555226586Sdim  }
556226586Sdim
557226586Sdim  const RetainSummary *& operator[](Selector S) {
558226586Sdim    return M[ ObjCSummaryKey(S) ];
559226586Sdim  }
560226586Sdim};
561226586Sdim} // end anonymous namespace
562226586Sdim
563226586Sdim//===----------------------------------------------------------------------===//
564226586Sdim// Data structures for managing collections of summaries.
565226586Sdim//===----------------------------------------------------------------------===//
566226586Sdim
567226586Sdimnamespace {
568226586Sdimclass RetainSummaryManager {
569226586Sdim
570226586Sdim  //==-----------------------------------------------------------------==//
571226586Sdim  //  Typedefs.
572226586Sdim  //==-----------------------------------------------------------------==//
573226586Sdim
574226586Sdim  typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
575226586Sdim          FuncSummariesTy;
576226586Sdim
577226586Sdim  typedef ObjCSummaryCache ObjCMethodSummariesTy;
578226586Sdim
579234353Sdim  typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
580234353Sdim
581226586Sdim  //==-----------------------------------------------------------------==//
582226586Sdim  //  Data.
583226586Sdim  //==-----------------------------------------------------------------==//
584226586Sdim
585226586Sdim  /// Ctx - The ASTContext object for the analyzed ASTs.
586226586Sdim  ASTContext &Ctx;
587226586Sdim
588226586Sdim  /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
589226586Sdim  const bool GCEnabled;
590226586Sdim
591226586Sdim  /// Records whether or not the analyzed code runs in ARC mode.
592226586Sdim  const bool ARCEnabled;
593226586Sdim
594226586Sdim  /// FuncSummaries - A map from FunctionDecls to summaries.
595226586Sdim  FuncSummariesTy FuncSummaries;
596226586Sdim
597226586Sdim  /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
598226586Sdim  ///  to summaries.
599226586Sdim  ObjCMethodSummariesTy ObjCClassMethodSummaries;
600226586Sdim
601226586Sdim  /// ObjCMethodSummaries - A map from selectors to summaries.
602226586Sdim  ObjCMethodSummariesTy ObjCMethodSummaries;
603226586Sdim
604226586Sdim  /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
605226586Sdim  ///  and all other data used by the checker.
606226586Sdim  llvm::BumpPtrAllocator BPAlloc;
607226586Sdim
608226586Sdim  /// AF - A factory for ArgEffects objects.
609226586Sdim  ArgEffects::Factory AF;
610226586Sdim
611226586Sdim  /// ScratchArgs - A holding buffer for construct ArgEffects.
612234353Sdim  ArgEffects ScratchArgs;
613226586Sdim
614226586Sdim  /// ObjCAllocRetE - Default return effect for methods returning Objective-C
615226586Sdim  ///  objects.
616226586Sdim  RetEffect ObjCAllocRetE;
617226586Sdim
618226586Sdim  /// ObjCInitRetE - Default return effect for init methods returning
619226586Sdim  ///   Objective-C objects.
620226586Sdim  RetEffect ObjCInitRetE;
621226586Sdim
622234353Sdim  /// SimpleSummaries - Used for uniquing summaries that don't have special
623234353Sdim  /// effects.
624234353Sdim  llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
625226586Sdim
626226586Sdim  //==-----------------------------------------------------------------==//
627226586Sdim  //  Methods.
628226586Sdim  //==-----------------------------------------------------------------==//
629226586Sdim
630226586Sdim  /// getArgEffects - Returns a persistent ArgEffects object based on the
631226586Sdim  ///  data in ScratchArgs.
632226586Sdim  ArgEffects getArgEffects();
633226586Sdim
634226586Sdim  enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
635226586Sdim
636234353Sdim  const RetainSummary *getUnarySummary(const FunctionType* FT,
637226586Sdim                                       UnaryFuncKind func);
638226586Sdim
639234353Sdim  const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
640234353Sdim  const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
641234353Sdim  const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
642226586Sdim
643234353Sdim  const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
644226586Sdim
645234353Sdim  const RetainSummary *getPersistentSummary(RetEffect RetEff,
646226586Sdim                                            ArgEffect ReceiverEff = DoNothing,
647226586Sdim                                            ArgEffect DefaultEff = MayEscape) {
648234353Sdim    RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
649234353Sdim    return getPersistentSummary(Summ);
650226586Sdim  }
651226586Sdim
652239462Sdim  const RetainSummary *getDoNothingSummary() {
653239462Sdim    return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
654239462Sdim  }
655239462Sdim
656234353Sdim  const RetainSummary *getDefaultSummary() {
657234353Sdim    return getPersistentSummary(RetEffect::MakeNoRet(),
658234353Sdim                                DoNothing, MayEscape);
659234353Sdim  }
660234353Sdim
661226586Sdim  const RetainSummary *getPersistentStopSummary() {
662234353Sdim    return getPersistentSummary(RetEffect::MakeNoRet(),
663234353Sdim                                StopTracking, StopTracking);
664226586Sdim  }
665226586Sdim
666226586Sdim  void InitializeClassMethodSummaries();
667226586Sdim  void InitializeMethodSummaries();
668226586Sdimprivate:
669226586Sdim  void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
670226586Sdim    ObjCClassMethodSummaries[S] = Summ;
671226586Sdim  }
672226586Sdim
673226586Sdim  void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
674226586Sdim    ObjCMethodSummaries[S] = Summ;
675226586Sdim  }
676226586Sdim
677234353Sdim  void addClassMethSummary(const char* Cls, const char* name,
678234353Sdim                           const RetainSummary *Summ, bool isNullary = true) {
679226586Sdim    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
680234353Sdim    Selector S = isNullary ? GetNullarySelector(name, Ctx)
681234353Sdim                           : GetUnarySelector(name, Ctx);
682226586Sdim    ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
683226586Sdim  }
684226586Sdim
685226586Sdim  void addInstMethSummary(const char* Cls, const char* nullaryName,
686226586Sdim                          const RetainSummary *Summ) {
687226586Sdim    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
688226586Sdim    Selector S = GetNullarySelector(nullaryName, Ctx);
689226586Sdim    ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
690226586Sdim  }
691226586Sdim
692226586Sdim  Selector generateSelector(va_list argp) {
693226586Sdim    SmallVector<IdentifierInfo*, 10> II;
694226586Sdim
695226586Sdim    while (const char* s = va_arg(argp, const char*))
696226586Sdim      II.push_back(&Ctx.Idents.get(s));
697226586Sdim
698226586Sdim    return Ctx.Selectors.getSelector(II.size(), &II[0]);
699226586Sdim  }
700226586Sdim
701226586Sdim  void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
702226586Sdim                        const RetainSummary * Summ, va_list argp) {
703226586Sdim    Selector S = generateSelector(argp);
704226586Sdim    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
705226586Sdim  }
706226586Sdim
707226586Sdim  void addInstMethSummary(const char* Cls, const RetainSummary * Summ, ...) {
708226586Sdim    va_list argp;
709226586Sdim    va_start(argp, Summ);
710226586Sdim    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
711226586Sdim    va_end(argp);
712226586Sdim  }
713226586Sdim
714226586Sdim  void addClsMethSummary(const char* Cls, const RetainSummary * Summ, ...) {
715226586Sdim    va_list argp;
716226586Sdim    va_start(argp, Summ);
717226586Sdim    addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
718226586Sdim    va_end(argp);
719226586Sdim  }
720226586Sdim
721226586Sdim  void addClsMethSummary(IdentifierInfo *II, const RetainSummary * Summ, ...) {
722226586Sdim    va_list argp;
723226586Sdim    va_start(argp, Summ);
724226586Sdim    addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
725226586Sdim    va_end(argp);
726226586Sdim  }
727226586Sdim
728226586Sdimpublic:
729226586Sdim
730226586Sdim  RetainSummaryManager(ASTContext &ctx, bool gcenabled, bool usesARC)
731226586Sdim   : Ctx(ctx),
732226586Sdim     GCEnabled(gcenabled),
733226586Sdim     ARCEnabled(usesARC),
734226586Sdim     AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
735226586Sdim     ObjCAllocRetE(gcenabled
736226586Sdim                    ? RetEffect::MakeGCNotOwned()
737226586Sdim                    : (usesARC ? RetEffect::MakeARCNotOwned()
738226586Sdim                               : RetEffect::MakeOwned(RetEffect::ObjC, true))),
739226586Sdim     ObjCInitRetE(gcenabled
740226586Sdim                    ? RetEffect::MakeGCNotOwned()
741226586Sdim                    : (usesARC ? RetEffect::MakeARCNotOwned()
742234353Sdim                               : RetEffect::MakeOwnedWhenTrackedReceiver())) {
743226586Sdim    InitializeClassMethodSummaries();
744226586Sdim    InitializeMethodSummaries();
745226586Sdim  }
746226586Sdim
747239462Sdim  const RetainSummary *getSummary(const CallEvent &Call,
748239462Sdim                                  ProgramStateRef State = 0);
749226586Sdim
750239462Sdim  const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
751239462Sdim
752239462Sdim  const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
753234353Sdim                                        const ObjCMethodDecl *MD,
754234353Sdim                                        QualType RetTy,
755234353Sdim                                        ObjCMethodSummariesTy &CachedSummaries);
756234353Sdim
757239462Sdim  const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M,
758239462Sdim                                                ProgramStateRef State);
759226586Sdim
760239462Sdim  const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
761239462Sdim    assert(!M.isInstanceMessage());
762239462Sdim    const ObjCInterfaceDecl *Class = M.getReceiverInterface();
763226586Sdim
764239462Sdim    return getMethodSummary(M.getSelector(), Class, M.getDecl(),
765239462Sdim                            M.getResultType(), ObjCClassMethodSummaries);
766226586Sdim  }
767226586Sdim
768226586Sdim  /// getMethodSummary - This version of getMethodSummary is used to query
769226586Sdim  ///  the summary for the current method being analyzed.
770226586Sdim  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
771226586Sdim    const ObjCInterfaceDecl *ID = MD->getClassInterface();
772226586Sdim    Selector S = MD->getSelector();
773226586Sdim    QualType ResultTy = MD->getResultType();
774226586Sdim
775234353Sdim    ObjCMethodSummariesTy *CachedSummaries;
776226586Sdim    if (MD->isInstanceMethod())
777234353Sdim      CachedSummaries = &ObjCMethodSummaries;
778226586Sdim    else
779234353Sdim      CachedSummaries = &ObjCClassMethodSummaries;
780234353Sdim
781239462Sdim    return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
782226586Sdim  }
783226586Sdim
784234353Sdim  const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
785239462Sdim                                                Selector S, QualType RetTy);
786226586Sdim
787249423Sdim  /// Determine if there is a special return effect for this function or method.
788249423Sdim  Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
789249423Sdim                                                  const Decl *D);
790249423Sdim
791226586Sdim  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
792226586Sdim                                    const ObjCMethodDecl *MD);
793226586Sdim
794226586Sdim  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
795226586Sdim                                    const FunctionDecl *FD);
796226586Sdim
797239462Sdim  void updateSummaryForCall(const RetainSummary *&Summ,
798239462Sdim                            const CallEvent &Call);
799239462Sdim
800226586Sdim  bool isGCEnabled() const { return GCEnabled; }
801226586Sdim
802226586Sdim  bool isARCEnabled() const { return ARCEnabled; }
803226586Sdim
804226586Sdim  bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; }
805239462Sdim
806239462Sdim  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
807239462Sdim
808239462Sdim  friend class RetainSummaryTemplate;
809226586Sdim};
810226586Sdim
811226586Sdim// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
812226586Sdim// summaries. If a function or method looks like it has a default summary, but
813226586Sdim// it has annotations, the annotations are added to the stack-based template
814226586Sdim// and then copied into managed memory.
815226586Sdimclass RetainSummaryTemplate {
816226586Sdim  RetainSummaryManager &Manager;
817226586Sdim  const RetainSummary *&RealSummary;
818226586Sdim  RetainSummary ScratchSummary;
819226586Sdim  bool Accessed;
820226586Sdimpublic:
821239462Sdim  RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
822239462Sdim    : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
823226586Sdim
824226586Sdim  ~RetainSummaryTemplate() {
825226586Sdim    if (Accessed)
826234353Sdim      RealSummary = Manager.getPersistentSummary(ScratchSummary);
827226586Sdim  }
828226586Sdim
829226586Sdim  RetainSummary &operator*() {
830226586Sdim    Accessed = true;
831226586Sdim    return ScratchSummary;
832226586Sdim  }
833226586Sdim
834226586Sdim  RetainSummary *operator->() {
835226586Sdim    Accessed = true;
836226586Sdim    return &ScratchSummary;
837226586Sdim  }
838226586Sdim};
839226586Sdim
840226586Sdim} // end anonymous namespace
841226586Sdim
842226586Sdim//===----------------------------------------------------------------------===//
843226586Sdim// Implementation of checker data structures.
844226586Sdim//===----------------------------------------------------------------------===//
845226586Sdim
846226586SdimArgEffects RetainSummaryManager::getArgEffects() {
847226586Sdim  ArgEffects AE = ScratchArgs;
848226586Sdim  ScratchArgs = AF.getEmptyMap();
849226586Sdim  return AE;
850226586Sdim}
851226586Sdim
852226586Sdimconst RetainSummary *
853234353SdimRetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
854234353Sdim  // Unique "simple" summaries -- those without ArgEffects.
855234353Sdim  if (OldSumm.isSimple()) {
856234353Sdim    llvm::FoldingSetNodeID ID;
857234353Sdim    OldSumm.Profile(ID);
858234353Sdim
859234353Sdim    void *Pos;
860234353Sdim    CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
861234353Sdim
862234353Sdim    if (!N) {
863234353Sdim      N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
864234353Sdim      new (N) CachedSummaryNode(OldSumm);
865234353Sdim      SimpleSummaries.InsertNode(N, Pos);
866234353Sdim    }
867234353Sdim
868234353Sdim    return &N->getValue();
869234353Sdim  }
870234353Sdim
871226586Sdim  RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
872234353Sdim  new (Summ) RetainSummary(OldSumm);
873226586Sdim  return Summ;
874226586Sdim}
875226586Sdim
876226586Sdim//===----------------------------------------------------------------------===//
877226586Sdim// Summary creation for functions (largely uses of Core Foundation).
878226586Sdim//===----------------------------------------------------------------------===//
879226586Sdim
880226586Sdimstatic bool isRetain(const FunctionDecl *FD, StringRef FName) {
881226586Sdim  return FName.endswith("Retain");
882226586Sdim}
883226586Sdim
884226586Sdimstatic bool isRelease(const FunctionDecl *FD, StringRef FName) {
885226586Sdim  return FName.endswith("Release");
886226586Sdim}
887226586Sdim
888226586Sdimstatic bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) {
889226586Sdim  // FIXME: Remove FunctionDecl parameter.
890226586Sdim  // FIXME: Is it really okay if MakeCollectable isn't a suffix?
891226586Sdim  return FName.find("MakeCollectable") != StringRef::npos;
892226586Sdim}
893226586Sdim
894243830Sdimstatic ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
895239462Sdim  switch (E) {
896239462Sdim  case DoNothing:
897239462Sdim  case Autorelease:
898239462Sdim  case DecRefBridgedTransfered:
899239462Sdim  case IncRef:
900239462Sdim  case IncRefMsg:
901239462Sdim  case MakeCollectable:
902239462Sdim  case MayEscape:
903239462Sdim  case StopTracking:
904243830Sdim  case StopTrackingHard:
905243830Sdim    return StopTrackingHard;
906239462Sdim  case DecRef:
907243830Sdim  case DecRefAndStopTrackingHard:
908243830Sdim    return DecRefAndStopTrackingHard;
909239462Sdim  case DecRefMsg:
910243830Sdim  case DecRefMsgAndStopTrackingHard:
911243830Sdim    return DecRefMsgAndStopTrackingHard;
912239462Sdim  case Dealloc:
913239462Sdim    return Dealloc;
914239462Sdim  }
915239462Sdim
916239462Sdim  llvm_unreachable("Unknown ArgEffect kind");
917239462Sdim}
918239462Sdim
919239462Sdimvoid RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
920239462Sdim                                                const CallEvent &Call) {
921239462Sdim  if (Call.hasNonZeroCallbackArg()) {
922243830Sdim    ArgEffect RecEffect =
923243830Sdim      getStopTrackingHardEquivalent(S->getReceiverEffect());
924243830Sdim    ArgEffect DefEffect =
925243830Sdim      getStopTrackingHardEquivalent(S->getDefaultArgEffect());
926239462Sdim
927239462Sdim    ArgEffects CustomArgEffects = S->getArgEffects();
928239462Sdim    for (ArgEffects::iterator I = CustomArgEffects.begin(),
929239462Sdim                              E = CustomArgEffects.end();
930239462Sdim         I != E; ++I) {
931243830Sdim      ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
932239462Sdim      if (Translated != DefEffect)
933239462Sdim        ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
934239462Sdim    }
935239462Sdim
936243830Sdim    RetEffect RE = RetEffect::MakeNoRetHard();
937239462Sdim
938239462Sdim    // Special cases where the callback argument CANNOT free the return value.
939239462Sdim    // This can generally only happen if we know that the callback will only be
940239462Sdim    // called when the return value is already being deallocated.
941239462Sdim    if (const FunctionCall *FC = dyn_cast<FunctionCall>(&Call)) {
942243830Sdim      if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
943243830Sdim        // When the CGBitmapContext is deallocated, the callback here will free
944243830Sdim        // the associated data buffer.
945243830Sdim        if (Name->isStr("CGBitmapContextCreateWithData"))
946243830Sdim          RE = S->getRetEffect();
947243830Sdim      }
948239462Sdim    }
949239462Sdim
950239462Sdim    S = getPersistentSummary(RE, RecEffect, DefEffect);
951239462Sdim  }
952243830Sdim
953243830Sdim  // Special case '[super init];' and '[self init];'
954243830Sdim  //
955243830Sdim  // Even though calling '[super init]' without assigning the result to self
956243830Sdim  // and checking if the parent returns 'nil' is a bad pattern, it is common.
957243830Sdim  // Additionally, our Self Init checker already warns about it. To avoid
958243830Sdim  // overwhelming the user with messages from both checkers, we model the case
959243830Sdim  // of '[super init]' in cases when it is not consumed by another expression
960243830Sdim  // as if the call preserves the value of 'self'; essentially, assuming it can
961243830Sdim  // never fail and return 'nil'.
962243830Sdim  // Note, we don't want to just stop tracking the value since we want the
963243830Sdim  // RetainCount checker to report leaks and use-after-free if SelfInit checker
964243830Sdim  // is turned off.
965243830Sdim  if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
966243830Sdim    if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
967243830Sdim
968243830Sdim      // Check if the message is not consumed, we know it will not be used in
969243830Sdim      // an assignment, ex: "self = [super init]".
970243830Sdim      const Expr *ME = MC->getOriginExpr();
971243830Sdim      const LocationContext *LCtx = MC->getLocationContext();
972243830Sdim      ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
973243830Sdim      if (!PM.isConsumedExpr(ME)) {
974243830Sdim        RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
975243830Sdim        ModifiableSummaryTemplate->setReceiverEffect(DoNothing);
976243830Sdim        ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
977243830Sdim      }
978243830Sdim    }
979243830Sdim
980243830Sdim  }
981239462Sdim}
982239462Sdim
983239462Sdimconst RetainSummary *
984239462SdimRetainSummaryManager::getSummary(const CallEvent &Call,
985239462Sdim                                 ProgramStateRef State) {
986239462Sdim  const RetainSummary *Summ;
987239462Sdim  switch (Call.getKind()) {
988239462Sdim  case CE_Function:
989239462Sdim    Summ = getFunctionSummary(cast<FunctionCall>(Call).getDecl());
990239462Sdim    break;
991239462Sdim  case CE_CXXMember:
992239462Sdim  case CE_CXXMemberOperator:
993239462Sdim  case CE_Block:
994239462Sdim  case CE_CXXConstructor:
995239462Sdim  case CE_CXXDestructor:
996239462Sdim  case CE_CXXAllocator:
997239462Sdim    // FIXME: These calls are currently unsupported.
998239462Sdim    return getPersistentStopSummary();
999239462Sdim  case CE_ObjCMessage: {
1000239462Sdim    const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
1001239462Sdim    if (Msg.isInstanceMessage())
1002239462Sdim      Summ = getInstanceMethodSummary(Msg, State);
1003239462Sdim    else
1004239462Sdim      Summ = getClassMethodSummary(Msg);
1005239462Sdim    break;
1006239462Sdim  }
1007239462Sdim  }
1008239462Sdim
1009239462Sdim  updateSummaryForCall(Summ, Call);
1010239462Sdim
1011239462Sdim  assert(Summ && "Unknown call type?");
1012239462Sdim  return Summ;
1013239462Sdim}
1014239462Sdim
1015239462Sdimconst RetainSummary *
1016239462SdimRetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
1017239462Sdim  // If we don't know what function we're calling, use our default summary.
1018239462Sdim  if (!FD)
1019239462Sdim    return getDefaultSummary();
1020239462Sdim
1021226586Sdim  // Look up a summary in our cache of FunctionDecls -> Summaries.
1022226586Sdim  FuncSummariesTy::iterator I = FuncSummaries.find(FD);
1023226586Sdim  if (I != FuncSummaries.end())
1024226586Sdim    return I->second;
1025226586Sdim
1026226586Sdim  // No summary?  Generate one.
1027226586Sdim  const RetainSummary *S = 0;
1028239462Sdim  bool AllowAnnotations = true;
1029226586Sdim
1030226586Sdim  do {
1031226586Sdim    // We generate "stop" summaries for implicitly defined functions.
1032226586Sdim    if (FD->isImplicit()) {
1033226586Sdim      S = getPersistentStopSummary();
1034226586Sdim      break;
1035226586Sdim    }
1036226586Sdim
1037226586Sdim    // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
1038226586Sdim    // function's type.
1039226586Sdim    const FunctionType* FT = FD->getType()->getAs<FunctionType>();
1040226586Sdim    const IdentifierInfo *II = FD->getIdentifier();
1041226586Sdim    if (!II)
1042226586Sdim      break;
1043226586Sdim
1044226586Sdim    StringRef FName = II->getName();
1045226586Sdim
1046226586Sdim    // Strip away preceding '_'.  Doing this here will effect all the checks
1047226586Sdim    // down below.
1048226586Sdim    FName = FName.substr(FName.find_first_not_of('_'));
1049226586Sdim
1050226586Sdim    // Inspect the result type.
1051226586Sdim    QualType RetTy = FT->getResultType();
1052226586Sdim
1053226586Sdim    // FIXME: This should all be refactored into a chain of "summary lookup"
1054226586Sdim    //  filters.
1055226586Sdim    assert(ScratchArgs.isEmpty());
1056226586Sdim
1057239462Sdim    if (FName == "pthread_create" || FName == "pthread_setspecific") {
1058239462Sdim      // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
1059239462Sdim      // This will be addressed better with IPA.
1060226586Sdim      S = getPersistentStopSummary();
1061226586Sdim    } else if (FName == "NSMakeCollectable") {
1062226586Sdim      // Handle: id NSMakeCollectable(CFTypeRef)
1063226586Sdim      S = (RetTy->isObjCIdType())
1064226586Sdim          ? getUnarySummary(FT, cfmakecollectable)
1065226586Sdim          : getPersistentStopSummary();
1066239462Sdim      // The headers on OS X 10.8 use cf_consumed/ns_returns_retained,
1067239462Sdim      // but we can fully model NSMakeCollectable ourselves.
1068239462Sdim      AllowAnnotations = false;
1069243830Sdim    } else if (FName == "CFPlugInInstanceCreate") {
1070243830Sdim      S = getPersistentSummary(RetEffect::MakeNoRet());
1071226586Sdim    } else if (FName == "IOBSDNameMatching" ||
1072226586Sdim               FName == "IOServiceMatching" ||
1073226586Sdim               FName == "IOServiceNameMatching" ||
1074239462Sdim               FName == "IORegistryEntrySearchCFProperty" ||
1075226586Sdim               FName == "IORegistryEntryIDMatching" ||
1076226586Sdim               FName == "IOOpenFirmwarePathMatching") {
1077226586Sdim      // Part of <rdar://problem/6961230>. (IOKit)
1078226586Sdim      // This should be addressed using a API table.
1079226586Sdim      S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
1080226586Sdim                               DoNothing, DoNothing);
1081226586Sdim    } else if (FName == "IOServiceGetMatchingService" ||
1082226586Sdim               FName == "IOServiceGetMatchingServices") {
1083226586Sdim      // FIXES: <rdar://problem/6326900>
1084226586Sdim      // This should be addressed using a API table.  This strcmp is also
1085226586Sdim      // a little gross, but there is no need to super optimize here.
1086226586Sdim      ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
1087226586Sdim      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1088226586Sdim    } else if (FName == "IOServiceAddNotification" ||
1089226586Sdim               FName == "IOServiceAddMatchingNotification") {
1090226586Sdim      // Part of <rdar://problem/6961230>. (IOKit)
1091226586Sdim      // This should be addressed using a API table.
1092226586Sdim      ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
1093226586Sdim      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1094226586Sdim    } else if (FName == "CVPixelBufferCreateWithBytes") {
1095226586Sdim      // FIXES: <rdar://problem/7283567>
1096226586Sdim      // Eventually this can be improved by recognizing that the pixel
1097226586Sdim      // buffer passed to CVPixelBufferCreateWithBytes is released via
1098226586Sdim      // a callback and doing full IPA to make sure this is done correctly.
1099226586Sdim      // FIXME: This function has an out parameter that returns an
1100226586Sdim      // allocated object.
1101226586Sdim      ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
1102226586Sdim      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1103226586Sdim    } else if (FName == "CGBitmapContextCreateWithData") {
1104226586Sdim      // FIXES: <rdar://problem/7358899>
1105226586Sdim      // Eventually this can be improved by recognizing that 'releaseInfo'
1106226586Sdim      // passed to CGBitmapContextCreateWithData is released via
1107226586Sdim      // a callback and doing full IPA to make sure this is done correctly.
1108226586Sdim      ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
1109226586Sdim      S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
1110226586Sdim                               DoNothing, DoNothing);
1111226586Sdim    } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
1112226586Sdim      // FIXES: <rdar://problem/7283567>
1113226586Sdim      // Eventually this can be improved by recognizing that the pixel
1114226586Sdim      // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
1115226586Sdim      // via a callback and doing full IPA to make sure this is done
1116226586Sdim      // correctly.
1117226586Sdim      ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
1118226586Sdim      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1119251662Sdim    } else if (FName == "dispatch_set_context" ||
1120251662Sdim               FName == "xpc_connection_set_context") {
1121234353Sdim      // <rdar://problem/11059275> - The analyzer currently doesn't have
1122234353Sdim      // a good way to reason about the finalizer function for libdispatch.
1123234353Sdim      // If we pass a context object that is memory managed, stop tracking it.
1124251662Sdim      // <rdar://problem/13783514> - Same problem, but for XPC.
1125234353Sdim      // FIXME: this hack should possibly go away once we can handle
1126251662Sdim      // libdispatch and XPC finalizers.
1127234353Sdim      ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
1128234353Sdim      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1129239462Sdim    } else if (FName.startswith("NSLog")) {
1130239462Sdim      S = getDoNothingSummary();
1131234353Sdim    } else if (FName.startswith("NS") &&
1132234353Sdim                (FName.find("Insert") != StringRef::npos)) {
1133234353Sdim      // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
1134234353Sdim      // be deallocated by NSMapRemove. (radar://11152419)
1135234353Sdim      ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
1136234353Sdim      ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);
1137234353Sdim      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1138226586Sdim    }
1139226586Sdim
1140226586Sdim    // Did we get a summary?
1141226586Sdim    if (S)
1142226586Sdim      break;
1143226586Sdim
1144249423Sdim    if (RetTy->isPointerType()) {
1145226586Sdim      // For CoreFoundation ('CF') types.
1146226586Sdim      if (cocoa::isRefType(RetTy, "CF", FName)) {
1147226586Sdim        if (isRetain(FD, FName))
1148226586Sdim          S = getUnarySummary(FT, cfretain);
1149226586Sdim        else if (isMakeCollectable(FD, FName))
1150226586Sdim          S = getUnarySummary(FT, cfmakecollectable);
1151226586Sdim        else
1152226586Sdim          S = getCFCreateGetRuleSummary(FD);
1153226586Sdim
1154226586Sdim        break;
1155226586Sdim      }
1156226586Sdim
1157226586Sdim      // For CoreGraphics ('CG') types.
1158226586Sdim      if (cocoa::isRefType(RetTy, "CG", FName)) {
1159226586Sdim        if (isRetain(FD, FName))
1160226586Sdim          S = getUnarySummary(FT, cfretain);
1161226586Sdim        else
1162226586Sdim          S = getCFCreateGetRuleSummary(FD);
1163226586Sdim
1164226586Sdim        break;
1165226586Sdim      }
1166226586Sdim
1167226586Sdim      // For the Disk Arbitration API (DiskArbitration/DADisk.h)
1168226586Sdim      if (cocoa::isRefType(RetTy, "DADisk") ||
1169226586Sdim          cocoa::isRefType(RetTy, "DADissenter") ||
1170226586Sdim          cocoa::isRefType(RetTy, "DASessionRef")) {
1171226586Sdim        S = getCFCreateGetRuleSummary(FD);
1172226586Sdim        break;
1173226586Sdim      }
1174226586Sdim
1175249423Sdim      if (FD->getAttr<CFAuditedTransferAttr>()) {
1176249423Sdim        S = getCFCreateGetRuleSummary(FD);
1177249423Sdim        break;
1178249423Sdim      }
1179249423Sdim
1180226586Sdim      break;
1181226586Sdim    }
1182226586Sdim
1183226586Sdim    // Check for release functions, the only kind of functions that we care
1184226586Sdim    // about that don't return a pointer type.
1185226586Sdim    if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
1186226586Sdim      // Test for 'CGCF'.
1187226586Sdim      FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
1188226586Sdim
1189226586Sdim      if (isRelease(FD, FName))
1190226586Sdim        S = getUnarySummary(FT, cfrelease);
1191226586Sdim      else {
1192226586Sdim        assert (ScratchArgs.isEmpty());
1193226586Sdim        // Remaining CoreFoundation and CoreGraphics functions.
1194226586Sdim        // We use to assume that they all strictly followed the ownership idiom
1195226586Sdim        // and that ownership cannot be transferred.  While this is technically
1196226586Sdim        // correct, many methods allow a tracked object to escape.  For example:
1197226586Sdim        //
1198226586Sdim        //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
1199226586Sdim        //   CFDictionaryAddValue(y, key, x);
1200226586Sdim        //   CFRelease(x);
1201226586Sdim        //   ... it is okay to use 'x' since 'y' has a reference to it
1202226586Sdim        //
1203226586Sdim        // We handle this and similar cases with the follow heuristic.  If the
1204226586Sdim        // function name contains "InsertValue", "SetValue", "AddValue",
1205226586Sdim        // "AppendValue", or "SetAttribute", then we assume that arguments may
1206226586Sdim        // "escape."  This means that something else holds on to the object,
1207226586Sdim        // allowing it be used even after its local retain count drops to 0.
1208226586Sdim        ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
1209226586Sdim                       StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
1210226586Sdim                       StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
1211226586Sdim                       StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
1212226586Sdim                       StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
1213226586Sdim                      ? MayEscape : DoNothing;
1214226586Sdim
1215226586Sdim        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
1216226586Sdim      }
1217226586Sdim    }
1218226586Sdim  }
1219226586Sdim  while (0);
1220226586Sdim
1221239462Sdim  // If we got all the way here without any luck, use a default summary.
1222239462Sdim  if (!S)
1223239462Sdim    S = getDefaultSummary();
1224239462Sdim
1225226586Sdim  // Annotations override defaults.
1226239462Sdim  if (AllowAnnotations)
1227239462Sdim    updateSummaryFromAnnotations(S, FD);
1228226586Sdim
1229226586Sdim  FuncSummaries[FD] = S;
1230226586Sdim  return S;
1231226586Sdim}
1232226586Sdim
1233226586Sdimconst RetainSummary *
1234226586SdimRetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
1235226586Sdim  if (coreFoundation::followsCreateRule(FD))
1236226586Sdim    return getCFSummaryCreateRule(FD);
1237226586Sdim
1238226586Sdim  return getCFSummaryGetRule(FD);
1239226586Sdim}
1240226586Sdim
1241226586Sdimconst RetainSummary *
1242226586SdimRetainSummaryManager::getUnarySummary(const FunctionType* FT,
1243226586Sdim                                      UnaryFuncKind func) {
1244226586Sdim
1245226586Sdim  // Sanity check that this is *really* a unary function.  This can
1246226586Sdim  // happen if people do weird things.
1247226586Sdim  const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
1248226586Sdim  if (!FTP || FTP->getNumArgs() != 1)
1249226586Sdim    return getPersistentStopSummary();
1250226586Sdim
1251226586Sdim  assert (ScratchArgs.isEmpty());
1252226586Sdim
1253226586Sdim  ArgEffect Effect;
1254226586Sdim  switch (func) {
1255226586Sdim    case cfretain: Effect = IncRef; break;
1256226586Sdim    case cfrelease: Effect = DecRef; break;
1257226586Sdim    case cfmakecollectable: Effect = MakeCollectable; break;
1258226586Sdim  }
1259226586Sdim
1260226586Sdim  ScratchArgs = AF.add(ScratchArgs, 0, Effect);
1261226586Sdim  return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1262226586Sdim}
1263226586Sdim
1264226586Sdimconst RetainSummary *
1265226586SdimRetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
1266226586Sdim  assert (ScratchArgs.isEmpty());
1267226586Sdim
1268226586Sdim  return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1269226586Sdim}
1270226586Sdim
1271226586Sdimconst RetainSummary *
1272226586SdimRetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
1273226586Sdim  assert (ScratchArgs.isEmpty());
1274226586Sdim  return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1275226586Sdim                              DoNothing, DoNothing);
1276226586Sdim}
1277226586Sdim
1278226586Sdim//===----------------------------------------------------------------------===//
1279226586Sdim// Summary creation for Selectors.
1280226586Sdim//===----------------------------------------------------------------------===//
1281226586Sdim
1282249423SdimOptional<RetEffect>
1283249423SdimRetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
1284249423Sdim                                                  const Decl *D) {
1285249423Sdim  if (cocoa::isCocoaObjectRef(RetTy)) {
1286249423Sdim    if (D->getAttr<NSReturnsRetainedAttr>())
1287249423Sdim      return ObjCAllocRetE;
1288249423Sdim
1289249423Sdim    if (D->getAttr<NSReturnsNotRetainedAttr>() ||
1290249423Sdim        D->getAttr<NSReturnsAutoreleasedAttr>())
1291249423Sdim      return RetEffect::MakeNotOwned(RetEffect::ObjC);
1292249423Sdim
1293249423Sdim  } else if (!RetTy->isPointerType()) {
1294249423Sdim    return None;
1295249423Sdim  }
1296249423Sdim
1297249423Sdim  if (D->getAttr<CFReturnsRetainedAttr>())
1298249423Sdim    return RetEffect::MakeOwned(RetEffect::CF, true);
1299249423Sdim
1300249423Sdim  if (D->getAttr<CFReturnsNotRetainedAttr>())
1301249423Sdim    return RetEffect::MakeNotOwned(RetEffect::CF);
1302249423Sdim
1303249423Sdim  return None;
1304249423Sdim}
1305249423Sdim
1306226586Sdimvoid
1307226586SdimRetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
1308226586Sdim                                                   const FunctionDecl *FD) {
1309226586Sdim  if (!FD)
1310226586Sdim    return;
1311226586Sdim
1312239462Sdim  assert(Summ && "Must have a summary to add annotations to.");
1313239462Sdim  RetainSummaryTemplate Template(Summ, *this);
1314226586Sdim
1315226586Sdim  // Effects on the parameters.
1316226586Sdim  unsigned parm_idx = 0;
1317226586Sdim  for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
1318226586Sdim         pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
1319226586Sdim    const ParmVarDecl *pd = *pi;
1320249423Sdim    if (pd->getAttr<NSConsumedAttr>())
1321249423Sdim      Template->addArg(AF, parm_idx, DecRefMsg);
1322249423Sdim    else if (pd->getAttr<CFConsumedAttr>())
1323226586Sdim      Template->addArg(AF, parm_idx, DecRef);
1324226586Sdim  }
1325226586Sdim
1326226586Sdim  QualType RetTy = FD->getResultType();
1327249423Sdim  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
1328249423Sdim    Template->setRetEffect(*RetE);
1329226586Sdim}
1330226586Sdim
1331226586Sdimvoid
1332226586SdimRetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
1333226586Sdim                                                   const ObjCMethodDecl *MD) {
1334226586Sdim  if (!MD)
1335226586Sdim    return;
1336226586Sdim
1337239462Sdim  assert(Summ && "Must have a valid summary to add annotations to");
1338239462Sdim  RetainSummaryTemplate Template(Summ, *this);
1339226586Sdim
1340226586Sdim  // Effects on the receiver.
1341249423Sdim  if (MD->getAttr<NSConsumesSelfAttr>())
1342249423Sdim    Template->setReceiverEffect(DecRefMsg);
1343226586Sdim
1344226586Sdim  // Effects on the parameters.
1345226586Sdim  unsigned parm_idx = 0;
1346226586Sdim  for (ObjCMethodDecl::param_const_iterator
1347226586Sdim         pi=MD->param_begin(), pe=MD->param_end();
1348226586Sdim       pi != pe; ++pi, ++parm_idx) {
1349226586Sdim    const ParmVarDecl *pd = *pi;
1350249423Sdim    if (pd->getAttr<NSConsumedAttr>())
1351249423Sdim      Template->addArg(AF, parm_idx, DecRefMsg);
1352249423Sdim    else if (pd->getAttr<CFConsumedAttr>()) {
1353226586Sdim      Template->addArg(AF, parm_idx, DecRef);
1354226586Sdim    }
1355226586Sdim  }
1356226586Sdim
1357249423Sdim  QualType RetTy = MD->getResultType();
1358249423Sdim  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
1359249423Sdim    Template->setRetEffect(*RetE);
1360226586Sdim}
1361226586Sdim
1362226586Sdimconst RetainSummary *
1363234353SdimRetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
1364234353Sdim                                               Selector S, QualType RetTy) {
1365234353Sdim  // Any special effects?
1366226586Sdim  ArgEffect ReceiverEff = DoNothing;
1367234353Sdim  RetEffect ResultEff = RetEffect::MakeNoRet();
1368226586Sdim
1369234353Sdim  // Check the method family, and apply any default annotations.
1370234353Sdim  switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
1371234353Sdim    case OMF_None:
1372234353Sdim    case OMF_performSelector:
1373234353Sdim      // Assume all Objective-C methods follow Cocoa Memory Management rules.
1374234353Sdim      // FIXME: Does the non-threaded performSelector family really belong here?
1375234353Sdim      // The selector could be, say, @selector(copy).
1376234353Sdim      if (cocoa::isCocoaObjectRef(RetTy))
1377234353Sdim        ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);
1378234353Sdim      else if (coreFoundation::isCFObjectRef(RetTy)) {
1379234353Sdim        // ObjCMethodDecl currently doesn't consider CF objects as valid return
1380234353Sdim        // values for alloc, new, copy, or mutableCopy, so we have to
1381234353Sdim        // double-check with the selector. This is ugly, but there aren't that
1382234353Sdim        // many Objective-C methods that return CF objects, right?
1383234353Sdim        if (MD) {
1384234353Sdim          switch (S.getMethodFamily()) {
1385234353Sdim          case OMF_alloc:
1386234353Sdim          case OMF_new:
1387234353Sdim          case OMF_copy:
1388234353Sdim          case OMF_mutableCopy:
1389234353Sdim            ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
1390234353Sdim            break;
1391234353Sdim          default:
1392234353Sdim            ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1393234353Sdim            break;
1394234353Sdim          }
1395234353Sdim        } else {
1396234353Sdim          ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1397234353Sdim        }
1398234353Sdim      }
1399234353Sdim      break;
1400234353Sdim    case OMF_init:
1401234353Sdim      ResultEff = ObjCInitRetE;
1402234353Sdim      ReceiverEff = DecRefMsg;
1403234353Sdim      break;
1404234353Sdim    case OMF_alloc:
1405234353Sdim    case OMF_new:
1406234353Sdim    case OMF_copy:
1407234353Sdim    case OMF_mutableCopy:
1408234353Sdim      if (cocoa::isCocoaObjectRef(RetTy))
1409234353Sdim        ResultEff = ObjCAllocRetE;
1410234353Sdim      else if (coreFoundation::isCFObjectRef(RetTy))
1411234353Sdim        ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
1412234353Sdim      break;
1413234353Sdim    case OMF_autorelease:
1414234353Sdim      ReceiverEff = Autorelease;
1415234353Sdim      break;
1416234353Sdim    case OMF_retain:
1417234353Sdim      ReceiverEff = IncRefMsg;
1418234353Sdim      break;
1419234353Sdim    case OMF_release:
1420234353Sdim      ReceiverEff = DecRefMsg;
1421234353Sdim      break;
1422234353Sdim    case OMF_dealloc:
1423234353Sdim      ReceiverEff = Dealloc;
1424234353Sdim      break;
1425234353Sdim    case OMF_self:
1426234353Sdim      // -self is handled specially by the ExprEngine to propagate the receiver.
1427234353Sdim      break;
1428234353Sdim    case OMF_retainCount:
1429234353Sdim    case OMF_finalize:
1430234353Sdim      // These methods don't return objects.
1431234353Sdim      break;
1432234353Sdim  }
1433234353Sdim
1434226586Sdim  // If one of the arguments in the selector has the keyword 'delegate' we
1435226586Sdim  // should stop tracking the reference count for the receiver.  This is
1436226586Sdim  // because the reference count is quite possibly handled by a delegate
1437226586Sdim  // method.
1438226586Sdim  if (S.isKeywordSelector()) {
1439239462Sdim    for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
1440239462Sdim      StringRef Slot = S.getNameForSlot(i);
1441239462Sdim      if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
1442239462Sdim        if (ResultEff == ObjCInitRetE)
1443243830Sdim          ResultEff = RetEffect::MakeNoRetHard();
1444239462Sdim        else
1445243830Sdim          ReceiverEff = StopTrackingHard;
1446239462Sdim      }
1447239462Sdim    }
1448226586Sdim  }
1449226586Sdim
1450234353Sdim  if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&
1451234353Sdim      ResultEff.getKind() == RetEffect::NoRet)
1452226586Sdim    return getDefaultSummary();
1453226586Sdim
1454234353Sdim  return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);
1455226586Sdim}
1456226586Sdim
1457226586Sdimconst RetainSummary *
1458239462SdimRetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
1459239462Sdim                                               ProgramStateRef State) {
1460239462Sdim  const ObjCInterfaceDecl *ReceiverClass = 0;
1461226586Sdim
1462239462Sdim  // We do better tracking of the type of the object than the core ExprEngine.
1463239462Sdim  // See if we have its type in our private state.
1464239462Sdim  // FIXME: Eventually replace the use of state->get<RefBindings> with
1465239462Sdim  // a generic API for reasoning about the Objective-C types of symbolic
1466239462Sdim  // objects.
1467239462Sdim  SVal ReceiverV = Msg.getReceiverSVal();
1468239462Sdim  if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
1469239462Sdim    if (const RefVal *T = getRefBinding(State, Sym))
1470239462Sdim      if (const ObjCObjectPointerType *PT =
1471226586Sdim            T->getType()->getAs<ObjCObjectPointerType>())
1472239462Sdim        ReceiverClass = PT->getInterfaceDecl();
1473226586Sdim
1474239462Sdim  // If we don't know what kind of object this is, fall back to its static type.
1475239462Sdim  if (!ReceiverClass)
1476239462Sdim    ReceiverClass = Msg.getReceiverInterface();
1477226586Sdim
1478226586Sdim  // FIXME: The receiver could be a reference to a class, meaning that
1479226586Sdim  //  we should use the class method.
1480239462Sdim  // id x = [NSObject class];
1481239462Sdim  // [x performSelector:... withObject:... afterDelay:...];
1482239462Sdim  Selector S = Msg.getSelector();
1483239462Sdim  const ObjCMethodDecl *Method = Msg.getDecl();
1484239462Sdim  if (!Method && ReceiverClass)
1485239462Sdim    Method = ReceiverClass->getInstanceMethod(S);
1486239462Sdim
1487239462Sdim  return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
1488239462Sdim                          ObjCMethodSummaries);
1489226586Sdim}
1490226586Sdim
1491226586Sdimconst RetainSummary *
1492239462SdimRetainSummaryManager::getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
1493234353Sdim                                       const ObjCMethodDecl *MD, QualType RetTy,
1494234353Sdim                                       ObjCMethodSummariesTy &CachedSummaries) {
1495226586Sdim
1496226586Sdim  // Look up a summary in our summary cache.
1497239462Sdim  const RetainSummary *Summ = CachedSummaries.find(ID, S);
1498226586Sdim
1499226586Sdim  if (!Summ) {
1500234353Sdim    Summ = getStandardMethodSummary(MD, S, RetTy);
1501226586Sdim
1502226586Sdim    // Annotations override defaults.
1503226586Sdim    updateSummaryFromAnnotations(Summ, MD);
1504226586Sdim
1505226586Sdim    // Memoize the summary.
1506239462Sdim    CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1507226586Sdim  }
1508226586Sdim
1509226586Sdim  return Summ;
1510226586Sdim}
1511226586Sdim
1512226586Sdimvoid RetainSummaryManager::InitializeClassMethodSummaries() {
1513226586Sdim  assert(ScratchArgs.isEmpty());
1514226586Sdim  // Create the [NSAssertionHandler currentHander] summary.
1515226586Sdim  addClassMethSummary("NSAssertionHandler", "currentHandler",
1516226586Sdim                getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
1517226586Sdim
1518226586Sdim  // Create the [NSAutoreleasePool addObject:] summary.
1519226586Sdim  ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
1520226586Sdim  addClassMethSummary("NSAutoreleasePool", "addObject",
1521226586Sdim                      getPersistentSummary(RetEffect::MakeNoRet(),
1522226586Sdim                                           DoNothing, Autorelease));
1523226586Sdim}
1524226586Sdim
1525226586Sdimvoid RetainSummaryManager::InitializeMethodSummaries() {
1526226586Sdim
1527226586Sdim  assert (ScratchArgs.isEmpty());
1528226586Sdim
1529226586Sdim  // Create the "init" selector.  It just acts as a pass-through for the
1530226586Sdim  // receiver.
1531226586Sdim  const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
1532226586Sdim  addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
1533226586Sdim
1534226586Sdim  // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
1535226586Sdim  // claims the receiver and returns a retained object.
1536226586Sdim  addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
1537226586Sdim                         InitSumm);
1538226586Sdim
1539226586Sdim  // The next methods are allocators.
1540226586Sdim  const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1541226586Sdim  const RetainSummary *CFAllocSumm =
1542226586Sdim    getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1543226586Sdim
1544226586Sdim  // Create the "retain" selector.
1545226586Sdim  RetEffect NoRet = RetEffect::MakeNoRet();
1546226586Sdim  const RetainSummary *Summ = getPersistentSummary(NoRet, IncRefMsg);
1547226586Sdim  addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
1548226586Sdim
1549226586Sdim  // Create the "release" selector.
1550226586Sdim  Summ = getPersistentSummary(NoRet, DecRefMsg);
1551226586Sdim  addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
1552226586Sdim
1553226586Sdim  // Create the -dealloc summary.
1554226586Sdim  Summ = getPersistentSummary(NoRet, Dealloc);
1555226586Sdim  addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
1556226586Sdim
1557226586Sdim  // Create the "autorelease" selector.
1558226586Sdim  Summ = getPersistentSummary(NoRet, Autorelease);
1559226586Sdim  addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
1560226586Sdim
1561226586Sdim  // For NSWindow, allocated objects are (initially) self-owned.
1562226586Sdim  // FIXME: For now we opt for false negatives with NSWindow, as these objects
1563226586Sdim  //  self-own themselves.  However, they only do this once they are displayed.
1564226586Sdim  //  Thus, we need to track an NSWindow's display status.
1565226586Sdim  //  This is tracked in <rdar://problem/6062711>.
1566226586Sdim  //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1567226586Sdim  const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1568226586Sdim                                                   StopTracking,
1569226586Sdim                                                   StopTracking);
1570226586Sdim
1571226586Sdim  addClassMethSummary("NSWindow", "alloc", NoTrackYet);
1572226586Sdim
1573226586Sdim  // For NSPanel (which subclasses NSWindow), allocated objects are not
1574226586Sdim  //  self-owned.
1575226586Sdim  // FIXME: For now we don't track NSPanels. object for the same reason
1576226586Sdim  //   as for NSWindow objects.
1577226586Sdim  addClassMethSummary("NSPanel", "alloc", NoTrackYet);
1578226586Sdim
1579249423Sdim  // Don't track allocated autorelease pools, as it is okay to prematurely
1580226586Sdim  // exit a method.
1581226586Sdim  addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
1582234353Sdim  addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
1583249423Sdim  addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
1584226586Sdim
1585226586Sdim  // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
1586226586Sdim  addInstMethSummary("QCRenderer", AllocSumm,
1587226586Sdim                     "createSnapshotImageOfType", NULL);
1588226586Sdim  addInstMethSummary("QCView", AllocSumm,
1589226586Sdim                     "createSnapshotImageOfType", NULL);
1590226586Sdim
1591226586Sdim  // Create summaries for CIContext, 'createCGImage' and
1592226586Sdim  // 'createCGLayerWithSize'.  These objects are CF objects, and are not
1593226586Sdim  // automatically garbage collected.
1594226586Sdim  addInstMethSummary("CIContext", CFAllocSumm,
1595226586Sdim                     "createCGImage", "fromRect", NULL);
1596226586Sdim  addInstMethSummary("CIContext", CFAllocSumm,
1597226586Sdim                     "createCGImage", "fromRect", "format", "colorSpace", NULL);
1598226586Sdim  addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize",
1599226586Sdim           "info", NULL);
1600226586Sdim}
1601226586Sdim
1602226586Sdim//===----------------------------------------------------------------------===//
1603226586Sdim// Error reporting.
1604226586Sdim//===----------------------------------------------------------------------===//
1605226586Sdimnamespace {
1606226586Sdim  typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
1607226586Sdim    SummaryLogTy;
1608226586Sdim
1609226586Sdim  //===-------------===//
1610226586Sdim  // Bug Descriptions. //
1611226586Sdim  //===-------------===//
1612226586Sdim
1613226586Sdim  class CFRefBug : public BugType {
1614226586Sdim  protected:
1615226586Sdim    CFRefBug(StringRef name)
1616234353Sdim    : BugType(name, categories::MemoryCoreFoundationObjectiveC) {}
1617226586Sdim  public:
1618226586Sdim
1619226586Sdim    // FIXME: Eventually remove.
1620226586Sdim    virtual const char *getDescription() const = 0;
1621226586Sdim
1622226586Sdim    virtual bool isLeak() const { return false; }
1623226586Sdim  };
1624226586Sdim
1625226586Sdim  class UseAfterRelease : public CFRefBug {
1626226586Sdim  public:
1627226586Sdim    UseAfterRelease() : CFRefBug("Use-after-release") {}
1628226586Sdim
1629226586Sdim    const char *getDescription() const {
1630226586Sdim      return "Reference-counted object is used after it is released";
1631226586Sdim    }
1632226586Sdim  };
1633226586Sdim
1634226586Sdim  class BadRelease : public CFRefBug {
1635226586Sdim  public:
1636226586Sdim    BadRelease() : CFRefBug("Bad release") {}
1637226586Sdim
1638226586Sdim    const char *getDescription() const {
1639226586Sdim      return "Incorrect decrement of the reference count of an object that is "
1640226586Sdim             "not owned at this point by the caller";
1641226586Sdim    }
1642226586Sdim  };
1643226586Sdim
1644226586Sdim  class DeallocGC : public CFRefBug {
1645226586Sdim  public:
1646226586Sdim    DeallocGC()
1647226586Sdim    : CFRefBug("-dealloc called while using garbage collection") {}
1648226586Sdim
1649226586Sdim    const char *getDescription() const {
1650226586Sdim      return "-dealloc called while using garbage collection";
1651226586Sdim    }
1652226586Sdim  };
1653226586Sdim
1654226586Sdim  class DeallocNotOwned : public CFRefBug {
1655226586Sdim  public:
1656226586Sdim    DeallocNotOwned()
1657226586Sdim    : CFRefBug("-dealloc sent to non-exclusively owned object") {}
1658226586Sdim
1659226586Sdim    const char *getDescription() const {
1660226586Sdim      return "-dealloc sent to object that may be referenced elsewhere";
1661226586Sdim    }
1662226586Sdim  };
1663226586Sdim
1664226586Sdim  class OverAutorelease : public CFRefBug {
1665226586Sdim  public:
1666226586Sdim    OverAutorelease()
1667251662Sdim    : CFRefBug("Object autoreleased too many times") {}
1668226586Sdim
1669226586Sdim    const char *getDescription() const {
1670251662Sdim      return "Object autoreleased too many times";
1671226586Sdim    }
1672226586Sdim  };
1673226586Sdim
1674226586Sdim  class ReturnedNotOwnedForOwned : public CFRefBug {
1675226586Sdim  public:
1676226586Sdim    ReturnedNotOwnedForOwned()
1677226586Sdim    : CFRefBug("Method should return an owned object") {}
1678226586Sdim
1679226586Sdim    const char *getDescription() const {
1680226586Sdim      return "Object with a +0 retain count returned to caller where a +1 "
1681226586Sdim             "(owning) retain count is expected";
1682226586Sdim    }
1683226586Sdim  };
1684226586Sdim
1685226586Sdim  class Leak : public CFRefBug {
1686239462Sdim  public:
1687239462Sdim    Leak(StringRef name)
1688239462Sdim    : CFRefBug(name) {
1689226586Sdim      // Leaks should not be reported if they are post-dominated by a sink.
1690226586Sdim      setSuppressOnSink(true);
1691226586Sdim    }
1692226586Sdim
1693226586Sdim    const char *getDescription() const { return ""; }
1694226586Sdim
1695226586Sdim    bool isLeak() const { return true; }
1696226586Sdim  };
1697226586Sdim
1698226586Sdim  //===---------===//
1699226586Sdim  // Bug Reports.  //
1700226586Sdim  //===---------===//
1701226586Sdim
1702234353Sdim  class CFRefReportVisitor : public BugReporterVisitorImpl<CFRefReportVisitor> {
1703226586Sdim  protected:
1704226586Sdim    SymbolRef Sym;
1705226586Sdim    const SummaryLogTy &SummaryLog;
1706226586Sdim    bool GCEnabled;
1707226586Sdim
1708226586Sdim  public:
1709226586Sdim    CFRefReportVisitor(SymbolRef sym, bool gcEnabled, const SummaryLogTy &log)
1710226586Sdim       : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
1711226586Sdim
1712226586Sdim    virtual void Profile(llvm::FoldingSetNodeID &ID) const {
1713226586Sdim      static int x = 0;
1714226586Sdim      ID.AddPointer(&x);
1715226586Sdim      ID.AddPointer(Sym);
1716226586Sdim    }
1717226586Sdim
1718226586Sdim    virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
1719226586Sdim                                           const ExplodedNode *PrevN,
1720226586Sdim                                           BugReporterContext &BRC,
1721226586Sdim                                           BugReport &BR);
1722226586Sdim
1723226586Sdim    virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
1724226586Sdim                                            const ExplodedNode *N,
1725226586Sdim                                            BugReport &BR);
1726226586Sdim  };
1727226586Sdim
1728226586Sdim  class CFRefLeakReportVisitor : public CFRefReportVisitor {
1729226586Sdim  public:
1730226586Sdim    CFRefLeakReportVisitor(SymbolRef sym, bool GCEnabled,
1731226586Sdim                           const SummaryLogTy &log)
1732226586Sdim       : CFRefReportVisitor(sym, GCEnabled, log) {}
1733226586Sdim
1734226586Sdim    PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
1735226586Sdim                                    const ExplodedNode *N,
1736226586Sdim                                    BugReport &BR);
1737234353Sdim
1738234353Sdim    virtual BugReporterVisitor *clone() const {
1739234353Sdim      // The curiously-recurring template pattern only works for one level of
1740234353Sdim      // subclassing. Rather than make a new template base for
1741234353Sdim      // CFRefReportVisitor, we simply override clone() to do the right thing.
1742234353Sdim      // This could be trouble someday if BugReporterVisitorImpl is ever
1743234353Sdim      // used for something else besides a convenient implementation of clone().
1744234353Sdim      return new CFRefLeakReportVisitor(*this);
1745234353Sdim    }
1746226586Sdim  };
1747226586Sdim
1748226586Sdim  class CFRefReport : public BugReport {
1749226586Sdim    void addGCModeDescription(const LangOptions &LOpts, bool GCEnabled);
1750226586Sdim
1751226586Sdim  public:
1752226586Sdim    CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
1753226586Sdim                const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
1754226586Sdim                bool registerVisitor = true)
1755226586Sdim      : BugReport(D, D.getDescription(), n) {
1756226586Sdim      if (registerVisitor)
1757226586Sdim        addVisitor(new CFRefReportVisitor(sym, GCEnabled, Log));
1758226586Sdim      addGCModeDescription(LOpts, GCEnabled);
1759226586Sdim    }
1760226586Sdim
1761226586Sdim    CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
1762226586Sdim                const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
1763226586Sdim                StringRef endText)
1764226586Sdim      : BugReport(D, D.getDescription(), endText, n) {
1765226586Sdim      addVisitor(new CFRefReportVisitor(sym, GCEnabled, Log));
1766226586Sdim      addGCModeDescription(LOpts, GCEnabled);
1767226586Sdim    }
1768226586Sdim
1769226586Sdim    virtual std::pair<ranges_iterator, ranges_iterator> getRanges() {
1770226586Sdim      const CFRefBug& BugTy = static_cast<CFRefBug&>(getBugType());
1771226586Sdim      if (!BugTy.isLeak())
1772226586Sdim        return BugReport::getRanges();
1773226586Sdim      else
1774226586Sdim        return std::make_pair(ranges_iterator(), ranges_iterator());
1775226586Sdim    }
1776226586Sdim  };
1777226586Sdim
1778226586Sdim  class CFRefLeakReport : public CFRefReport {
1779226586Sdim    const MemRegion* AllocBinding;
1780226586Sdim  public:
1781226586Sdim    CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
1782226586Sdim                    const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
1783251662Sdim                    CheckerContext &Ctx,
1784251662Sdim                    bool IncludeAllocationLine);
1785226586Sdim
1786226586Sdim    PathDiagnosticLocation getLocation(const SourceManager &SM) const {
1787226586Sdim      assert(Location.isValid());
1788226586Sdim      return Location;
1789226586Sdim    }
1790226586Sdim  };
1791226586Sdim} // end anonymous namespace
1792226586Sdim
1793226586Sdimvoid CFRefReport::addGCModeDescription(const LangOptions &LOpts,
1794226586Sdim                                       bool GCEnabled) {
1795226586Sdim  const char *GCModeDescription = 0;
1796226586Sdim
1797226586Sdim  switch (LOpts.getGC()) {
1798226586Sdim  case LangOptions::GCOnly:
1799226586Sdim    assert(GCEnabled);
1800226586Sdim    GCModeDescription = "Code is compiled to only use garbage collection";
1801226586Sdim    break;
1802226586Sdim
1803226586Sdim  case LangOptions::NonGC:
1804226586Sdim    assert(!GCEnabled);
1805226586Sdim    GCModeDescription = "Code is compiled to use reference counts";
1806226586Sdim    break;
1807226586Sdim
1808226586Sdim  case LangOptions::HybridGC:
1809226586Sdim    if (GCEnabled) {
1810226586Sdim      GCModeDescription = "Code is compiled to use either garbage collection "
1811226586Sdim                          "(GC) or reference counts (non-GC).  The bug occurs "
1812226586Sdim                          "with GC enabled";
1813226586Sdim      break;
1814226586Sdim    } else {
1815226586Sdim      GCModeDescription = "Code is compiled to use either garbage collection "
1816226586Sdim                          "(GC) or reference counts (non-GC).  The bug occurs "
1817226586Sdim                          "in non-GC mode";
1818226586Sdim      break;
1819226586Sdim    }
1820226586Sdim  }
1821226586Sdim
1822226586Sdim  assert(GCModeDescription && "invalid/unknown GC mode");
1823226586Sdim  addExtraText(GCModeDescription);
1824226586Sdim}
1825226586Sdim
1826226586Sdim// FIXME: This should be a method on SmallVector.
1827226586Sdimstatic inline bool contains(const SmallVectorImpl<ArgEffect>& V,
1828226586Sdim                            ArgEffect X) {
1829226586Sdim  for (SmallVectorImpl<ArgEffect>::const_iterator I=V.begin(), E=V.end();
1830226586Sdim       I!=E; ++I)
1831226586Sdim    if (*I == X) return true;
1832226586Sdim
1833226586Sdim  return false;
1834226586Sdim}
1835226586Sdim
1836239462Sdimstatic bool isNumericLiteralExpression(const Expr *E) {
1837239462Sdim  // FIXME: This set of cases was copied from SemaExprObjC.
1838239462Sdim  return isa<IntegerLiteral>(E) ||
1839239462Sdim         isa<CharacterLiteral>(E) ||
1840239462Sdim         isa<FloatingLiteral>(E) ||
1841239462Sdim         isa<ObjCBoolLiteralExpr>(E) ||
1842239462Sdim         isa<CXXBoolLiteralExpr>(E);
1843234353Sdim}
1844234353Sdim
1845226586SdimPathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
1846226586Sdim                                                   const ExplodedNode *PrevN,
1847226586Sdim                                                   BugReporterContext &BRC,
1848226586Sdim                                                   BugReport &BR) {
1849239462Sdim  // FIXME: We will eventually need to handle non-statement-based events
1850239462Sdim  // (__attribute__((cleanup))).
1851249423Sdim  if (!N->getLocation().getAs<StmtPoint>())
1852226586Sdim    return NULL;
1853226586Sdim
1854226586Sdim  // Check if the type state has changed.
1855234353Sdim  ProgramStateRef PrevSt = PrevN->getState();
1856234353Sdim  ProgramStateRef CurrSt = N->getState();
1857234353Sdim  const LocationContext *LCtx = N->getLocationContext();
1858226586Sdim
1859239462Sdim  const RefVal* CurrT = getRefBinding(CurrSt, Sym);
1860226586Sdim  if (!CurrT) return NULL;
1861226586Sdim
1862226586Sdim  const RefVal &CurrV = *CurrT;
1863239462Sdim  const RefVal *PrevT = getRefBinding(PrevSt, Sym);
1864226586Sdim
1865226586Sdim  // Create a string buffer to constain all the useful things we want
1866226586Sdim  // to tell the user.
1867226586Sdim  std::string sbuf;
1868226586Sdim  llvm::raw_string_ostream os(sbuf);
1869226586Sdim
1870226586Sdim  // This is the allocation site since the previous node had no bindings
1871226586Sdim  // for this symbol.
1872226586Sdim  if (!PrevT) {
1873249423Sdim    const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
1874226586Sdim
1875234353Sdim    if (isa<ObjCArrayLiteral>(S)) {
1876234353Sdim      os << "NSArray literal is an object with a +0 retain count";
1877226586Sdim    }
1878234353Sdim    else if (isa<ObjCDictionaryLiteral>(S)) {
1879234353Sdim      os << "NSDictionary literal is an object with a +0 retain count";
1880226586Sdim    }
1881239462Sdim    else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
1882239462Sdim      if (isNumericLiteralExpression(BL->getSubExpr()))
1883239462Sdim        os << "NSNumber literal is an object with a +0 retain count";
1884239462Sdim      else {
1885239462Sdim        const ObjCInterfaceDecl *BoxClass = 0;
1886239462Sdim        if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
1887239462Sdim          BoxClass = Method->getClassInterface();
1888239462Sdim
1889239462Sdim        // We should always be able to find the boxing class interface,
1890239462Sdim        // but consider this future-proofing.
1891239462Sdim        if (BoxClass)
1892239462Sdim          os << *BoxClass << " b";
1893239462Sdim        else
1894239462Sdim          os << "B";
1895239462Sdim
1896239462Sdim        os << "oxed expression produces an object with a +0 retain count";
1897239462Sdim      }
1898239462Sdim    }
1899234353Sdim    else {
1900234353Sdim      if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1901234353Sdim        // Get the name of the callee (if it is available).
1902234353Sdim        SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
1903234353Sdim        if (const FunctionDecl *FD = X.getAsFunctionDecl())
1904234353Sdim          os << "Call to function '" << *FD << '\'';
1905234353Sdim        else
1906234353Sdim          os << "function call";
1907234353Sdim      }
1908234353Sdim      else {
1909239462Sdim        assert(isa<ObjCMessageExpr>(S));
1910239462Sdim        CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
1911239462Sdim        CallEventRef<ObjCMethodCall> Call
1912239462Sdim          = Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
1913239462Sdim
1914239462Sdim        switch (Call->getMessageKind()) {
1915239462Sdim        case OCM_Message:
1916239462Sdim          os << "Method";
1917239462Sdim          break;
1918239462Sdim        case OCM_PropertyAccess:
1919239462Sdim          os << "Property";
1920239462Sdim          break;
1921239462Sdim        case OCM_Subscript:
1922239462Sdim          os << "Subscript";
1923239462Sdim          break;
1924239462Sdim        }
1925234353Sdim      }
1926226586Sdim
1927234353Sdim      if (CurrV.getObjKind() == RetEffect::CF) {
1928234353Sdim        os << " returns a Core Foundation object with a ";
1929234353Sdim      }
1930234353Sdim      else {
1931234353Sdim        assert (CurrV.getObjKind() == RetEffect::ObjC);
1932234353Sdim        os << " returns an Objective-C object with a ";
1933234353Sdim      }
1934226586Sdim
1935234353Sdim      if (CurrV.isOwned()) {
1936234353Sdim        os << "+1 retain count";
1937226586Sdim
1938234353Sdim        if (GCEnabled) {
1939234353Sdim          assert(CurrV.getObjKind() == RetEffect::CF);
1940234353Sdim          os << ".  "
1941234353Sdim          "Core Foundation objects are not automatically garbage collected.";
1942234353Sdim        }
1943226586Sdim      }
1944234353Sdim      else {
1945234353Sdim        assert (CurrV.isNotOwned());
1946234353Sdim        os << "+0 retain count";
1947234353Sdim      }
1948226586Sdim    }
1949226586Sdim
1950226586Sdim    PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
1951226586Sdim                                  N->getLocationContext());
1952226586Sdim    return new PathDiagnosticEventPiece(Pos, os.str());
1953226586Sdim  }
1954226586Sdim
1955226586Sdim  // Gather up the effects that were performed on the object at this
1956226586Sdim  // program point
1957226586Sdim  SmallVector<ArgEffect, 2> AEffects;
1958226586Sdim
1959226586Sdim  const ExplodedNode *OrigNode = BRC.getNodeResolver().getOriginalNode(N);
1960226586Sdim  if (const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
1961226586Sdim    // We only have summaries attached to nodes after evaluating CallExpr and
1962226586Sdim    // ObjCMessageExprs.
1963249423Sdim    const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
1964226586Sdim
1965226586Sdim    if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1966226586Sdim      // Iterate through the parameter expressions and see if the symbol
1967226586Sdim      // was ever passed as an argument.
1968226586Sdim      unsigned i = 0;
1969226586Sdim
1970226586Sdim      for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
1971226586Sdim           AI!=AE; ++AI, ++i) {
1972226586Sdim
1973226586Sdim        // Retrieve the value of the argument.  Is it the symbol
1974226586Sdim        // we are interested in?
1975234353Sdim        if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
1976226586Sdim          continue;
1977226586Sdim
1978226586Sdim        // We have an argument.  Get the effect!
1979226586Sdim        AEffects.push_back(Summ->getArg(i));
1980226586Sdim      }
1981226586Sdim    }
1982226586Sdim    else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
1983226586Sdim      if (const Expr *receiver = ME->getInstanceReceiver())
1984234353Sdim        if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
1985234353Sdim              .getAsLocSymbol() == Sym) {
1986226586Sdim          // The symbol we are tracking is the receiver.
1987226586Sdim          AEffects.push_back(Summ->getReceiverEffect());
1988226586Sdim        }
1989226586Sdim    }
1990226586Sdim  }
1991226586Sdim
1992226586Sdim  do {
1993226586Sdim    // Get the previous type state.
1994226586Sdim    RefVal PrevV = *PrevT;
1995226586Sdim
1996226586Sdim    // Specially handle -dealloc.
1997226586Sdim    if (!GCEnabled && contains(AEffects, Dealloc)) {
1998226586Sdim      // Determine if the object's reference count was pushed to zero.
1999226586Sdim      assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
2000226586Sdim      // We may not have transitioned to 'release' if we hit an error.
2001226586Sdim      // This case is handled elsewhere.
2002226586Sdim      if (CurrV.getKind() == RefVal::Released) {
2003226586Sdim        assert(CurrV.getCombinedCounts() == 0);
2004226586Sdim        os << "Object released by directly sending the '-dealloc' message";
2005226586Sdim        break;
2006226586Sdim      }
2007226586Sdim    }
2008226586Sdim
2009226586Sdim    // Specially handle CFMakeCollectable and friends.
2010226586Sdim    if (contains(AEffects, MakeCollectable)) {
2011226586Sdim      // Get the name of the function.
2012249423Sdim      const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
2013234353Sdim      SVal X =
2014234353Sdim        CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
2015226586Sdim      const FunctionDecl *FD = X.getAsFunctionDecl();
2016226586Sdim
2017226586Sdim      if (GCEnabled) {
2018226586Sdim        // Determine if the object's reference count was pushed to zero.
2019226586Sdim        assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
2020226586Sdim
2021226586Sdim        os << "In GC mode a call to '" << *FD
2022226586Sdim        <<  "' decrements an object's retain count and registers the "
2023226586Sdim        "object with the garbage collector. ";
2024226586Sdim
2025226586Sdim        if (CurrV.getKind() == RefVal::Released) {
2026226586Sdim          assert(CurrV.getCount() == 0);
2027226586Sdim          os << "Since it now has a 0 retain count the object can be "
2028226586Sdim          "automatically collected by the garbage collector.";
2029226586Sdim        }
2030226586Sdim        else
2031226586Sdim          os << "An object must have a 0 retain count to be garbage collected. "
2032226586Sdim          "After this call its retain count is +" << CurrV.getCount()
2033226586Sdim          << '.';
2034226586Sdim      }
2035226586Sdim      else
2036226586Sdim        os << "When GC is not enabled a call to '" << *FD
2037226586Sdim        << "' has no effect on its argument.";
2038226586Sdim
2039226586Sdim      // Nothing more to say.
2040226586Sdim      break;
2041226586Sdim    }
2042226586Sdim
2043226586Sdim    // Determine if the typestate has changed.
2044226586Sdim    if (!(PrevV == CurrV))
2045226586Sdim      switch (CurrV.getKind()) {
2046226586Sdim        case RefVal::Owned:
2047226586Sdim        case RefVal::NotOwned:
2048226586Sdim
2049226586Sdim          if (PrevV.getCount() == CurrV.getCount()) {
2050226586Sdim            // Did an autorelease message get sent?
2051226586Sdim            if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2052226586Sdim              return 0;
2053226586Sdim
2054226586Sdim            assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2055251662Sdim            os << "Object autoreleased";
2056226586Sdim            break;
2057226586Sdim          }
2058226586Sdim
2059226586Sdim          if (PrevV.getCount() > CurrV.getCount())
2060226586Sdim            os << "Reference count decremented.";
2061226586Sdim          else
2062226586Sdim            os << "Reference count incremented.";
2063226586Sdim
2064226586Sdim          if (unsigned Count = CurrV.getCount())
2065226586Sdim            os << " The object now has a +" << Count << " retain count.";
2066226586Sdim
2067226586Sdim          if (PrevV.getKind() == RefVal::Released) {
2068226586Sdim            assert(GCEnabled && CurrV.getCount() > 0);
2069234353Sdim            os << " The object is not eligible for garbage collection until "
2070234353Sdim                  "the retain count reaches 0 again.";
2071226586Sdim          }
2072226586Sdim
2073226586Sdim          break;
2074226586Sdim
2075226586Sdim        case RefVal::Released:
2076226586Sdim          os << "Object released.";
2077226586Sdim          break;
2078226586Sdim
2079226586Sdim        case RefVal::ReturnedOwned:
2080234353Sdim          // Autoreleases can be applied after marking a node ReturnedOwned.
2081234353Sdim          if (CurrV.getAutoreleaseCount())
2082234353Sdim            return NULL;
2083234353Sdim
2084234353Sdim          os << "Object returned to caller as an owning reference (single "
2085234353Sdim                "retain count transferred to caller)";
2086226586Sdim          break;
2087226586Sdim
2088226586Sdim        case RefVal::ReturnedNotOwned:
2089226586Sdim          os << "Object returned to caller with a +0 retain count";
2090226586Sdim          break;
2091226586Sdim
2092226586Sdim        default:
2093226586Sdim          return NULL;
2094226586Sdim      }
2095226586Sdim
2096226586Sdim    // Emit any remaining diagnostics for the argument effects (if any).
2097226586Sdim    for (SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
2098226586Sdim         E=AEffects.end(); I != E; ++I) {
2099226586Sdim
2100226586Sdim      // A bunch of things have alternate behavior under GC.
2101226586Sdim      if (GCEnabled)
2102226586Sdim        switch (*I) {
2103226586Sdim          default: break;
2104226586Sdim          case Autorelease:
2105226586Sdim            os << "In GC mode an 'autorelease' has no effect.";
2106226586Sdim            continue;
2107226586Sdim          case IncRefMsg:
2108226586Sdim            os << "In GC mode the 'retain' message has no effect.";
2109226586Sdim            continue;
2110226586Sdim          case DecRefMsg:
2111226586Sdim            os << "In GC mode the 'release' message has no effect.";
2112226586Sdim            continue;
2113226586Sdim        }
2114226586Sdim    }
2115226586Sdim  } while (0);
2116226586Sdim
2117226586Sdim  if (os.str().empty())
2118226586Sdim    return 0; // We have nothing to say!
2119226586Sdim
2120249423Sdim  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
2121226586Sdim  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
2122226586Sdim                                N->getLocationContext());
2123226586Sdim  PathDiagnosticPiece *P = new PathDiagnosticEventPiece(Pos, os.str());
2124226586Sdim
2125226586Sdim  // Add the range by scanning the children of the statement for any bindings
2126226586Sdim  // to Sym.
2127226586Sdim  for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
2128226586Sdim       I!=E; ++I)
2129226586Sdim    if (const Expr *Exp = dyn_cast_or_null<Expr>(*I))
2130234353Sdim      if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
2131226586Sdim        P->addRange(Exp->getSourceRange());
2132226586Sdim        break;
2133226586Sdim      }
2134226586Sdim
2135226586Sdim  return P;
2136226586Sdim}
2137226586Sdim
2138234353Sdim// Find the first node in the current function context that referred to the
2139234353Sdim// tracked symbol and the memory location that value was stored to. Note, the
2140234353Sdim// value is only reported if the allocation occurred in the same function as
2141251662Sdim// the leak. The function can also return a location context, which should be
2142251662Sdim// treated as interesting.
2143251662Sdimstruct AllocationInfo {
2144251662Sdim  const ExplodedNode* N;
2145251662Sdim  const MemRegion *R;
2146251662Sdim  const LocationContext *InterestingMethodContext;
2147251662Sdim  AllocationInfo(const ExplodedNode *InN,
2148251662Sdim                 const MemRegion *InR,
2149251662Sdim                 const LocationContext *InInterestingMethodContext) :
2150251662Sdim    N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2151251662Sdim};
2152251662Sdim
2153251662Sdimstatic AllocationInfo
2154226586SdimGetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
2155226586Sdim                  SymbolRef Sym) {
2156251662Sdim  const ExplodedNode *AllocationNode = N;
2157251662Sdim  const ExplodedNode *AllocationNodeInCurrentContext = N;
2158226586Sdim  const MemRegion* FirstBinding = 0;
2159234353Sdim  const LocationContext *LeakContext = N->getLocationContext();
2160226586Sdim
2161251662Sdim  // The location context of the init method called on the leaked object, if
2162251662Sdim  // available.
2163251662Sdim  const LocationContext *InitMethodContext = 0;
2164251662Sdim
2165226586Sdim  while (N) {
2166234353Sdim    ProgramStateRef St = N->getState();
2167251662Sdim    const LocationContext *NContext = N->getLocationContext();
2168226586Sdim
2169239462Sdim    if (!getRefBinding(St, Sym))
2170226586Sdim      break;
2171226586Sdim
2172234353Sdim    StoreManager::FindUniqueBinding FB(Sym);
2173226586Sdim    StateMgr.iterBindings(St, FB);
2174251662Sdim
2175251662Sdim    if (FB) {
2176251662Sdim      const MemRegion *R = FB.getRegion();
2177251662Sdim      const VarRegion *VR = R->getBaseRegion()->getAs<VarRegion>();
2178251662Sdim      // Do not show local variables belonging to a function other than
2179251662Sdim      // where the error is reported.
2180251662Sdim      if (!VR || VR->getStackFrame() == LeakContext->getCurrentStackFrame())
2181251662Sdim        FirstBinding = R;
2182251662Sdim    }
2183226586Sdim
2184251662Sdim    // AllocationNode is the last node in which the symbol was tracked.
2185251662Sdim    AllocationNode = N;
2186234353Sdim
2187251662Sdim    // AllocationNodeInCurrentContext, is the last node in the current context
2188251662Sdim    // in which the symbol was tracked.
2189251662Sdim    if (NContext == LeakContext)
2190251662Sdim      AllocationNodeInCurrentContext = N;
2191251662Sdim
2192251662Sdim    // Find the last init that was called on the given symbol and store the
2193251662Sdim    // init method's location context.
2194251662Sdim    if (!InitMethodContext)
2195251662Sdim      if (Optional<CallEnter> CEP = N->getLocation().getAs<CallEnter>()) {
2196251662Sdim        const Stmt *CE = CEP->getCallExpr();
2197251662Sdim        if (const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2198251662Sdim          const Stmt *RecExpr = ME->getInstanceReceiver();
2199251662Sdim          if (RecExpr) {
2200251662Sdim            SVal RecV = St->getSVal(RecExpr, NContext);
2201251662Sdim            if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
2202251662Sdim              InitMethodContext = CEP->getCalleeContext();
2203251662Sdim          }
2204251662Sdim        }
2205251662Sdim      }
2206251662Sdim
2207226586Sdim    N = N->pred_empty() ? NULL : *(N->pred_begin());
2208226586Sdim  }
2209226586Sdim
2210251662Sdim  // If we are reporting a leak of the object that was allocated with alloc,
2211251662Sdim  // mark its init method as interesting.
2212251662Sdim  const LocationContext *InterestingMethodContext = 0;
2213251662Sdim  if (InitMethodContext) {
2214251662Sdim    const ProgramPoint AllocPP = AllocationNode->getLocation();
2215251662Sdim    if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
2216251662Sdim      if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
2217251662Sdim        if (ME->getMethodFamily() == OMF_alloc)
2218251662Sdim          InterestingMethodContext = InitMethodContext;
2219251662Sdim  }
2220251662Sdim
2221234353Sdim  // If allocation happened in a function different from the leak node context,
2222234353Sdim  // do not report the binding.
2223243830Sdim  assert(N && "Could not find allocation node");
2224234353Sdim  if (N->getLocationContext() != LeakContext) {
2225234353Sdim    FirstBinding = 0;
2226234353Sdim  }
2227234353Sdim
2228251662Sdim  return AllocationInfo(AllocationNodeInCurrentContext,
2229251662Sdim                        FirstBinding,
2230251662Sdim                        InterestingMethodContext);
2231226586Sdim}
2232226586Sdim
2233226586SdimPathDiagnosticPiece*
2234226586SdimCFRefReportVisitor::getEndPath(BugReporterContext &BRC,
2235226586Sdim                               const ExplodedNode *EndN,
2236226586Sdim                               BugReport &BR) {
2237234353Sdim  BR.markInteresting(Sym);
2238226586Sdim  return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
2239226586Sdim}
2240226586Sdim
2241226586SdimPathDiagnosticPiece*
2242226586SdimCFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
2243226586Sdim                                   const ExplodedNode *EndN,
2244226586Sdim                                   BugReport &BR) {
2245226586Sdim
2246226586Sdim  // Tell the BugReporterContext to report cases when the tracked symbol is
2247226586Sdim  // assigned to different variables, etc.
2248234353Sdim  BR.markInteresting(Sym);
2249226586Sdim
2250226586Sdim  // We are reporting a leak.  Walk up the graph to get to the first node where
2251226586Sdim  // the symbol appeared, and also get the first VarDecl that tracked object
2252226586Sdim  // is stored to.
2253251662Sdim  AllocationInfo AllocI =
2254226586Sdim    GetAllocationSite(BRC.getStateManager(), EndN, Sym);
2255226586Sdim
2256251662Sdim  const MemRegion* FirstBinding = AllocI.R;
2257251662Sdim  BR.markInteresting(AllocI.InterestingMethodContext);
2258251662Sdim
2259226586Sdim  SourceManager& SM = BRC.getSourceManager();
2260226586Sdim
2261226586Sdim  // Compute an actual location for the leak.  Sometimes a leak doesn't
2262226586Sdim  // occur at an actual statement (e.g., transition between blocks; end
2263226586Sdim  // of function) so we need to walk the graph and compute a real location.
2264226586Sdim  const ExplodedNode *LeakN = EndN;
2265226586Sdim  PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
2266226586Sdim
2267226586Sdim  std::string sbuf;
2268226586Sdim  llvm::raw_string_ostream os(sbuf);
2269226586Sdim
2270226586Sdim  os << "Object leaked: ";
2271226586Sdim
2272226586Sdim  if (FirstBinding) {
2273226586Sdim    os << "object allocated and stored into '"
2274226586Sdim       << FirstBinding->getString() << '\'';
2275226586Sdim  }
2276226586Sdim  else
2277226586Sdim    os << "allocated object";
2278226586Sdim
2279226586Sdim  // Get the retain count.
2280239462Sdim  const RefVal* RV = getRefBinding(EndN->getState(), Sym);
2281243830Sdim  assert(RV);
2282226586Sdim
2283226586Sdim  if (RV->getKind() == RefVal::ErrorLeakReturned) {
2284226586Sdim    // FIXME: Per comments in rdar://6320065, "create" only applies to CF
2285226586Sdim    // objects.  Only "copy", "alloc", "retain" and "new" transfer ownership
2286226586Sdim    // to the caller for NS objects.
2287226586Sdim    const Decl *D = &EndN->getCodeDecl();
2288243830Sdim
2289243830Sdim    os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
2290243830Sdim                                  : " is returned from a function ");
2291243830Sdim
2292243830Sdim    if (D->getAttr<CFReturnsNotRetainedAttr>())
2293243830Sdim      os << "that is annotated as CF_RETURNS_NOT_RETAINED";
2294243830Sdim    else if (D->getAttr<NSReturnsNotRetainedAttr>())
2295243830Sdim      os << "that is annotated as NS_RETURNS_NOT_RETAINED";
2296243830Sdim    else {
2297243830Sdim      if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
2298243830Sdim        os << "whose name ('" << MD->getSelector().getAsString()
2299243830Sdim           << "') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
2300243830Sdim              "  This violates the naming convention rules"
2301243830Sdim              " given in the Memory Management Guide for Cocoa";
2302243830Sdim      }
2303243830Sdim      else {
2304243830Sdim        const FunctionDecl *FD = cast<FunctionDecl>(D);
2305243830Sdim        os << "whose name ('" << *FD
2306243830Sdim           << "') does not contain 'Copy' or 'Create'.  This violates the naming"
2307243830Sdim              " convention rules given in the Memory Management Guide for Core"
2308243830Sdim              " Foundation";
2309243830Sdim      }
2310226586Sdim    }
2311226586Sdim  }
2312226586Sdim  else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2313249423Sdim    const ObjCMethodDecl &MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
2314226586Sdim    os << " and returned from method '" << MD.getSelector().getAsString()
2315226586Sdim       << "' is potentially leaked when using garbage collection.  Callers "
2316226586Sdim          "of this method do not expect a returned object with a +1 retain "
2317226586Sdim          "count since they expect the object to be managed by the garbage "
2318226586Sdim          "collector";
2319226586Sdim  }
2320226586Sdim  else
2321226586Sdim    os << " is not referenced later in this execution path and has a retain "
2322226586Sdim          "count of +" << RV->getCount();
2323226586Sdim
2324226586Sdim  return new PathDiagnosticEventPiece(L, os.str());
2325226586Sdim}
2326226586Sdim
2327226586SdimCFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
2328226586Sdim                                 bool GCEnabled, const SummaryLogTy &Log,
2329226586Sdim                                 ExplodedNode *n, SymbolRef sym,
2330251662Sdim                                 CheckerContext &Ctx,
2331251662Sdim                                 bool IncludeAllocationLine)
2332251662Sdim  : CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) {
2333226586Sdim
2334226586Sdim  // Most bug reports are cached at the location where they occurred.
2335226586Sdim  // With leaks, we want to unique them by the location where they were
2336226586Sdim  // allocated, and only report a single path.  To do this, we need to find
2337226586Sdim  // the allocation site of a piece of tracked memory, which we do via a
2338226586Sdim  // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
2339226586Sdim  // Note that this is *not* the trimmed graph; we are guaranteed, however,
2340226586Sdim  // that all ancestor nodes that represent the allocation site have the
2341226586Sdim  // same SourceLocation.
2342226586Sdim  const ExplodedNode *AllocNode = 0;
2343226586Sdim
2344234353Sdim  const SourceManager& SMgr = Ctx.getSourceManager();
2345226586Sdim
2346251662Sdim  AllocationInfo AllocI =
2347234353Sdim    GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
2348226586Sdim
2349251662Sdim  AllocNode = AllocI.N;
2350251662Sdim  AllocBinding = AllocI.R;
2351251662Sdim  markInteresting(AllocI.InterestingMethodContext);
2352251662Sdim
2353226586Sdim  // Get the SourceLocation for the allocation site.
2354239462Sdim  // FIXME: This will crash the analyzer if an allocation comes from an
2355239462Sdim  // implicit call. (Currently there are no such allocations in Cocoa, though.)
2356239462Sdim  const Stmt *AllocStmt;
2357226586Sdim  ProgramPoint P = AllocNode->getLocation();
2358249423Sdim  if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
2359239462Sdim    AllocStmt = Exit->getCalleeContext()->getCallSite();
2360239462Sdim  else
2361249423Sdim    AllocStmt = P.castAs<PostStmt>().getStmt();
2362239462Sdim  assert(AllocStmt && "All allocations must come from explicit calls");
2363251662Sdim
2364251662Sdim  PathDiagnosticLocation AllocLocation =
2365251662Sdim    PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
2366251662Sdim                                        AllocNode->getLocationContext());
2367251662Sdim  Location = AllocLocation;
2368251662Sdim
2369251662Sdim  // Set uniqieing info, which will be used for unique the bug reports. The
2370251662Sdim  // leaks should be uniqued on the allocation site.
2371251662Sdim  UniqueingLocation = AllocLocation;
2372251662Sdim  UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2373251662Sdim
2374226586Sdim  // Fill in the description of the bug.
2375226586Sdim  Description.clear();
2376226586Sdim  llvm::raw_string_ostream os(Description);
2377226586Sdim  os << "Potential leak ";
2378226586Sdim  if (GCEnabled)
2379226586Sdim    os << "(when using garbage collection) ";
2380234353Sdim  os << "of an object";
2381226586Sdim
2382251662Sdim  if (AllocBinding) {
2383234353Sdim    os << " stored into '" << AllocBinding->getString() << '\'';
2384251662Sdim    if (IncludeAllocationLine) {
2385251662Sdim      FullSourceLoc SL(AllocStmt->getLocStart(), Ctx.getSourceManager());
2386251662Sdim      os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
2387251662Sdim    }
2388251662Sdim  }
2389226586Sdim
2390226586Sdim  addVisitor(new CFRefLeakReportVisitor(sym, GCEnabled, Log));
2391226586Sdim}
2392226586Sdim
2393226586Sdim//===----------------------------------------------------------------------===//
2394226586Sdim// Main checker logic.
2395226586Sdim//===----------------------------------------------------------------------===//
2396226586Sdim
2397226586Sdimnamespace {
2398226586Sdimclass RetainCountChecker
2399226586Sdim  : public Checker< check::Bind,
2400226586Sdim                    check::DeadSymbols,
2401226586Sdim                    check::EndAnalysis,
2402249423Sdim                    check::EndFunction,
2403226586Sdim                    check::PostStmt<BlockExpr>,
2404226586Sdim                    check::PostStmt<CastExpr>,
2405234353Sdim                    check::PostStmt<ObjCArrayLiteral>,
2406234353Sdim                    check::PostStmt<ObjCDictionaryLiteral>,
2407239462Sdim                    check::PostStmt<ObjCBoxedExpr>,
2408239462Sdim                    check::PostCall,
2409226586Sdim                    check::PreStmt<ReturnStmt>,
2410226586Sdim                    check::RegionChanges,
2411226586Sdim                    eval::Assume,
2412226586Sdim                    eval::Call > {
2413234353Sdim  mutable OwningPtr<CFRefBug> useAfterRelease, releaseNotOwned;
2414234353Sdim  mutable OwningPtr<CFRefBug> deallocGC, deallocNotOwned;
2415234353Sdim  mutable OwningPtr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2416234353Sdim  mutable OwningPtr<CFRefBug> leakWithinFunction, leakAtReturn;
2417234353Sdim  mutable OwningPtr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2418226586Sdim
2419226586Sdim  typedef llvm::DenseMap<SymbolRef, const SimpleProgramPointTag *> SymbolTagMap;
2420226586Sdim
2421226586Sdim  // This map is only used to ensure proper deletion of any allocated tags.
2422226586Sdim  mutable SymbolTagMap DeadSymbolTags;
2423226586Sdim
2424234353Sdim  mutable OwningPtr<RetainSummaryManager> Summaries;
2425234353Sdim  mutable OwningPtr<RetainSummaryManager> SummariesGC;
2426226586Sdim  mutable SummaryLogTy SummaryLog;
2427226586Sdim  mutable bool ShouldResetSummaryLog;
2428226586Sdim
2429251662Sdim  /// Optional setting to indicate if leak reports should include
2430251662Sdim  /// the allocation line.
2431251662Sdim  mutable bool IncludeAllocationLine;
2432251662Sdim
2433226586Sdimpublic:
2434251662Sdim  RetainCountChecker(AnalyzerOptions &AO)
2435251662Sdim    : ShouldResetSummaryLog(false),
2436251662Sdim      IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
2437226586Sdim
2438226586Sdim  virtual ~RetainCountChecker() {
2439226586Sdim    DeleteContainerSeconds(DeadSymbolTags);
2440226586Sdim  }
2441226586Sdim
2442226586Sdim  void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
2443226586Sdim                        ExprEngine &Eng) const {
2444226586Sdim    // FIXME: This is a hack to make sure the summary log gets cleared between
2445226586Sdim    // analyses of different code bodies.
2446226586Sdim    //
2447226586Sdim    // Why is this necessary? Because a checker's lifetime is tied to a
2448226586Sdim    // translation unit, but an ExplodedGraph's lifetime is just a code body.
2449226586Sdim    // Once in a blue moon, a new ExplodedNode will have the same address as an
2450226586Sdim    // old one with an associated summary, and the bug report visitor gets very
2451226586Sdim    // confused. (To make things worse, the summary lifetime is currently also
2452226586Sdim    // tied to a code body, so we get a crash instead of incorrect results.)
2453226586Sdim    //
2454226586Sdim    // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
2455226586Sdim    // changes, things will start going wrong again. Really the lifetime of this
2456226586Sdim    // log needs to be tied to either the specific nodes in it or the entire
2457226586Sdim    // ExplodedGraph, not to a specific part of the code being analyzed.
2458226586Sdim    //
2459226586Sdim    // (Also, having stateful local data means that the same checker can't be
2460226586Sdim    // used from multiple threads, but a lot of checkers have incorrect
2461226586Sdim    // assumptions about that anyway. So that wasn't a priority at the time of
2462226586Sdim    // this fix.)
2463226586Sdim    //
2464226586Sdim    // This happens at the end of analysis, but bug reports are emitted /after/
2465226586Sdim    // this point. So we can't just clear the summary log now. Instead, we mark
2466226586Sdim    // that the next time we access the summary log, it should be cleared.
2467226586Sdim
2468226586Sdim    // If we never reset the summary log during /this/ code body analysis,
2469226586Sdim    // there were no new summaries. There might still have been summaries from
2470226586Sdim    // the /last/ analysis, so clear them out to make sure the bug report
2471226586Sdim    // visitors don't get confused.
2472226586Sdim    if (ShouldResetSummaryLog)
2473226586Sdim      SummaryLog.clear();
2474226586Sdim
2475226586Sdim    ShouldResetSummaryLog = !SummaryLog.empty();
2476226586Sdim  }
2477226586Sdim
2478226586Sdim  CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts,
2479226586Sdim                                     bool GCEnabled) const {
2480226586Sdim    if (GCEnabled) {
2481226586Sdim      if (!leakWithinFunctionGC)
2482239462Sdim        leakWithinFunctionGC.reset(new Leak("Leak of object when using "
2483239462Sdim                                             "garbage collection"));
2484226586Sdim      return leakWithinFunctionGC.get();
2485226586Sdim    } else {
2486226586Sdim      if (!leakWithinFunction) {
2487226586Sdim        if (LOpts.getGC() == LangOptions::HybridGC) {
2488239462Sdim          leakWithinFunction.reset(new Leak("Leak of object when not using "
2489239462Sdim                                            "garbage collection (GC) in "
2490239462Sdim                                            "dual GC/non-GC code"));
2491226586Sdim        } else {
2492239462Sdim          leakWithinFunction.reset(new Leak("Leak"));
2493226586Sdim        }
2494226586Sdim      }
2495226586Sdim      return leakWithinFunction.get();
2496226586Sdim    }
2497226586Sdim  }
2498226586Sdim
2499226586Sdim  CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts, bool GCEnabled) const {
2500226586Sdim    if (GCEnabled) {
2501226586Sdim      if (!leakAtReturnGC)
2502239462Sdim        leakAtReturnGC.reset(new Leak("Leak of returned object when using "
2503239462Sdim                                      "garbage collection"));
2504226586Sdim      return leakAtReturnGC.get();
2505226586Sdim    } else {
2506226586Sdim      if (!leakAtReturn) {
2507226586Sdim        if (LOpts.getGC() == LangOptions::HybridGC) {
2508239462Sdim          leakAtReturn.reset(new Leak("Leak of returned object when not using "
2509239462Sdim                                      "garbage collection (GC) in dual "
2510239462Sdim                                      "GC/non-GC code"));
2511226586Sdim        } else {
2512239462Sdim          leakAtReturn.reset(new Leak("Leak of returned object"));
2513226586Sdim        }
2514226586Sdim      }
2515226586Sdim      return leakAtReturn.get();
2516226586Sdim    }
2517226586Sdim  }
2518226586Sdim
2519226586Sdim  RetainSummaryManager &getSummaryManager(ASTContext &Ctx,
2520226586Sdim                                          bool GCEnabled) const {
2521226586Sdim    // FIXME: We don't support ARC being turned on and off during one analysis.
2522226586Sdim    // (nor, for that matter, do we support changing ASTContexts)
2523234353Sdim    bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
2524226586Sdim    if (GCEnabled) {
2525226586Sdim      if (!SummariesGC)
2526226586Sdim        SummariesGC.reset(new RetainSummaryManager(Ctx, true, ARCEnabled));
2527226586Sdim      else
2528226586Sdim        assert(SummariesGC->isARCEnabled() == ARCEnabled);
2529226586Sdim      return *SummariesGC;
2530226586Sdim    } else {
2531226586Sdim      if (!Summaries)
2532226586Sdim        Summaries.reset(new RetainSummaryManager(Ctx, false, ARCEnabled));
2533226586Sdim      else
2534226586Sdim        assert(Summaries->isARCEnabled() == ARCEnabled);
2535226586Sdim      return *Summaries;
2536226586Sdim    }
2537226586Sdim  }
2538226586Sdim
2539226586Sdim  RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
2540226586Sdim    return getSummaryManager(C.getASTContext(), C.isObjCGCEnabled());
2541226586Sdim  }
2542226586Sdim
2543234353Sdim  void printState(raw_ostream &Out, ProgramStateRef State,
2544226586Sdim                  const char *NL, const char *Sep) const;
2545226586Sdim
2546226586Sdim  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
2547226586Sdim  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
2548226586Sdim  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
2549226586Sdim
2550234353Sdim  void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
2551234353Sdim  void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
2552239462Sdim  void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
2553239462Sdim
2554239462Sdim  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
2555234353Sdim
2556239462Sdim  void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
2557226586Sdim                    CheckerContext &C) const;
2558226586Sdim
2559243830Sdim  void processSummaryOfInlined(const RetainSummary &Summ,
2560243830Sdim                               const CallEvent &Call,
2561243830Sdim                               CheckerContext &C) const;
2562243830Sdim
2563226586Sdim  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
2564226586Sdim
2565234353Sdim  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
2566226586Sdim                                 bool Assumption) const;
2567226586Sdim
2568234353Sdim  ProgramStateRef
2569234353Sdim  checkRegionChanges(ProgramStateRef state,
2570249423Sdim                     const InvalidatedSymbols *invalidated,
2571226586Sdim                     ArrayRef<const MemRegion *> ExplicitRegions,
2572234353Sdim                     ArrayRef<const MemRegion *> Regions,
2573239462Sdim                     const CallEvent *Call) const;
2574226586Sdim
2575234353Sdim  bool wantsRegionChangeUpdate(ProgramStateRef state) const {
2576226586Sdim    return true;
2577226586Sdim  }
2578226586Sdim
2579226586Sdim  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
2580226586Sdim  void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
2581226586Sdim                                ExplodedNode *Pred, RetEffect RE, RefVal X,
2582234353Sdim                                SymbolRef Sym, ProgramStateRef state) const;
2583226586Sdim
2584226586Sdim  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
2585249423Sdim  void checkEndFunction(CheckerContext &C) const;
2586226586Sdim
2587234353Sdim  ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
2588243830Sdim                               RefVal V, ArgEffect E, RefVal::Kind &hasErr,
2589243830Sdim                               CheckerContext &C) const;
2590226586Sdim
2591234353Sdim  void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
2592226586Sdim                           RefVal::Kind ErrorKind, SymbolRef Sym,
2593226586Sdim                           CheckerContext &C) const;
2594234353Sdim
2595234353Sdim  void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
2596226586Sdim
2597226586Sdim  const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const;
2598226586Sdim
2599234353Sdim  ProgramStateRef handleSymbolDeath(ProgramStateRef state,
2600239462Sdim                                    SymbolRef sid, RefVal V,
2601239462Sdim                                    SmallVectorImpl<SymbolRef> &Leaked) const;
2602226586Sdim
2603249423Sdim  ProgramStateRef
2604243830Sdim  handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
2605243830Sdim                          const ProgramPointTag *Tag, CheckerContext &Ctx,
2606243830Sdim                          SymbolRef Sym, RefVal V) const;
2607226586Sdim
2608234353Sdim  ExplodedNode *processLeaks(ProgramStateRef state,
2609226586Sdim                             SmallVectorImpl<SymbolRef> &Leaked,
2610234353Sdim                             CheckerContext &Ctx,
2611226586Sdim                             ExplodedNode *Pred = 0) const;
2612226586Sdim};
2613226586Sdim} // end anonymous namespace
2614226586Sdim
2615226586Sdimnamespace {
2616226586Sdimclass StopTrackingCallback : public SymbolVisitor {
2617234353Sdim  ProgramStateRef state;
2618226586Sdimpublic:
2619234353Sdim  StopTrackingCallback(ProgramStateRef st) : state(st) {}
2620234353Sdim  ProgramStateRef getState() const { return state; }
2621226586Sdim
2622226586Sdim  bool VisitSymbol(SymbolRef sym) {
2623226586Sdim    state = state->remove<RefBindings>(sym);
2624226586Sdim    return true;
2625226586Sdim  }
2626226586Sdim};
2627226586Sdim} // end anonymous namespace
2628226586Sdim
2629226586Sdim//===----------------------------------------------------------------------===//
2630226586Sdim// Handle statements that may have an effect on refcounts.
2631226586Sdim//===----------------------------------------------------------------------===//
2632226586Sdim
2633226586Sdimvoid RetainCountChecker::checkPostStmt(const BlockExpr *BE,
2634226586Sdim                                       CheckerContext &C) const {
2635226586Sdim
2636226586Sdim  // Scan the BlockDecRefExprs for any object the retain count checker
2637226586Sdim  // may be tracking.
2638226586Sdim  if (!BE->getBlockDecl()->hasCaptures())
2639226586Sdim    return;
2640226586Sdim
2641234353Sdim  ProgramStateRef state = C.getState();
2642226586Sdim  const BlockDataRegion *R =
2643234353Sdim    cast<BlockDataRegion>(state->getSVal(BE,
2644234353Sdim                                         C.getLocationContext()).getAsRegion());
2645226586Sdim
2646226586Sdim  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
2647226586Sdim                                            E = R->referenced_vars_end();
2648226586Sdim
2649226586Sdim  if (I == E)
2650226586Sdim    return;
2651226586Sdim
2652226586Sdim  // FIXME: For now we invalidate the tracking of all symbols passed to blocks
2653226586Sdim  // via captured variables, even though captured variables result in a copy
2654226586Sdim  // and in implicit increment/decrement of a retain count.
2655226586Sdim  SmallVector<const MemRegion*, 10> Regions;
2656234353Sdim  const LocationContext *LC = C.getLocationContext();
2657226586Sdim  MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
2658226586Sdim
2659226586Sdim  for ( ; I != E; ++I) {
2660249423Sdim    const VarRegion *VR = I.getCapturedRegion();
2661226586Sdim    if (VR->getSuperRegion() == R) {
2662226586Sdim      VR = MemMgr.getVarRegion(VR->getDecl(), LC);
2663226586Sdim    }
2664226586Sdim    Regions.push_back(VR);
2665226586Sdim  }
2666226586Sdim
2667226586Sdim  state =
2668226586Sdim    state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2669226586Sdim                                    Regions.data() + Regions.size()).getState();
2670226586Sdim  C.addTransition(state);
2671226586Sdim}
2672226586Sdim
2673226586Sdimvoid RetainCountChecker::checkPostStmt(const CastExpr *CE,
2674226586Sdim                                       CheckerContext &C) const {
2675226586Sdim  const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
2676226586Sdim  if (!BE)
2677226586Sdim    return;
2678226586Sdim
2679226586Sdim  ArgEffect AE = IncRef;
2680226586Sdim
2681226586Sdim  switch (BE->getBridgeKind()) {
2682226586Sdim    case clang::OBC_Bridge:
2683226586Sdim      // Do nothing.
2684226586Sdim      return;
2685226586Sdim    case clang::OBC_BridgeRetained:
2686226586Sdim      AE = IncRef;
2687226586Sdim      break;
2688226586Sdim    case clang::OBC_BridgeTransfer:
2689226586Sdim      AE = DecRefBridgedTransfered;
2690226586Sdim      break;
2691226586Sdim  }
2692226586Sdim
2693234353Sdim  ProgramStateRef state = C.getState();
2694234353Sdim  SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
2695226586Sdim  if (!Sym)
2696226586Sdim    return;
2697239462Sdim  const RefVal* T = getRefBinding(state, Sym);
2698226586Sdim  if (!T)
2699226586Sdim    return;
2700226586Sdim
2701226586Sdim  RefVal::Kind hasErr = (RefVal::Kind) 0;
2702226586Sdim  state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2703226586Sdim
2704226586Sdim  if (hasErr) {
2705226586Sdim    // FIXME: If we get an error during a bridge cast, should we report it?
2706226586Sdim    // Should we assert that there is no error?
2707226586Sdim    return;
2708226586Sdim  }
2709226586Sdim
2710234353Sdim  C.addTransition(state);
2711226586Sdim}
2712226586Sdim
2713234353Sdimvoid RetainCountChecker::processObjCLiterals(CheckerContext &C,
2714234353Sdim                                             const Expr *Ex) const {
2715234353Sdim  ProgramStateRef state = C.getState();
2716234353Sdim  const ExplodedNode *pred = C.getPredecessor();
2717234353Sdim  for (Stmt::const_child_iterator it = Ex->child_begin(), et = Ex->child_end() ;
2718234353Sdim       it != et ; ++it) {
2719234353Sdim    const Stmt *child = *it;
2720234353Sdim    SVal V = state->getSVal(child, pred->getLocationContext());
2721234353Sdim    if (SymbolRef sym = V.getAsSymbol())
2722239462Sdim      if (const RefVal* T = getRefBinding(state, sym)) {
2723234353Sdim        RefVal::Kind hasErr = (RefVal::Kind) 0;
2724234353Sdim        state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
2725234353Sdim        if (hasErr) {
2726234353Sdim          processNonLeakError(state, child->getSourceRange(), hasErr, sym, C);
2727234353Sdim          return;
2728234353Sdim        }
2729234353Sdim      }
2730234353Sdim  }
2731234353Sdim
2732234353Sdim  // Return the object as autoreleased.
2733234353Sdim  //  RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
2734234353Sdim  if (SymbolRef sym =
2735234353Sdim        state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
2736234353Sdim    QualType ResultTy = Ex->getType();
2737239462Sdim    state = setRefBinding(state, sym,
2738239462Sdim                          RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
2739234353Sdim  }
2740234353Sdim
2741234353Sdim  C.addTransition(state);
2742234353Sdim}
2743234353Sdim
2744234353Sdimvoid RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
2745234353Sdim                                       CheckerContext &C) const {
2746234353Sdim  // Apply the 'MayEscape' to all values.
2747234353Sdim  processObjCLiterals(C, AL);
2748234353Sdim}
2749234353Sdim
2750234353Sdimvoid RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
2751234353Sdim                                       CheckerContext &C) const {
2752234353Sdim  // Apply the 'MayEscape' to all keys and values.
2753234353Sdim  processObjCLiterals(C, DL);
2754234353Sdim}
2755234353Sdim
2756239462Sdimvoid RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
2757239462Sdim                                       CheckerContext &C) const {
2758239462Sdim  const ExplodedNode *Pred = C.getPredecessor();
2759239462Sdim  const LocationContext *LCtx = Pred->getLocationContext();
2760239462Sdim  ProgramStateRef State = Pred->getState();
2761226586Sdim
2762239462Sdim  if (SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
2763239462Sdim    QualType ResultTy = Ex->getType();
2764239462Sdim    State = setRefBinding(State, Sym,
2765239462Sdim                          RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
2766226586Sdim  }
2767226586Sdim
2768239462Sdim  C.addTransition(State);
2769239462Sdim}
2770239462Sdim
2771239462Sdimvoid RetainCountChecker::checkPostCall(const CallEvent &Call,
2772239462Sdim                                       CheckerContext &C) const {
2773239462Sdim  RetainSummaryManager &Summaries = getSummaryManager(C);
2774239462Sdim  const RetainSummary *Summ = Summaries.getSummary(Call, C.getState());
2775243830Sdim
2776243830Sdim  if (C.wasInlined) {
2777243830Sdim    processSummaryOfInlined(*Summ, Call, C);
2778243830Sdim    return;
2779243830Sdim  }
2780239462Sdim  checkSummary(*Summ, Call, C);
2781226586Sdim}
2782226586Sdim
2783226586Sdim/// GetReturnType - Used to get the return type of a message expression or
2784226586Sdim///  function call with the intention of affixing that type to a tracked symbol.
2785239462Sdim///  While the return type can be queried directly from RetEx, when
2786226586Sdim///  invoking class methods we augment to the return type to be that of
2787226586Sdim///  a pointer to the class (as opposed it just being id).
2788226586Sdim// FIXME: We may be able to do this with related result types instead.
2789226586Sdim// This function is probably overestimating.
2790226586Sdimstatic QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
2791226586Sdim  QualType RetTy = RetE->getType();
2792226586Sdim  // If RetE is not a message expression just return its type.
2793226586Sdim  // If RetE is a message expression, return its types if it is something
2794226586Sdim  /// more specific than id.
2795226586Sdim  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
2796226586Sdim    if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
2797226586Sdim      if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2798226586Sdim          PT->isObjCClassType()) {
2799226586Sdim        // At this point we know the return type of the message expression is
2800226586Sdim        // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
2801226586Sdim        // is a call to a class method whose type we can resolve.  In such
2802226586Sdim        // cases, promote the return type to XXX* (where XXX is the class).
2803226586Sdim        const ObjCInterfaceDecl *D = ME->getReceiverInterface();
2804226586Sdim        return !D ? RetTy :
2805226586Sdim                    Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
2806226586Sdim      }
2807226586Sdim
2808226586Sdim  return RetTy;
2809226586Sdim}
2810226586Sdim
2811243830Sdim// We don't always get the exact modeling of the function with regards to the
2812243830Sdim// retain count checker even when the function is inlined. For example, we need
2813243830Sdim// to stop tracking the symbols which were marked with StopTrackingHard.
2814243830Sdimvoid RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
2815243830Sdim                                                 const CallEvent &CallOrMsg,
2816243830Sdim                                                 CheckerContext &C) const {
2817243830Sdim  ProgramStateRef state = C.getState();
2818243830Sdim
2819243830Sdim  // Evaluate the effect of the arguments.
2820243830Sdim  for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
2821243830Sdim    if (Summ.getArg(idx) == StopTrackingHard) {
2822243830Sdim      SVal V = CallOrMsg.getArgSVal(idx);
2823243830Sdim      if (SymbolRef Sym = V.getAsLocSymbol()) {
2824243830Sdim        state = removeRefBinding(state, Sym);
2825243830Sdim      }
2826243830Sdim    }
2827243830Sdim  }
2828243830Sdim
2829243830Sdim  // Evaluate the effect on the message receiver.
2830243830Sdim  const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
2831243830Sdim  if (MsgInvocation) {
2832243830Sdim    if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
2833243830Sdim      if (Summ.getReceiverEffect() == StopTrackingHard) {
2834243830Sdim        state = removeRefBinding(state, Sym);
2835243830Sdim      }
2836243830Sdim    }
2837243830Sdim  }
2838243830Sdim
2839243830Sdim  // Consult the summary for the return value.
2840243830Sdim  RetEffect RE = Summ.getRetEffect();
2841243830Sdim  if (RE.getKind() == RetEffect::NoRetHard) {
2842243830Sdim    SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
2843243830Sdim    if (Sym)
2844243830Sdim      state = removeRefBinding(state, Sym);
2845243830Sdim  }
2846243830Sdim
2847243830Sdim  C.addTransition(state);
2848243830Sdim}
2849243830Sdim
2850226586Sdimvoid RetainCountChecker::checkSummary(const RetainSummary &Summ,
2851239462Sdim                                      const CallEvent &CallOrMsg,
2852226586Sdim                                      CheckerContext &C) const {
2853234353Sdim  ProgramStateRef state = C.getState();
2854226586Sdim
2855226586Sdim  // Evaluate the effect of the arguments.
2856226586Sdim  RefVal::Kind hasErr = (RefVal::Kind) 0;
2857226586Sdim  SourceRange ErrorRange;
2858226586Sdim  SymbolRef ErrorSym = 0;
2859226586Sdim
2860226586Sdim  for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
2861226586Sdim    SVal V = CallOrMsg.getArgSVal(idx);
2862226586Sdim
2863226586Sdim    if (SymbolRef Sym = V.getAsLocSymbol()) {
2864239462Sdim      if (const RefVal *T = getRefBinding(state, Sym)) {
2865226586Sdim        state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr, C);
2866226586Sdim        if (hasErr) {
2867226586Sdim          ErrorRange = CallOrMsg.getArgSourceRange(idx);
2868226586Sdim          ErrorSym = Sym;
2869226586Sdim          break;
2870226586Sdim        }
2871226586Sdim      }
2872226586Sdim    }
2873226586Sdim  }
2874226586Sdim
2875226586Sdim  // Evaluate the effect on the message receiver.
2876226586Sdim  bool ReceiverIsTracked = false;
2877239462Sdim  if (!hasErr) {
2878239462Sdim    const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
2879239462Sdim    if (MsgInvocation) {
2880239462Sdim      if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
2881239462Sdim        if (const RefVal *T = getRefBinding(state, Sym)) {
2882239462Sdim          ReceiverIsTracked = true;
2883239462Sdim          state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
2884243830Sdim                                 hasErr, C);
2885239462Sdim          if (hasErr) {
2886239462Sdim            ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
2887239462Sdim            ErrorSym = Sym;
2888239462Sdim          }
2889226586Sdim        }
2890226586Sdim      }
2891226586Sdim    }
2892226586Sdim  }
2893226586Sdim
2894226586Sdim  // Process any errors.
2895226586Sdim  if (hasErr) {
2896226586Sdim    processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
2897226586Sdim    return;
2898226586Sdim  }
2899226586Sdim
2900226586Sdim  // Consult the summary for the return value.
2901226586Sdim  RetEffect RE = Summ.getRetEffect();
2902226586Sdim
2903226586Sdim  if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
2904226586Sdim    if (ReceiverIsTracked)
2905226586Sdim      RE = getSummaryManager(C).getObjAllocRetEffect();
2906226586Sdim    else
2907226586Sdim      RE = RetEffect::MakeNoRet();
2908226586Sdim  }
2909226586Sdim
2910226586Sdim  switch (RE.getKind()) {
2911226586Sdim    default:
2912234353Sdim      llvm_unreachable("Unhandled RetEffect.");
2913226586Sdim
2914226586Sdim    case RetEffect::NoRet:
2915243830Sdim    case RetEffect::NoRetHard:
2916226586Sdim      // No work necessary.
2917226586Sdim      break;
2918226586Sdim
2919226586Sdim    case RetEffect::OwnedAllocatedSymbol:
2920226586Sdim    case RetEffect::OwnedSymbol: {
2921243830Sdim      SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
2922226586Sdim      if (!Sym)
2923226586Sdim        break;
2924226586Sdim
2925239462Sdim      // Use the result type from the CallEvent as it automatically adjusts
2926226586Sdim      // for methods/functions that return references.
2927239462Sdim      QualType ResultTy = CallOrMsg.getResultType();
2928239462Sdim      state = setRefBinding(state, Sym, RefVal::makeOwned(RE.getObjKind(),
2929239462Sdim                                                          ResultTy));
2930226586Sdim
2931226586Sdim      // FIXME: Add a flag to the checker where allocations are assumed to
2932239462Sdim      // *not* fail.
2933226586Sdim      break;
2934226586Sdim    }
2935226586Sdim
2936226586Sdim    case RetEffect::GCNotOwnedSymbol:
2937226586Sdim    case RetEffect::ARCNotOwnedSymbol:
2938226586Sdim    case RetEffect::NotOwnedSymbol: {
2939226586Sdim      const Expr *Ex = CallOrMsg.getOriginExpr();
2940243830Sdim      SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
2941226586Sdim      if (!Sym)
2942226586Sdim        break;
2943243830Sdim      assert(Ex);
2944226586Sdim      // Use GetReturnType in order to give [NSFoo alloc] the type NSFoo *.
2945226586Sdim      QualType ResultTy = GetReturnType(Ex, C.getASTContext());
2946239462Sdim      state = setRefBinding(state, Sym, RefVal::makeNotOwned(RE.getObjKind(),
2947239462Sdim                                                             ResultTy));
2948226586Sdim      break;
2949226586Sdim    }
2950226586Sdim  }
2951226586Sdim
2952226586Sdim  // This check is actually necessary; otherwise the statement builder thinks
2953226586Sdim  // we've hit a previously-found path.
2954226586Sdim  // Normally addTransition takes care of this, but we want the node pointer.
2955226586Sdim  ExplodedNode *NewNode;
2956226586Sdim  if (state == C.getState()) {
2957226586Sdim    NewNode = C.getPredecessor();
2958226586Sdim  } else {
2959234353Sdim    NewNode = C.addTransition(state);
2960226586Sdim  }
2961226586Sdim
2962226586Sdim  // Annotate the node with summary we used.
2963226586Sdim  if (NewNode) {
2964226586Sdim    // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
2965226586Sdim    if (ShouldResetSummaryLog) {
2966226586Sdim      SummaryLog.clear();
2967226586Sdim      ShouldResetSummaryLog = false;
2968226586Sdim    }
2969226586Sdim    SummaryLog[NewNode] = &Summ;
2970226586Sdim  }
2971226586Sdim}
2972226586Sdim
2973226586Sdim
2974234353SdimProgramStateRef
2975234353SdimRetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
2976226586Sdim                                 RefVal V, ArgEffect E, RefVal::Kind &hasErr,
2977226586Sdim                                 CheckerContext &C) const {
2978226586Sdim  // In GC mode [... release] and [... retain] do nothing.
2979226586Sdim  // In ARC mode they shouldn't exist at all, but we just ignore them.
2980226586Sdim  bool IgnoreRetainMsg = C.isObjCGCEnabled();
2981226586Sdim  if (!IgnoreRetainMsg)
2982234353Sdim    IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
2983226586Sdim
2984226586Sdim  switch (E) {
2985239462Sdim  default:
2986239462Sdim    break;
2987239462Sdim  case IncRefMsg:
2988239462Sdim    E = IgnoreRetainMsg ? DoNothing : IncRef;
2989239462Sdim    break;
2990239462Sdim  case DecRefMsg:
2991239462Sdim    E = IgnoreRetainMsg ? DoNothing : DecRef;
2992239462Sdim    break;
2993243830Sdim  case DecRefMsgAndStopTrackingHard:
2994243830Sdim    E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
2995239462Sdim    break;
2996239462Sdim  case MakeCollectable:
2997239462Sdim    E = C.isObjCGCEnabled() ? DecRef : DoNothing;
2998239462Sdim    break;
2999226586Sdim  }
3000226586Sdim
3001226586Sdim  // Handle all use-after-releases.
3002226586Sdim  if (!C.isObjCGCEnabled() && V.getKind() == RefVal::Released) {
3003226586Sdim    V = V ^ RefVal::ErrorUseAfterRelease;
3004226586Sdim    hasErr = V.getKind();
3005239462Sdim    return setRefBinding(state, sym, V);
3006226586Sdim  }
3007226586Sdim
3008226586Sdim  switch (E) {
3009226586Sdim    case DecRefMsg:
3010226586Sdim    case IncRefMsg:
3011226586Sdim    case MakeCollectable:
3012243830Sdim    case DecRefMsgAndStopTrackingHard:
3013226586Sdim      llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
3014226586Sdim
3015226586Sdim    case Dealloc:
3016226586Sdim      // Any use of -dealloc in GC is *bad*.
3017226586Sdim      if (C.isObjCGCEnabled()) {
3018226586Sdim        V = V ^ RefVal::ErrorDeallocGC;
3019226586Sdim        hasErr = V.getKind();
3020226586Sdim        break;
3021226586Sdim      }
3022226586Sdim
3023226586Sdim      switch (V.getKind()) {
3024226586Sdim        default:
3025226586Sdim          llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
3026226586Sdim        case RefVal::Owned:
3027226586Sdim          // The object immediately transitions to the released state.
3028226586Sdim          V = V ^ RefVal::Released;
3029226586Sdim          V.clearCounts();
3030239462Sdim          return setRefBinding(state, sym, V);
3031226586Sdim        case RefVal::NotOwned:
3032226586Sdim          V = V ^ RefVal::ErrorDeallocNotOwned;
3033226586Sdim          hasErr = V.getKind();
3034226586Sdim          break;
3035226586Sdim      }
3036226586Sdim      break;
3037226586Sdim
3038226586Sdim    case MayEscape:
3039226586Sdim      if (V.getKind() == RefVal::Owned) {
3040226586Sdim        V = V ^ RefVal::NotOwned;
3041226586Sdim        break;
3042226586Sdim      }
3043226586Sdim
3044226586Sdim      // Fall-through.
3045226586Sdim
3046226586Sdim    case DoNothing:
3047226586Sdim      return state;
3048226586Sdim
3049226586Sdim    case Autorelease:
3050226586Sdim      if (C.isObjCGCEnabled())
3051226586Sdim        return state;
3052226586Sdim      // Update the autorelease counts.
3053226586Sdim      V = V.autorelease();
3054226586Sdim      break;
3055226586Sdim
3056226586Sdim    case StopTracking:
3057243830Sdim    case StopTrackingHard:
3058239462Sdim      return removeRefBinding(state, sym);
3059226586Sdim
3060226586Sdim    case IncRef:
3061226586Sdim      switch (V.getKind()) {
3062226586Sdim        default:
3063226586Sdim          llvm_unreachable("Invalid RefVal state for a retain.");
3064226586Sdim        case RefVal::Owned:
3065226586Sdim        case RefVal::NotOwned:
3066226586Sdim          V = V + 1;
3067226586Sdim          break;
3068226586Sdim        case RefVal::Released:
3069226586Sdim          // Non-GC cases are handled above.
3070226586Sdim          assert(C.isObjCGCEnabled());
3071226586Sdim          V = (V ^ RefVal::Owned) + 1;
3072226586Sdim          break;
3073226586Sdim      }
3074226586Sdim      break;
3075226586Sdim
3076226586Sdim    case DecRef:
3077226586Sdim    case DecRefBridgedTransfered:
3078243830Sdim    case DecRefAndStopTrackingHard:
3079226586Sdim      switch (V.getKind()) {
3080226586Sdim        default:
3081226586Sdim          // case 'RefVal::Released' handled above.
3082226586Sdim          llvm_unreachable("Invalid RefVal state for a release.");
3083226586Sdim
3084226586Sdim        case RefVal::Owned:
3085226586Sdim          assert(V.getCount() > 0);
3086226586Sdim          if (V.getCount() == 1)
3087226586Sdim            V = V ^ (E == DecRefBridgedTransfered ?
3088226586Sdim                      RefVal::NotOwned : RefVal::Released);
3089243830Sdim          else if (E == DecRefAndStopTrackingHard)
3090239462Sdim            return removeRefBinding(state, sym);
3091239462Sdim
3092226586Sdim          V = V - 1;
3093226586Sdim          break;
3094226586Sdim
3095226586Sdim        case RefVal::NotOwned:
3096239462Sdim          if (V.getCount() > 0) {
3097243830Sdim            if (E == DecRefAndStopTrackingHard)
3098239462Sdim              return removeRefBinding(state, sym);
3099226586Sdim            V = V - 1;
3100239462Sdim          } else {
3101226586Sdim            V = V ^ RefVal::ErrorReleaseNotOwned;
3102226586Sdim            hasErr = V.getKind();
3103226586Sdim          }
3104226586Sdim          break;
3105226586Sdim
3106226586Sdim        case RefVal::Released:
3107226586Sdim          // Non-GC cases are handled above.
3108226586Sdim          assert(C.isObjCGCEnabled());
3109226586Sdim          V = V ^ RefVal::ErrorUseAfterRelease;
3110226586Sdim          hasErr = V.getKind();
3111226586Sdim          break;
3112226586Sdim      }
3113226586Sdim      break;
3114226586Sdim  }
3115239462Sdim  return setRefBinding(state, sym, V);
3116226586Sdim}
3117226586Sdim
3118234353Sdimvoid RetainCountChecker::processNonLeakError(ProgramStateRef St,
3119226586Sdim                                             SourceRange ErrorRange,
3120226586Sdim                                             RefVal::Kind ErrorKind,
3121226586Sdim                                             SymbolRef Sym,
3122226586Sdim                                             CheckerContext &C) const {
3123226586Sdim  ExplodedNode *N = C.generateSink(St);
3124226586Sdim  if (!N)
3125226586Sdim    return;
3126226586Sdim
3127226586Sdim  CFRefBug *BT;
3128226586Sdim  switch (ErrorKind) {
3129226586Sdim    default:
3130226586Sdim      llvm_unreachable("Unhandled error.");
3131226586Sdim    case RefVal::ErrorUseAfterRelease:
3132226586Sdim      if (!useAfterRelease)
3133226586Sdim        useAfterRelease.reset(new UseAfterRelease());
3134226586Sdim      BT = &*useAfterRelease;
3135226586Sdim      break;
3136226586Sdim    case RefVal::ErrorReleaseNotOwned:
3137226586Sdim      if (!releaseNotOwned)
3138226586Sdim        releaseNotOwned.reset(new BadRelease());
3139226586Sdim      BT = &*releaseNotOwned;
3140226586Sdim      break;
3141226586Sdim    case RefVal::ErrorDeallocGC:
3142226586Sdim      if (!deallocGC)
3143226586Sdim        deallocGC.reset(new DeallocGC());
3144226586Sdim      BT = &*deallocGC;
3145226586Sdim      break;
3146226586Sdim    case RefVal::ErrorDeallocNotOwned:
3147226586Sdim      if (!deallocNotOwned)
3148226586Sdim        deallocNotOwned.reset(new DeallocNotOwned());
3149226586Sdim      BT = &*deallocNotOwned;
3150226586Sdim      break;
3151226586Sdim  }
3152226586Sdim
3153226586Sdim  assert(BT);
3154234353Sdim  CFRefReport *report = new CFRefReport(*BT, C.getASTContext().getLangOpts(),
3155226586Sdim                                        C.isObjCGCEnabled(), SummaryLog,
3156226586Sdim                                        N, Sym);
3157226586Sdim  report->addRange(ErrorRange);
3158243830Sdim  C.emitReport(report);
3159226586Sdim}
3160226586Sdim
3161226586Sdim//===----------------------------------------------------------------------===//
3162226586Sdim// Handle the return values of retain-count-related functions.
3163226586Sdim//===----------------------------------------------------------------------===//
3164226586Sdim
3165226586Sdimbool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
3166226586Sdim  // Get the callee. We're only interested in simple C functions.
3167234353Sdim  ProgramStateRef state = C.getState();
3168234353Sdim  const FunctionDecl *FD = C.getCalleeDecl(CE);
3169226586Sdim  if (!FD)
3170226586Sdim    return false;
3171226586Sdim
3172226586Sdim  IdentifierInfo *II = FD->getIdentifier();
3173226586Sdim  if (!II)
3174226586Sdim    return false;
3175226586Sdim
3176226586Sdim  // For now, we're only handling the functions that return aliases of their
3177226586Sdim  // arguments: CFRetain and CFMakeCollectable (and their families).
3178226586Sdim  // Eventually we should add other functions we can model entirely,
3179226586Sdim  // such as CFRelease, which don't invalidate their arguments or globals.
3180226586Sdim  if (CE->getNumArgs() != 1)
3181226586Sdim    return false;
3182226586Sdim
3183226586Sdim  // Get the name of the function.
3184226586Sdim  StringRef FName = II->getName();
3185226586Sdim  FName = FName.substr(FName.find_first_not_of('_'));
3186226586Sdim
3187226586Sdim  // See if it's one of the specific functions we know how to eval.
3188226586Sdim  bool canEval = false;
3189226586Sdim
3190234353Sdim  QualType ResultTy = CE->getCallReturnType();
3191226586Sdim  if (ResultTy->isObjCIdType()) {
3192226586Sdim    // Handle: id NSMakeCollectable(CFTypeRef)
3193226586Sdim    canEval = II->isStr("NSMakeCollectable");
3194226586Sdim  } else if (ResultTy->isPointerType()) {
3195226586Sdim    // Handle: (CF|CG)Retain
3196226586Sdim    //         CFMakeCollectable
3197226586Sdim    // It's okay to be a little sloppy here (CGMakeCollectable doesn't exist).
3198226586Sdim    if (cocoa::isRefType(ResultTy, "CF", FName) ||
3199226586Sdim        cocoa::isRefType(ResultTy, "CG", FName)) {
3200226586Sdim      canEval = isRetain(FD, FName) || isMakeCollectable(FD, FName);
3201226586Sdim    }
3202226586Sdim  }
3203226586Sdim
3204226586Sdim  if (!canEval)
3205226586Sdim    return false;
3206226586Sdim
3207226586Sdim  // Bind the return value.
3208234353Sdim  const LocationContext *LCtx = C.getLocationContext();
3209234353Sdim  SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
3210226586Sdim  if (RetVal.isUnknown()) {
3211226586Sdim    // If the receiver is unknown, conjure a return value.
3212226586Sdim    SValBuilder &SVB = C.getSValBuilder();
3213243830Sdim    RetVal = SVB.conjureSymbolVal(0, CE, LCtx, ResultTy, C.blockCount());
3214226586Sdim  }
3215234353Sdim  state = state->BindExpr(CE, LCtx, RetVal, false);
3216226586Sdim
3217226586Sdim  // FIXME: This should not be necessary, but otherwise the argument seems to be
3218226586Sdim  // considered alive during the next statement.
3219226586Sdim  if (const MemRegion *ArgRegion = RetVal.getAsRegion()) {
3220226586Sdim    // Save the refcount status of the argument.
3221226586Sdim    SymbolRef Sym = RetVal.getAsLocSymbol();
3222239462Sdim    const RefVal *Binding = 0;
3223226586Sdim    if (Sym)
3224239462Sdim      Binding = getRefBinding(state, Sym);
3225226586Sdim
3226226586Sdim    // Invalidate the argument region.
3227249423Sdim    state = state->invalidateRegions(ArgRegion, CE, C.blockCount(), LCtx,
3228249423Sdim                                     /*CausesPointerEscape*/ false);
3229226586Sdim
3230226586Sdim    // Restore the refcount status of the argument.
3231226586Sdim    if (Binding)
3232239462Sdim      state = setRefBinding(state, Sym, *Binding);
3233226586Sdim  }
3234226586Sdim
3235226586Sdim  C.addTransition(state);
3236226586Sdim  return true;
3237226586Sdim}
3238226586Sdim
3239226586Sdim//===----------------------------------------------------------------------===//
3240226586Sdim// Handle return statements.
3241226586Sdim//===----------------------------------------------------------------------===//
3242226586Sdim
3243226586Sdimvoid RetainCountChecker::checkPreStmt(const ReturnStmt *S,
3244226586Sdim                                      CheckerContext &C) const {
3245234353Sdim
3246234353Sdim  // Only adjust the reference count if this is the top-level call frame,
3247234353Sdim  // and not the result of inlining.  In the future, we should do
3248234353Sdim  // better checking even for inlined calls, and see if they match
3249234353Sdim  // with their expected semantics (e.g., the method should return a retained
3250234353Sdim  // object, etc.).
3251243830Sdim  if (!C.inTopFrame())
3252234353Sdim    return;
3253234353Sdim
3254226586Sdim  const Expr *RetE = S->getRetValue();
3255226586Sdim  if (!RetE)
3256226586Sdim    return;
3257226586Sdim
3258234353Sdim  ProgramStateRef state = C.getState();
3259234353Sdim  SymbolRef Sym =
3260234353Sdim    state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
3261226586Sdim  if (!Sym)
3262226586Sdim    return;
3263226586Sdim
3264226586Sdim  // Get the reference count binding (if any).
3265239462Sdim  const RefVal *T = getRefBinding(state, Sym);
3266226586Sdim  if (!T)
3267226586Sdim    return;
3268226586Sdim
3269226586Sdim  // Change the reference count.
3270226586Sdim  RefVal X = *T;
3271226586Sdim
3272226586Sdim  switch (X.getKind()) {
3273226586Sdim    case RefVal::Owned: {
3274226586Sdim      unsigned cnt = X.getCount();
3275226586Sdim      assert(cnt > 0);
3276226586Sdim      X.setCount(cnt - 1);
3277226586Sdim      X = X ^ RefVal::ReturnedOwned;
3278226586Sdim      break;
3279226586Sdim    }
3280226586Sdim
3281226586Sdim    case RefVal::NotOwned: {
3282226586Sdim      unsigned cnt = X.getCount();
3283226586Sdim      if (cnt) {
3284226586Sdim        X.setCount(cnt - 1);
3285226586Sdim        X = X ^ RefVal::ReturnedOwned;
3286226586Sdim      }
3287226586Sdim      else {
3288226586Sdim        X = X ^ RefVal::ReturnedNotOwned;
3289226586Sdim      }
3290226586Sdim      break;
3291226586Sdim    }
3292226586Sdim
3293226586Sdim    default:
3294226586Sdim      return;
3295226586Sdim  }
3296226586Sdim
3297226586Sdim  // Update the binding.
3298239462Sdim  state = setRefBinding(state, Sym, X);
3299234353Sdim  ExplodedNode *Pred = C.addTransition(state);
3300226586Sdim
3301226586Sdim  // At this point we have updated the state properly.
3302226586Sdim  // Everything after this is merely checking to see if the return value has
3303226586Sdim  // been over- or under-retained.
3304226586Sdim
3305226586Sdim  // Did we cache out?
3306226586Sdim  if (!Pred)
3307226586Sdim    return;
3308226586Sdim
3309226586Sdim  // Update the autorelease counts.
3310226586Sdim  static SimpleProgramPointTag
3311226586Sdim         AutoreleaseTag("RetainCountChecker : Autorelease");
3312249423Sdim  state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3313226586Sdim
3314226586Sdim  // Did we cache out?
3315249423Sdim  if (!state)
3316226586Sdim    return;
3317226586Sdim
3318226586Sdim  // Get the updated binding.
3319239462Sdim  T = getRefBinding(state, Sym);
3320226586Sdim  assert(T);
3321226586Sdim  X = *T;
3322226586Sdim
3323226586Sdim  // Consult the summary of the enclosing method.
3324226586Sdim  RetainSummaryManager &Summaries = getSummaryManager(C);
3325226586Sdim  const Decl *CD = &Pred->getCodeDecl();
3326239462Sdim  RetEffect RE = RetEffect::MakeNoRet();
3327226586Sdim
3328239462Sdim  // FIXME: What is the convention for blocks? Is there one?
3329226586Sdim  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
3330226586Sdim    const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3331239462Sdim    RE = Summ->getRetEffect();
3332239462Sdim  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3333239462Sdim    if (!isa<CXXMethodDecl>(FD)) {
3334239462Sdim      const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3335239462Sdim      RE = Summ->getRetEffect();
3336239462Sdim    }
3337226586Sdim  }
3338226586Sdim
3339239462Sdim  checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3340226586Sdim}
3341226586Sdim
3342226586Sdimvoid RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
3343226586Sdim                                                  CheckerContext &C,
3344226586Sdim                                                  ExplodedNode *Pred,
3345226586Sdim                                                  RetEffect RE, RefVal X,
3346226586Sdim                                                  SymbolRef Sym,
3347234353Sdim                                              ProgramStateRef state) const {
3348226586Sdim  // Any leaks or other errors?
3349226586Sdim  if (X.isReturnedOwned() && X.getCount() == 0) {
3350226586Sdim    if (RE.getKind() != RetEffect::NoRet) {
3351226586Sdim      bool hasError = false;
3352226586Sdim      if (C.isObjCGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
3353226586Sdim        // Things are more complicated with garbage collection.  If the
3354226586Sdim        // returned object is suppose to be an Objective-C object, we have
3355226586Sdim        // a leak (as the caller expects a GC'ed object) because no
3356226586Sdim        // method should return ownership unless it returns a CF object.
3357226586Sdim        hasError = true;
3358226586Sdim        X = X ^ RefVal::ErrorGCLeakReturned;
3359226586Sdim      }
3360226586Sdim      else if (!RE.isOwned()) {
3361226586Sdim        // Either we are using GC and the returned object is a CF type
3362226586Sdim        // or we aren't using GC.  In either case, we expect that the
3363226586Sdim        // enclosing method is expected to return ownership.
3364226586Sdim        hasError = true;
3365226586Sdim        X = X ^ RefVal::ErrorLeakReturned;
3366226586Sdim      }
3367226586Sdim
3368226586Sdim      if (hasError) {
3369226586Sdim        // Generate an error node.
3370239462Sdim        state = setRefBinding(state, Sym, X);
3371226586Sdim
3372226586Sdim        static SimpleProgramPointTag
3373226586Sdim               ReturnOwnLeakTag("RetainCountChecker : ReturnsOwnLeak");
3374234353Sdim        ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
3375226586Sdim        if (N) {
3376234353Sdim          const LangOptions &LOpts = C.getASTContext().getLangOpts();
3377226586Sdim          bool GCEnabled = C.isObjCGCEnabled();
3378226586Sdim          CFRefReport *report =
3379226586Sdim            new CFRefLeakReport(*getLeakAtReturnBug(LOpts, GCEnabled),
3380226586Sdim                                LOpts, GCEnabled, SummaryLog,
3381251662Sdim                                N, Sym, C, IncludeAllocationLine);
3382251662Sdim
3383243830Sdim          C.emitReport(report);
3384226586Sdim        }
3385226586Sdim      }
3386226586Sdim    }
3387226586Sdim  } else if (X.isReturnedNotOwned()) {
3388226586Sdim    if (RE.isOwned()) {
3389226586Sdim      // Trying to return a not owned object to a caller expecting an
3390226586Sdim      // owned object.
3391239462Sdim      state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3392226586Sdim
3393226586Sdim      static SimpleProgramPointTag
3394226586Sdim             ReturnNotOwnedTag("RetainCountChecker : ReturnNotOwnedForOwned");
3395234353Sdim      ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
3396226586Sdim      if (N) {
3397226586Sdim        if (!returnNotOwnedForOwned)
3398226586Sdim          returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned());
3399226586Sdim
3400226586Sdim        CFRefReport *report =
3401226586Sdim            new CFRefReport(*returnNotOwnedForOwned,
3402234353Sdim                            C.getASTContext().getLangOpts(),
3403226586Sdim                            C.isObjCGCEnabled(), SummaryLog, N, Sym);
3404243830Sdim        C.emitReport(report);
3405226586Sdim      }
3406226586Sdim    }
3407226586Sdim  }
3408226586Sdim}
3409226586Sdim
3410226586Sdim//===----------------------------------------------------------------------===//
3411226586Sdim// Check various ways a symbol can be invalidated.
3412226586Sdim//===----------------------------------------------------------------------===//
3413226586Sdim
3414226586Sdimvoid RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
3415226586Sdim                                   CheckerContext &C) const {
3416226586Sdim  // Are we storing to something that causes the value to "escape"?
3417226586Sdim  bool escapes = true;
3418226586Sdim
3419226586Sdim  // A value escapes in three possible cases (this may change):
3420226586Sdim  //
3421226586Sdim  // (1) we are binding to something that is not a memory region.
3422226586Sdim  // (2) we are binding to a memregion that does not have stack storage
3423226586Sdim  // (3) we are binding to a memregion with stack storage that the store
3424226586Sdim  //     does not understand.
3425234353Sdim  ProgramStateRef state = C.getState();
3426226586Sdim
3427249423Sdim  if (Optional<loc::MemRegionVal> regionLoc = loc.getAs<loc::MemRegionVal>()) {
3428226586Sdim    escapes = !regionLoc->getRegion()->hasStackStorage();
3429226586Sdim
3430226586Sdim    if (!escapes) {
3431226586Sdim      // To test (3), generate a new state with the binding added.  If it is
3432226586Sdim      // the same state, then it escapes (since the store cannot represent
3433226586Sdim      // the binding).
3434239462Sdim      // Do this only if we know that the store is not supposed to generate the
3435239462Sdim      // same state.
3436239462Sdim      SVal StoredVal = state->getSVal(regionLoc->getRegion());
3437239462Sdim      if (StoredVal != val)
3438239462Sdim        escapes = (state == (state->bindLoc(*regionLoc, val)));
3439226586Sdim    }
3440234353Sdim    if (!escapes) {
3441234353Sdim      // Case 4: We do not currently model what happens when a symbol is
3442234353Sdim      // assigned to a struct field, so be conservative here and let the symbol
3443234353Sdim      // go. TODO: This could definitely be improved upon.
3444234353Sdim      escapes = !isa<VarRegion>(regionLoc->getRegion());
3445234353Sdim    }
3446226586Sdim  }
3447226586Sdim
3448226586Sdim  // If our store can represent the binding and we aren't storing to something
3449226586Sdim  // that doesn't have local storage then just return and have the simulation
3450226586Sdim  // state continue as is.
3451226586Sdim  if (!escapes)
3452226586Sdim      return;
3453226586Sdim
3454226586Sdim  // Otherwise, find all symbols referenced by 'val' that we are tracking
3455226586Sdim  // and stop tracking them.
3456226586Sdim  state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3457226586Sdim  C.addTransition(state);
3458226586Sdim}
3459226586Sdim
3460234353SdimProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
3461226586Sdim                                                   SVal Cond,
3462226586Sdim                                                   bool Assumption) const {
3463226586Sdim
3464226586Sdim  // FIXME: We may add to the interface of evalAssume the list of symbols
3465226586Sdim  //  whose assumptions have changed.  For now we just iterate through the
3466226586Sdim  //  bindings and check if any of the tracked symbols are NULL.  This isn't
3467226586Sdim  //  too bad since the number of symbols we will track in practice are
3468226586Sdim  //  probably small and evalAssume is only called at branches and a few
3469226586Sdim  //  other places.
3470243830Sdim  RefBindingsTy B = state->get<RefBindings>();
3471226586Sdim
3472226586Sdim  if (B.isEmpty())
3473226586Sdim    return state;
3474226586Sdim
3475226586Sdim  bool changed = false;
3476243830Sdim  RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
3477226586Sdim
3478243830Sdim  for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3479243830Sdim    // Check if the symbol is null stop tracking the symbol.
3480243830Sdim    ConstraintManager &CMgr = state->getConstraintManager();
3481243830Sdim    ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
3482243830Sdim    if (AllocFailed.isConstrainedTrue()) {
3483226586Sdim      changed = true;
3484226586Sdim      B = RefBFactory.remove(B, I.getKey());
3485226586Sdim    }
3486226586Sdim  }
3487226586Sdim
3488226586Sdim  if (changed)
3489226586Sdim    state = state->set<RefBindings>(B);
3490226586Sdim
3491226586Sdim  return state;
3492226586Sdim}
3493226586Sdim
3494234353SdimProgramStateRef
3495234353SdimRetainCountChecker::checkRegionChanges(ProgramStateRef state,
3496249423Sdim                                    const InvalidatedSymbols *invalidated,
3497226586Sdim                                    ArrayRef<const MemRegion *> ExplicitRegions,
3498234353Sdim                                    ArrayRef<const MemRegion *> Regions,
3499239462Sdim                                    const CallEvent *Call) const {
3500226586Sdim  if (!invalidated)
3501226586Sdim    return state;
3502226586Sdim
3503226586Sdim  llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
3504226586Sdim  for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
3505226586Sdim       E = ExplicitRegions.end(); I != E; ++I) {
3506226586Sdim    if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
3507226586Sdim      WhitelistedSymbols.insert(SR->getSymbol());
3508226586Sdim  }
3509226586Sdim
3510249423Sdim  for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
3511226586Sdim       E = invalidated->end(); I!=E; ++I) {
3512226586Sdim    SymbolRef sym = *I;
3513226586Sdim    if (WhitelistedSymbols.count(sym))
3514226586Sdim      continue;
3515226586Sdim    // Remove any existing reference-count binding.
3516239462Sdim    state = removeRefBinding(state, sym);
3517226586Sdim  }
3518226586Sdim  return state;
3519226586Sdim}
3520226586Sdim
3521226586Sdim//===----------------------------------------------------------------------===//
3522226586Sdim// Handle dead symbols and end-of-path.
3523226586Sdim//===----------------------------------------------------------------------===//
3524226586Sdim
3525249423SdimProgramStateRef
3526249423SdimRetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
3527234353Sdim                                            ExplodedNode *Pred,
3528243830Sdim                                            const ProgramPointTag *Tag,
3529234353Sdim                                            CheckerContext &Ctx,
3530226586Sdim                                            SymbolRef Sym, RefVal V) const {
3531226586Sdim  unsigned ACnt = V.getAutoreleaseCount();
3532226586Sdim
3533226586Sdim  // No autorelease counts?  Nothing to be done.
3534226586Sdim  if (!ACnt)
3535249423Sdim    return state;
3536226586Sdim
3537234353Sdim  assert(!Ctx.isObjCGCEnabled() && "Autorelease counts in GC mode?");
3538226586Sdim  unsigned Cnt = V.getCount();
3539226586Sdim
3540226586Sdim  // FIXME: Handle sending 'autorelease' to already released object.
3541226586Sdim
3542226586Sdim  if (V.getKind() == RefVal::ReturnedOwned)
3543226586Sdim    ++Cnt;
3544226586Sdim
3545226586Sdim  if (ACnt <= Cnt) {
3546226586Sdim    if (ACnt == Cnt) {
3547226586Sdim      V.clearCounts();
3548226586Sdim      if (V.getKind() == RefVal::ReturnedOwned)
3549226586Sdim        V = V ^ RefVal::ReturnedNotOwned;
3550226586Sdim      else
3551226586Sdim        V = V ^ RefVal::NotOwned;
3552226586Sdim    } else {
3553249423Sdim      V.setCount(V.getCount() - ACnt);
3554226586Sdim      V.setAutoreleaseCount(0);
3555226586Sdim    }
3556249423Sdim    return setRefBinding(state, Sym, V);
3557226586Sdim  }
3558226586Sdim
3559226586Sdim  // Woah!  More autorelease counts then retain counts left.
3560226586Sdim  // Emit hard error.
3561226586Sdim  V = V ^ RefVal::ErrorOverAutorelease;
3562239462Sdim  state = setRefBinding(state, Sym, V);
3563226586Sdim
3564243830Sdim  ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
3565243830Sdim  if (N) {
3566234353Sdim    SmallString<128> sbuf;
3567226586Sdim    llvm::raw_svector_ostream os(sbuf);
3568251662Sdim    os << "Object was autoreleased ";
3569226586Sdim    if (V.getAutoreleaseCount() > 1)
3570251662Sdim      os << V.getAutoreleaseCount() << " times but the object ";
3571251662Sdim    else
3572251662Sdim      os << "but ";
3573251662Sdim    os << "has a +" << V.getCount() << " retain count";
3574226586Sdim
3575226586Sdim    if (!overAutorelease)
3576226586Sdim      overAutorelease.reset(new OverAutorelease());
3577226586Sdim
3578234353Sdim    const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
3579226586Sdim    CFRefReport *report =
3580226586Sdim      new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
3581226586Sdim                      SummaryLog, N, Sym, os.str());
3582243830Sdim    Ctx.emitReport(report);
3583226586Sdim  }
3584226586Sdim
3585249423Sdim  return 0;
3586226586Sdim}
3587226586Sdim
3588234353SdimProgramStateRef
3589234353SdimRetainCountChecker::handleSymbolDeath(ProgramStateRef state,
3590226586Sdim                                      SymbolRef sid, RefVal V,
3591226586Sdim                                    SmallVectorImpl<SymbolRef> &Leaked) const {
3592226586Sdim  bool hasLeak = false;
3593226586Sdim  if (V.isOwned())
3594226586Sdim    hasLeak = true;
3595226586Sdim  else if (V.isNotOwned() || V.isReturnedOwned())
3596226586Sdim    hasLeak = (V.getCount() > 0);
3597226586Sdim
3598226586Sdim  if (!hasLeak)
3599239462Sdim    return removeRefBinding(state, sid);
3600226586Sdim
3601226586Sdim  Leaked.push_back(sid);
3602239462Sdim  return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
3603226586Sdim}
3604226586Sdim
3605226586SdimExplodedNode *
3606234353SdimRetainCountChecker::processLeaks(ProgramStateRef state,
3607226586Sdim                                 SmallVectorImpl<SymbolRef> &Leaked,
3608234353Sdim                                 CheckerContext &Ctx,
3609234353Sdim                                 ExplodedNode *Pred) const {
3610226586Sdim  // Generate an intermediate node representing the leak point.
3611243830Sdim  ExplodedNode *N = Ctx.addTransition(state, Pred);
3612226586Sdim
3613226586Sdim  if (N) {
3614226586Sdim    for (SmallVectorImpl<SymbolRef>::iterator
3615226586Sdim         I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
3616226586Sdim
3617234353Sdim      const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
3618234353Sdim      bool GCEnabled = Ctx.isObjCGCEnabled();
3619226586Sdim      CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
3620226586Sdim                          : getLeakAtReturnBug(LOpts, GCEnabled);
3621226586Sdim      assert(BT && "BugType not initialized.");
3622226586Sdim
3623226586Sdim      CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, GCEnabled,
3624251662Sdim                                                    SummaryLog, N, *I, Ctx,
3625251662Sdim                                                    IncludeAllocationLine);
3626243830Sdim      Ctx.emitReport(report);
3627226586Sdim    }
3628226586Sdim  }
3629226586Sdim
3630226586Sdim  return N;
3631226586Sdim}
3632226586Sdim
3633249423Sdimvoid RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
3634234353Sdim  ProgramStateRef state = Ctx.getState();
3635243830Sdim  RefBindingsTy B = state->get<RefBindings>();
3636234353Sdim  ExplodedNode *Pred = Ctx.getPredecessor();
3637226586Sdim
3638243830Sdim  for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3639249423Sdim    state = handleAutoreleaseCounts(state, Pred, /*Tag=*/0, Ctx,
3640249423Sdim                                    I->first, I->second);
3641226586Sdim    if (!state)
3642226586Sdim      return;
3643226586Sdim  }
3644226586Sdim
3645234353Sdim  // If the current LocationContext has a parent, don't check for leaks.
3646234353Sdim  // We will do that later.
3647239462Sdim  // FIXME: we should instead check for imbalances of the retain/releases,
3648234353Sdim  // and suggest annotations.
3649234353Sdim  if (Ctx.getLocationContext()->getParent())
3650234353Sdim    return;
3651234353Sdim
3652226586Sdim  B = state->get<RefBindings>();
3653226586Sdim  SmallVector<SymbolRef, 10> Leaked;
3654226586Sdim
3655243830Sdim  for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
3656226586Sdim    state = handleSymbolDeath(state, I->first, I->second, Leaked);
3657226586Sdim
3658243830Sdim  processLeaks(state, Leaked, Ctx, Pred);
3659226586Sdim}
3660226586Sdim
3661226586Sdimconst ProgramPointTag *
3662226586SdimRetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
3663226586Sdim  const SimpleProgramPointTag *&tag = DeadSymbolTags[sym];
3664226586Sdim  if (!tag) {
3665234353Sdim    SmallString<64> buf;
3666226586Sdim    llvm::raw_svector_ostream out(buf);
3667234353Sdim    out << "RetainCountChecker : Dead Symbol : ";
3668234353Sdim    sym->dumpToStream(out);
3669226586Sdim    tag = new SimpleProgramPointTag(out.str());
3670226586Sdim  }
3671226586Sdim  return tag;
3672226586Sdim}
3673226586Sdim
3674226586Sdimvoid RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
3675226586Sdim                                          CheckerContext &C) const {
3676226586Sdim  ExplodedNode *Pred = C.getPredecessor();
3677226586Sdim
3678234353Sdim  ProgramStateRef state = C.getState();
3679243830Sdim  RefBindingsTy B = state->get<RefBindings>();
3680249423Sdim  SmallVector<SymbolRef, 10> Leaked;
3681226586Sdim
3682226586Sdim  // Update counts from autorelease pools
3683226586Sdim  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3684226586Sdim       E = SymReaper.dead_end(); I != E; ++I) {
3685226586Sdim    SymbolRef Sym = *I;
3686226586Sdim    if (const RefVal *T = B.lookup(Sym)){
3687226586Sdim      // Use the symbol as the tag.
3688226586Sdim      // FIXME: This might not be as unique as we would like.
3689243830Sdim      const ProgramPointTag *Tag = getDeadSymbolTag(Sym);
3690249423Sdim      state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
3691226586Sdim      if (!state)
3692226586Sdim        return;
3693249423Sdim
3694249423Sdim      // Fetch the new reference count from the state, and use it to handle
3695249423Sdim      // this symbol.
3696249423Sdim      state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked);
3697226586Sdim    }
3698226586Sdim  }
3699226586Sdim
3700249423Sdim  if (Leaked.empty()) {
3701249423Sdim    C.addTransition(state);
3702249423Sdim    return;
3703226586Sdim  }
3704226586Sdim
3705243830Sdim  Pred = processLeaks(state, Leaked, C, Pred);
3706226586Sdim
3707226586Sdim  // Did we cache out?
3708226586Sdim  if (!Pred)
3709226586Sdim    return;
3710226586Sdim
3711226586Sdim  // Now generate a new node that nukes the old bindings.
3712249423Sdim  // The only bindings left at this point are the leaked symbols.
3713243830Sdim  RefBindingsTy::Factory &F = state->get_context<RefBindings>();
3714249423Sdim  B = state->get<RefBindings>();
3715226586Sdim
3716249423Sdim  for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
3717249423Sdim                                            E = Leaked.end();
3718249423Sdim       I != E; ++I)
3719226586Sdim    B = F.remove(B, *I);
3720226586Sdim
3721226586Sdim  state = state->set<RefBindings>(B);
3722234353Sdim  C.addTransition(state, Pred);
3723226586Sdim}
3724226586Sdim
3725234353Sdimvoid RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
3726226586Sdim                                    const char *NL, const char *Sep) const {
3727226586Sdim
3728243830Sdim  RefBindingsTy B = State->get<RefBindings>();
3729226586Sdim
3730249423Sdim  if (B.isEmpty())
3731249423Sdim    return;
3732226586Sdim
3733249423Sdim  Out << Sep << NL;
3734249423Sdim
3735243830Sdim  for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3736226586Sdim    Out << I->first << " : ";
3737226586Sdim    I->second.print(Out);
3738226586Sdim    Out << NL;
3739226586Sdim  }
3740226586Sdim}
3741226586Sdim
3742226586Sdim//===----------------------------------------------------------------------===//
3743226586Sdim// Checker registration.
3744226586Sdim//===----------------------------------------------------------------------===//
3745226586Sdim
3746226586Sdimvoid ento::registerRetainCountChecker(CheckerManager &Mgr) {
3747251662Sdim  Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions());
3748226586Sdim}
3749226586Sdim
3750