xref: /aosp_15_r20/external/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  This file defines the methods for RetainCountChecker, which implements
11*67e74705SXin Li //  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li 
15*67e74705SXin Li #include "AllocationDiagnostics.h"
16*67e74705SXin Li #include "ClangSACheckers.h"
17*67e74705SXin Li #include "SelectorExtras.h"
18*67e74705SXin Li #include "clang/AST/Attr.h"
19*67e74705SXin Li #include "clang/AST/DeclCXX.h"
20*67e74705SXin Li #include "clang/AST/DeclObjC.h"
21*67e74705SXin Li #include "clang/AST/ParentMap.h"
22*67e74705SXin Li #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
23*67e74705SXin Li #include "clang/Basic/LangOptions.h"
24*67e74705SXin Li #include "clang/Basic/SourceManager.h"
25*67e74705SXin Li #include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
26*67e74705SXin Li #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
27*67e74705SXin Li #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
28*67e74705SXin Li #include "clang/StaticAnalyzer/Core/Checker.h"
29*67e74705SXin Li #include "clang/StaticAnalyzer/Core/CheckerManager.h"
30*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
31*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
32*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
33*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
34*67e74705SXin Li #include "llvm/ADT/DenseMap.h"
35*67e74705SXin Li #include "llvm/ADT/FoldingSet.h"
36*67e74705SXin Li #include "llvm/ADT/ImmutableList.h"
37*67e74705SXin Li #include "llvm/ADT/ImmutableMap.h"
38*67e74705SXin Li #include "llvm/ADT/STLExtras.h"
39*67e74705SXin Li #include "llvm/ADT/SmallString.h"
40*67e74705SXin Li #include "llvm/ADT/StringExtras.h"
41*67e74705SXin Li #include <cstdarg>
42*67e74705SXin Li #include <utility>
43*67e74705SXin Li 
44*67e74705SXin Li using namespace clang;
45*67e74705SXin Li using namespace ento;
46*67e74705SXin Li using namespace objc_retain;
47*67e74705SXin Li using llvm::StrInStrNoCase;
48*67e74705SXin Li 
49*67e74705SXin Li //===----------------------------------------------------------------------===//
50*67e74705SXin Li // Adapters for FoldingSet.
51*67e74705SXin Li //===----------------------------------------------------------------------===//
52*67e74705SXin Li 
53*67e74705SXin Li namespace llvm {
54*67e74705SXin Li template <> struct FoldingSetTrait<ArgEffect> {
Profilellvm::FoldingSetTrait55*67e74705SXin Li static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
56*67e74705SXin Li   ID.AddInteger((unsigned) X);
57*67e74705SXin Li }
58*67e74705SXin Li };
59*67e74705SXin Li template <> struct FoldingSetTrait<RetEffect> {
Profilellvm::FoldingSetTrait60*67e74705SXin Li   static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
61*67e74705SXin Li     ID.AddInteger((unsigned) X.getKind());
62*67e74705SXin Li     ID.AddInteger((unsigned) X.getObjKind());
63*67e74705SXin Li }
64*67e74705SXin Li };
65*67e74705SXin Li } // end llvm namespace
66*67e74705SXin Li 
67*67e74705SXin Li //===----------------------------------------------------------------------===//
68*67e74705SXin Li // Reference-counting logic (typestate + counts).
69*67e74705SXin Li //===----------------------------------------------------------------------===//
70*67e74705SXin Li 
71*67e74705SXin Li /// ArgEffects summarizes the effects of a function/method call on all of
72*67e74705SXin Li /// its arguments.
73*67e74705SXin Li typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
74*67e74705SXin Li 
75*67e74705SXin Li namespace {
76*67e74705SXin Li class RefVal {
77*67e74705SXin Li public:
78*67e74705SXin Li   enum Kind {
79*67e74705SXin Li     Owned = 0, // Owning reference.
80*67e74705SXin Li     NotOwned,  // Reference is not owned by still valid (not freed).
81*67e74705SXin Li     Released,  // Object has been released.
82*67e74705SXin Li     ReturnedOwned, // Returned object passes ownership to caller.
83*67e74705SXin Li     ReturnedNotOwned, // Return object does not pass ownership to caller.
84*67e74705SXin Li     ERROR_START,
85*67e74705SXin Li     ErrorDeallocNotOwned, // -dealloc called on non-owned object.
86*67e74705SXin Li     ErrorDeallocGC, // Calling -dealloc with GC enabled.
87*67e74705SXin Li     ErrorUseAfterRelease, // Object used after released.
88*67e74705SXin Li     ErrorReleaseNotOwned, // Release of an object that was not owned.
89*67e74705SXin Li     ERROR_LEAK_START,
90*67e74705SXin Li     ErrorLeak,  // A memory leak due to excessive reference counts.
91*67e74705SXin Li     ErrorLeakReturned, // A memory leak due to the returning method not having
92*67e74705SXin Li                        // the correct naming conventions.
93*67e74705SXin Li     ErrorGCLeakReturned,
94*67e74705SXin Li     ErrorOverAutorelease,
95*67e74705SXin Li     ErrorReturnedNotOwned
96*67e74705SXin Li   };
97*67e74705SXin Li 
98*67e74705SXin Li   /// Tracks how an object referenced by an ivar has been used.
99*67e74705SXin Li   ///
100*67e74705SXin Li   /// This accounts for us not knowing if an arbitrary ivar is supposed to be
101*67e74705SXin Li   /// stored at +0 or +1.
102*67e74705SXin Li   enum class IvarAccessHistory {
103*67e74705SXin Li     None,
104*67e74705SXin Li     AccessedDirectly,
105*67e74705SXin Li     ReleasedAfterDirectAccess
106*67e74705SXin Li   };
107*67e74705SXin Li 
108*67e74705SXin Li private:
109*67e74705SXin Li   /// The number of outstanding retains.
110*67e74705SXin Li   unsigned Cnt;
111*67e74705SXin Li   /// The number of outstanding autoreleases.
112*67e74705SXin Li   unsigned ACnt;
113*67e74705SXin Li   /// The (static) type of the object at the time we started tracking it.
114*67e74705SXin Li   QualType T;
115*67e74705SXin Li 
116*67e74705SXin Li   /// The current state of the object.
117*67e74705SXin Li   ///
118*67e74705SXin Li   /// See the RefVal::Kind enum for possible values.
119*67e74705SXin Li   unsigned RawKind : 5;
120*67e74705SXin Li 
121*67e74705SXin Li   /// The kind of object being tracked (CF or ObjC), if known.
122*67e74705SXin Li   ///
123*67e74705SXin Li   /// See the RetEffect::ObjKind enum for possible values.
124*67e74705SXin Li   unsigned RawObjectKind : 2;
125*67e74705SXin Li 
126*67e74705SXin Li   /// True if the current state and/or retain count may turn out to not be the
127*67e74705SXin Li   /// best possible approximation of the reference counting state.
128*67e74705SXin Li   ///
129*67e74705SXin Li   /// If true, the checker may decide to throw away ("override") this state
130*67e74705SXin Li   /// in favor of something else when it sees the object being used in new ways.
131*67e74705SXin Li   ///
132*67e74705SXin Li   /// This setting should not be propagated to state derived from this state.
133*67e74705SXin Li   /// Once we start deriving new states, it would be inconsistent to override
134*67e74705SXin Li   /// them.
135*67e74705SXin Li   unsigned RawIvarAccessHistory : 2;
136*67e74705SXin Li 
RefVal(Kind k,RetEffect::ObjKind o,unsigned cnt,unsigned acnt,QualType t,IvarAccessHistory IvarAccess)137*67e74705SXin Li   RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t,
138*67e74705SXin Li          IvarAccessHistory IvarAccess)
139*67e74705SXin Li     : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
140*67e74705SXin Li       RawObjectKind(static_cast<unsigned>(o)),
141*67e74705SXin Li       RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
142*67e74705SXin Li     assert(getKind() == k && "not enough bits for the kind");
143*67e74705SXin Li     assert(getObjKind() == o && "not enough bits for the object kind");
144*67e74705SXin Li     assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
145*67e74705SXin Li   }
146*67e74705SXin Li 
147*67e74705SXin Li public:
getKind() const148*67e74705SXin Li   Kind getKind() const { return static_cast<Kind>(RawKind); }
149*67e74705SXin Li 
getObjKind() const150*67e74705SXin Li   RetEffect::ObjKind getObjKind() const {
151*67e74705SXin Li     return static_cast<RetEffect::ObjKind>(RawObjectKind);
152*67e74705SXin Li   }
153*67e74705SXin Li 
getCount() const154*67e74705SXin Li   unsigned getCount() const { return Cnt; }
getAutoreleaseCount() const155*67e74705SXin Li   unsigned getAutoreleaseCount() const { return ACnt; }
getCombinedCounts() const156*67e74705SXin Li   unsigned getCombinedCounts() const { return Cnt + ACnt; }
clearCounts()157*67e74705SXin Li   void clearCounts() {
158*67e74705SXin Li     Cnt = 0;
159*67e74705SXin Li     ACnt = 0;
160*67e74705SXin Li   }
setCount(unsigned i)161*67e74705SXin Li   void setCount(unsigned i) {
162*67e74705SXin Li     Cnt = i;
163*67e74705SXin Li   }
setAutoreleaseCount(unsigned i)164*67e74705SXin Li   void setAutoreleaseCount(unsigned i) {
165*67e74705SXin Li     ACnt = i;
166*67e74705SXin Li   }
167*67e74705SXin Li 
getType() const168*67e74705SXin Li   QualType getType() const { return T; }
169*67e74705SXin Li 
170*67e74705SXin Li   /// Returns what the analyzer knows about direct accesses to a particular
171*67e74705SXin Li   /// instance variable.
172*67e74705SXin Li   ///
173*67e74705SXin Li   /// If the object with this refcount wasn't originally from an Objective-C
174*67e74705SXin Li   /// ivar region, this should always return IvarAccessHistory::None.
getIvarAccessHistory() const175*67e74705SXin Li   IvarAccessHistory getIvarAccessHistory() const {
176*67e74705SXin Li     return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
177*67e74705SXin Li   }
178*67e74705SXin Li 
isOwned() const179*67e74705SXin Li   bool isOwned() const {
180*67e74705SXin Li     return getKind() == Owned;
181*67e74705SXin Li   }
182*67e74705SXin Li 
isNotOwned() const183*67e74705SXin Li   bool isNotOwned() const {
184*67e74705SXin Li     return getKind() == NotOwned;
185*67e74705SXin Li   }
186*67e74705SXin Li 
isReturnedOwned() const187*67e74705SXin Li   bool isReturnedOwned() const {
188*67e74705SXin Li     return getKind() == ReturnedOwned;
189*67e74705SXin Li   }
190*67e74705SXin Li 
isReturnedNotOwned() const191*67e74705SXin Li   bool isReturnedNotOwned() const {
192*67e74705SXin Li     return getKind() == ReturnedNotOwned;
193*67e74705SXin Li   }
194*67e74705SXin Li 
195*67e74705SXin Li   /// Create a state for an object whose lifetime is the responsibility of the
196*67e74705SXin Li   /// current function, at least partially.
197*67e74705SXin Li   ///
198*67e74705SXin Li   /// Most commonly, this is an owned object with a retain count of +1.
makeOwned(RetEffect::ObjKind o,QualType t,unsigned Count=1)199*67e74705SXin Li   static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
200*67e74705SXin Li                           unsigned Count = 1) {
201*67e74705SXin Li     return RefVal(Owned, o, Count, 0, t, IvarAccessHistory::None);
202*67e74705SXin Li   }
203*67e74705SXin Li 
204*67e74705SXin Li   /// Create a state for an object whose lifetime is not the responsibility of
205*67e74705SXin Li   /// the current function.
206*67e74705SXin Li   ///
207*67e74705SXin Li   /// Most commonly, this is an unowned object with a retain count of +0.
makeNotOwned(RetEffect::ObjKind o,QualType t,unsigned Count=0)208*67e74705SXin Li   static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
209*67e74705SXin Li                              unsigned Count = 0) {
210*67e74705SXin Li     return RefVal(NotOwned, o, Count, 0, t, IvarAccessHistory::None);
211*67e74705SXin Li   }
212*67e74705SXin Li 
operator -(size_t i) const213*67e74705SXin Li   RefVal operator-(size_t i) const {
214*67e74705SXin Li     return RefVal(getKind(), getObjKind(), getCount() - i,
215*67e74705SXin Li                   getAutoreleaseCount(), getType(), getIvarAccessHistory());
216*67e74705SXin Li   }
217*67e74705SXin Li 
operator +(size_t i) const218*67e74705SXin Li   RefVal operator+(size_t i) const {
219*67e74705SXin Li     return RefVal(getKind(), getObjKind(), getCount() + i,
220*67e74705SXin Li                   getAutoreleaseCount(), getType(), getIvarAccessHistory());
221*67e74705SXin Li   }
222*67e74705SXin Li 
operator ^(Kind k) const223*67e74705SXin Li   RefVal operator^(Kind k) const {
224*67e74705SXin Li     return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
225*67e74705SXin Li                   getType(), getIvarAccessHistory());
226*67e74705SXin Li   }
227*67e74705SXin Li 
autorelease() const228*67e74705SXin Li   RefVal autorelease() const {
229*67e74705SXin Li     return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
230*67e74705SXin Li                   getType(), getIvarAccessHistory());
231*67e74705SXin Li   }
232*67e74705SXin Li 
withIvarAccess() const233*67e74705SXin Li   RefVal withIvarAccess() const {
234*67e74705SXin Li     assert(getIvarAccessHistory() == IvarAccessHistory::None);
235*67e74705SXin Li     return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
236*67e74705SXin Li                   getType(), IvarAccessHistory::AccessedDirectly);
237*67e74705SXin Li   }
238*67e74705SXin Li 
releaseViaIvar() const239*67e74705SXin Li   RefVal releaseViaIvar() const {
240*67e74705SXin Li     assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
241*67e74705SXin Li     return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
242*67e74705SXin Li                   getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
243*67e74705SXin Li   }
244*67e74705SXin Li 
245*67e74705SXin Li   // Comparison, profiling, and pretty-printing.
246*67e74705SXin Li 
hasSameState(const RefVal & X) const247*67e74705SXin Li   bool hasSameState(const RefVal &X) const {
248*67e74705SXin Li     return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
249*67e74705SXin Li            getIvarAccessHistory() == X.getIvarAccessHistory();
250*67e74705SXin Li   }
251*67e74705SXin Li 
operator ==(const RefVal & X) const252*67e74705SXin Li   bool operator==(const RefVal& X) const {
253*67e74705SXin Li     return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
254*67e74705SXin Li   }
255*67e74705SXin Li 
Profile(llvm::FoldingSetNodeID & ID) const256*67e74705SXin Li   void Profile(llvm::FoldingSetNodeID& ID) const {
257*67e74705SXin Li     ID.Add(T);
258*67e74705SXin Li     ID.AddInteger(RawKind);
259*67e74705SXin Li     ID.AddInteger(Cnt);
260*67e74705SXin Li     ID.AddInteger(ACnt);
261*67e74705SXin Li     ID.AddInteger(RawObjectKind);
262*67e74705SXin Li     ID.AddInteger(RawIvarAccessHistory);
263*67e74705SXin Li   }
264*67e74705SXin Li 
265*67e74705SXin Li   void print(raw_ostream &Out) const;
266*67e74705SXin Li };
267*67e74705SXin Li 
print(raw_ostream & Out) const268*67e74705SXin Li void RefVal::print(raw_ostream &Out) const {
269*67e74705SXin Li   if (!T.isNull())
270*67e74705SXin Li     Out << "Tracked " << T.getAsString() << '/';
271*67e74705SXin Li 
272*67e74705SXin Li   switch (getKind()) {
273*67e74705SXin Li     default: llvm_unreachable("Invalid RefVal kind");
274*67e74705SXin Li     case Owned: {
275*67e74705SXin Li       Out << "Owned";
276*67e74705SXin Li       unsigned cnt = getCount();
277*67e74705SXin Li       if (cnt) Out << " (+ " << cnt << ")";
278*67e74705SXin Li       break;
279*67e74705SXin Li     }
280*67e74705SXin Li 
281*67e74705SXin Li     case NotOwned: {
282*67e74705SXin Li       Out << "NotOwned";
283*67e74705SXin Li       unsigned cnt = getCount();
284*67e74705SXin Li       if (cnt) Out << " (+ " << cnt << ")";
285*67e74705SXin Li       break;
286*67e74705SXin Li     }
287*67e74705SXin Li 
288*67e74705SXin Li     case ReturnedOwned: {
289*67e74705SXin Li       Out << "ReturnedOwned";
290*67e74705SXin Li       unsigned cnt = getCount();
291*67e74705SXin Li       if (cnt) Out << " (+ " << cnt << ")";
292*67e74705SXin Li       break;
293*67e74705SXin Li     }
294*67e74705SXin Li 
295*67e74705SXin Li     case ReturnedNotOwned: {
296*67e74705SXin Li       Out << "ReturnedNotOwned";
297*67e74705SXin Li       unsigned cnt = getCount();
298*67e74705SXin Li       if (cnt) Out << " (+ " << cnt << ")";
299*67e74705SXin Li       break;
300*67e74705SXin Li     }
301*67e74705SXin Li 
302*67e74705SXin Li     case Released:
303*67e74705SXin Li       Out << "Released";
304*67e74705SXin Li       break;
305*67e74705SXin Li 
306*67e74705SXin Li     case ErrorDeallocGC:
307*67e74705SXin Li       Out << "-dealloc (GC)";
308*67e74705SXin Li       break;
309*67e74705SXin Li 
310*67e74705SXin Li     case ErrorDeallocNotOwned:
311*67e74705SXin Li       Out << "-dealloc (not-owned)";
312*67e74705SXin Li       break;
313*67e74705SXin Li 
314*67e74705SXin Li     case ErrorLeak:
315*67e74705SXin Li       Out << "Leaked";
316*67e74705SXin Li       break;
317*67e74705SXin Li 
318*67e74705SXin Li     case ErrorLeakReturned:
319*67e74705SXin Li       Out << "Leaked (Bad naming)";
320*67e74705SXin Li       break;
321*67e74705SXin Li 
322*67e74705SXin Li     case ErrorGCLeakReturned:
323*67e74705SXin Li       Out << "Leaked (GC-ed at return)";
324*67e74705SXin Li       break;
325*67e74705SXin Li 
326*67e74705SXin Li     case ErrorUseAfterRelease:
327*67e74705SXin Li       Out << "Use-After-Release [ERROR]";
328*67e74705SXin Li       break;
329*67e74705SXin Li 
330*67e74705SXin Li     case ErrorReleaseNotOwned:
331*67e74705SXin Li       Out << "Release of Not-Owned [ERROR]";
332*67e74705SXin Li       break;
333*67e74705SXin Li 
334*67e74705SXin Li     case RefVal::ErrorOverAutorelease:
335*67e74705SXin Li       Out << "Over-autoreleased";
336*67e74705SXin Li       break;
337*67e74705SXin Li 
338*67e74705SXin Li     case RefVal::ErrorReturnedNotOwned:
339*67e74705SXin Li       Out << "Non-owned object returned instead of owned";
340*67e74705SXin Li       break;
341*67e74705SXin Li   }
342*67e74705SXin Li 
343*67e74705SXin Li   switch (getIvarAccessHistory()) {
344*67e74705SXin Li   case IvarAccessHistory::None:
345*67e74705SXin Li     break;
346*67e74705SXin Li   case IvarAccessHistory::AccessedDirectly:
347*67e74705SXin Li     Out << " [direct ivar access]";
348*67e74705SXin Li     break;
349*67e74705SXin Li   case IvarAccessHistory::ReleasedAfterDirectAccess:
350*67e74705SXin Li     Out << " [released after direct ivar access]";
351*67e74705SXin Li   }
352*67e74705SXin Li 
353*67e74705SXin Li   if (ACnt) {
354*67e74705SXin Li     Out << " [autorelease -" << ACnt << ']';
355*67e74705SXin Li   }
356*67e74705SXin Li }
357*67e74705SXin Li } //end anonymous namespace
358*67e74705SXin Li 
359*67e74705SXin Li //===----------------------------------------------------------------------===//
360*67e74705SXin Li // RefBindings - State used to track object reference counts.
361*67e74705SXin Li //===----------------------------------------------------------------------===//
362*67e74705SXin Li 
REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings,SymbolRef,RefVal) const363*67e74705SXin Li REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
364*67e74705SXin Li 
365*67e74705SXin Li static inline const RefVal *getRefBinding(ProgramStateRef State,
366*67e74705SXin Li                                           SymbolRef Sym) {
367*67e74705SXin Li   return State->get<RefBindings>(Sym);
368*67e74705SXin Li }
369*67e74705SXin Li 
setRefBinding(ProgramStateRef State,SymbolRef Sym,RefVal Val)370*67e74705SXin Li static inline ProgramStateRef setRefBinding(ProgramStateRef State,
371*67e74705SXin Li                                             SymbolRef Sym, RefVal Val) {
372*67e74705SXin Li   return State->set<RefBindings>(Sym, Val);
373*67e74705SXin Li }
374*67e74705SXin Li 
removeRefBinding(ProgramStateRef State,SymbolRef Sym)375*67e74705SXin Li static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
376*67e74705SXin Li   return State->remove<RefBindings>(Sym);
377*67e74705SXin Li }
378*67e74705SXin Li 
379*67e74705SXin Li //===----------------------------------------------------------------------===//
380*67e74705SXin Li // Function/Method behavior summaries.
381*67e74705SXin Li //===----------------------------------------------------------------------===//
382*67e74705SXin Li 
383*67e74705SXin Li namespace {
384*67e74705SXin Li class RetainSummary {
385*67e74705SXin Li   /// Args - a map of (index, ArgEffect) pairs, where index
386*67e74705SXin Li   ///  specifies the argument (starting from 0).  This can be sparsely
387*67e74705SXin Li   ///  populated; arguments with no entry in Args use 'DefaultArgEffect'.
388*67e74705SXin Li   ArgEffects Args;
389*67e74705SXin Li 
390*67e74705SXin Li   /// DefaultArgEffect - The default ArgEffect to apply to arguments that
391*67e74705SXin Li   ///  do not have an entry in Args.
392*67e74705SXin Li   ArgEffect DefaultArgEffect;
393*67e74705SXin Li 
394*67e74705SXin Li   /// Receiver - If this summary applies to an Objective-C message expression,
395*67e74705SXin Li   ///  this is the effect applied to the state of the receiver.
396*67e74705SXin Li   ArgEffect Receiver;
397*67e74705SXin Li 
398*67e74705SXin Li   /// Ret - The effect on the return value.  Used to indicate if the
399*67e74705SXin Li   ///  function/method call returns a new tracked symbol.
400*67e74705SXin Li   RetEffect Ret;
401*67e74705SXin Li 
402*67e74705SXin Li public:
RetainSummary(ArgEffects A,RetEffect R,ArgEffect defaultEff,ArgEffect ReceiverEff)403*67e74705SXin Li   RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
404*67e74705SXin Li                 ArgEffect ReceiverEff)
405*67e74705SXin Li     : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
406*67e74705SXin Li 
407*67e74705SXin Li   /// getArg - Return the argument effect on the argument specified by
408*67e74705SXin Li   ///  idx (starting from 0).
getArg(unsigned idx) const409*67e74705SXin Li   ArgEffect getArg(unsigned idx) const {
410*67e74705SXin Li     if (const ArgEffect *AE = Args.lookup(idx))
411*67e74705SXin Li       return *AE;
412*67e74705SXin Li 
413*67e74705SXin Li     return DefaultArgEffect;
414*67e74705SXin Li   }
415*67e74705SXin Li 
addArg(ArgEffects::Factory & af,unsigned idx,ArgEffect e)416*67e74705SXin Li   void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
417*67e74705SXin Li     Args = af.add(Args, idx, e);
418*67e74705SXin Li   }
419*67e74705SXin Li 
420*67e74705SXin Li   /// setDefaultArgEffect - Set the default argument effect.
setDefaultArgEffect(ArgEffect E)421*67e74705SXin Li   void setDefaultArgEffect(ArgEffect E) {
422*67e74705SXin Li     DefaultArgEffect = E;
423*67e74705SXin Li   }
424*67e74705SXin Li 
425*67e74705SXin Li   /// getRetEffect - Returns the effect on the return value of the call.
getRetEffect() const426*67e74705SXin Li   RetEffect getRetEffect() const { return Ret; }
427*67e74705SXin Li 
428*67e74705SXin Li   /// setRetEffect - Set the effect of the return value of the call.
setRetEffect(RetEffect E)429*67e74705SXin Li   void setRetEffect(RetEffect E) { Ret = E; }
430*67e74705SXin Li 
431*67e74705SXin Li 
432*67e74705SXin Li   /// Sets the effect on the receiver of the message.
setReceiverEffect(ArgEffect e)433*67e74705SXin Li   void setReceiverEffect(ArgEffect e) { Receiver = e; }
434*67e74705SXin Li 
435*67e74705SXin Li   /// getReceiverEffect - Returns the effect on the receiver of the call.
436*67e74705SXin Li   ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
getReceiverEffect() const437*67e74705SXin Li   ArgEffect getReceiverEffect() const { return Receiver; }
438*67e74705SXin Li 
439*67e74705SXin Li   /// Test if two retain summaries are identical. Note that merely equivalent
440*67e74705SXin Li   /// summaries are not necessarily identical (for example, if an explicit
441*67e74705SXin Li   /// argument effect matches the default effect).
operator ==(const RetainSummary & Other) const442*67e74705SXin Li   bool operator==(const RetainSummary &Other) const {
443*67e74705SXin Li     return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
444*67e74705SXin Li            Receiver == Other.Receiver && Ret == Other.Ret;
445*67e74705SXin Li   }
446*67e74705SXin Li 
447*67e74705SXin Li   /// Profile this summary for inclusion in a FoldingSet.
Profile(llvm::FoldingSetNodeID & ID) const448*67e74705SXin Li   void Profile(llvm::FoldingSetNodeID& ID) const {
449*67e74705SXin Li     ID.Add(Args);
450*67e74705SXin Li     ID.Add(DefaultArgEffect);
451*67e74705SXin Li     ID.Add(Receiver);
452*67e74705SXin Li     ID.Add(Ret);
453*67e74705SXin Li   }
454*67e74705SXin Li 
455*67e74705SXin Li   /// A retain summary is simple if it has no ArgEffects other than the default.
isSimple() const456*67e74705SXin Li   bool isSimple() const {
457*67e74705SXin Li     return Args.isEmpty();
458*67e74705SXin Li   }
459*67e74705SXin Li 
460*67e74705SXin Li private:
getArgEffects() const461*67e74705SXin Li   ArgEffects getArgEffects() const { return Args; }
getDefaultArgEffect() const462*67e74705SXin Li   ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
463*67e74705SXin Li 
464*67e74705SXin Li   friend class RetainSummaryManager;
465*67e74705SXin Li };
466*67e74705SXin Li } // end anonymous namespace
467*67e74705SXin Li 
468*67e74705SXin Li //===----------------------------------------------------------------------===//
469*67e74705SXin Li // Data structures for constructing summaries.
470*67e74705SXin Li //===----------------------------------------------------------------------===//
471*67e74705SXin Li 
472*67e74705SXin Li namespace {
473*67e74705SXin Li class ObjCSummaryKey {
474*67e74705SXin Li   IdentifierInfo* II;
475*67e74705SXin Li   Selector S;
476*67e74705SXin Li public:
ObjCSummaryKey(IdentifierInfo * ii,Selector s)477*67e74705SXin Li   ObjCSummaryKey(IdentifierInfo* ii, Selector s)
478*67e74705SXin Li     : II(ii), S(s) {}
479*67e74705SXin Li 
ObjCSummaryKey(const ObjCInterfaceDecl * d,Selector s)480*67e74705SXin Li   ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
481*67e74705SXin Li     : II(d ? d->getIdentifier() : nullptr), S(s) {}
482*67e74705SXin Li 
ObjCSummaryKey(Selector s)483*67e74705SXin Li   ObjCSummaryKey(Selector s)
484*67e74705SXin Li     : II(nullptr), S(s) {}
485*67e74705SXin Li 
getIdentifier() const486*67e74705SXin Li   IdentifierInfo *getIdentifier() const { return II; }
getSelector() const487*67e74705SXin Li   Selector getSelector() const { return S; }
488*67e74705SXin Li };
489*67e74705SXin Li } // end anonymous namespace
490*67e74705SXin Li 
491*67e74705SXin Li namespace llvm {
492*67e74705SXin Li template <> struct DenseMapInfo<ObjCSummaryKey> {
getEmptyKeyllvm::DenseMapInfo493*67e74705SXin Li   static inline ObjCSummaryKey getEmptyKey() {
494*67e74705SXin Li     return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
495*67e74705SXin Li                           DenseMapInfo<Selector>::getEmptyKey());
496*67e74705SXin Li   }
497*67e74705SXin Li 
getTombstoneKeyllvm::DenseMapInfo498*67e74705SXin Li   static inline ObjCSummaryKey getTombstoneKey() {
499*67e74705SXin Li     return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
500*67e74705SXin Li                           DenseMapInfo<Selector>::getTombstoneKey());
501*67e74705SXin Li   }
502*67e74705SXin Li 
getHashValuellvm::DenseMapInfo503*67e74705SXin Li   static unsigned getHashValue(const ObjCSummaryKey &V) {
504*67e74705SXin Li     typedef std::pair<IdentifierInfo*, Selector> PairTy;
505*67e74705SXin Li     return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
506*67e74705SXin Li                                                      V.getSelector()));
507*67e74705SXin Li   }
508*67e74705SXin Li 
isEqualllvm::DenseMapInfo509*67e74705SXin Li   static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
510*67e74705SXin Li     return LHS.getIdentifier() == RHS.getIdentifier() &&
511*67e74705SXin Li            LHS.getSelector() == RHS.getSelector();
512*67e74705SXin Li   }
513*67e74705SXin Li 
514*67e74705SXin Li };
515*67e74705SXin Li } // end llvm namespace
516*67e74705SXin Li 
517*67e74705SXin Li namespace {
518*67e74705SXin Li class ObjCSummaryCache {
519*67e74705SXin Li   typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
520*67e74705SXin Li   MapTy M;
521*67e74705SXin Li public:
ObjCSummaryCache()522*67e74705SXin Li   ObjCSummaryCache() {}
523*67e74705SXin Li 
find(const ObjCInterfaceDecl * D,Selector S)524*67e74705SXin Li   const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
525*67e74705SXin Li     // Do a lookup with the (D,S) pair.  If we find a match return
526*67e74705SXin Li     // the iterator.
527*67e74705SXin Li     ObjCSummaryKey K(D, S);
528*67e74705SXin Li     MapTy::iterator I = M.find(K);
529*67e74705SXin Li 
530*67e74705SXin Li     if (I != M.end())
531*67e74705SXin Li       return I->second;
532*67e74705SXin Li     if (!D)
533*67e74705SXin Li       return nullptr;
534*67e74705SXin Li 
535*67e74705SXin Li     // Walk the super chain.  If we find a hit with a parent, we'll end
536*67e74705SXin Li     // up returning that summary.  We actually allow that key (null,S), as
537*67e74705SXin Li     // we cache summaries for the null ObjCInterfaceDecl* to allow us to
538*67e74705SXin Li     // generate initial summaries without having to worry about NSObject
539*67e74705SXin Li     // being declared.
540*67e74705SXin Li     // FIXME: We may change this at some point.
541*67e74705SXin Li     for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
542*67e74705SXin Li       if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
543*67e74705SXin Li         break;
544*67e74705SXin Li 
545*67e74705SXin Li       if (!C)
546*67e74705SXin Li         return nullptr;
547*67e74705SXin Li     }
548*67e74705SXin Li 
549*67e74705SXin Li     // Cache the summary with original key to make the next lookup faster
550*67e74705SXin Li     // and return the iterator.
551*67e74705SXin Li     const RetainSummary *Summ = I->second;
552*67e74705SXin Li     M[K] = Summ;
553*67e74705SXin Li     return Summ;
554*67e74705SXin Li   }
555*67e74705SXin Li 
find(IdentifierInfo * II,Selector S)556*67e74705SXin Li   const RetainSummary *find(IdentifierInfo* II, Selector S) {
557*67e74705SXin Li     // FIXME: Class method lookup.  Right now we dont' have a good way
558*67e74705SXin Li     // of going between IdentifierInfo* and the class hierarchy.
559*67e74705SXin Li     MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
560*67e74705SXin Li 
561*67e74705SXin Li     if (I == M.end())
562*67e74705SXin Li       I = M.find(ObjCSummaryKey(S));
563*67e74705SXin Li 
564*67e74705SXin Li     return I == M.end() ? nullptr : I->second;
565*67e74705SXin Li   }
566*67e74705SXin Li 
operator [](ObjCSummaryKey K)567*67e74705SXin Li   const RetainSummary *& operator[](ObjCSummaryKey K) {
568*67e74705SXin Li     return M[K];
569*67e74705SXin Li   }
570*67e74705SXin Li 
operator [](Selector S)571*67e74705SXin Li   const RetainSummary *& operator[](Selector S) {
572*67e74705SXin Li     return M[ ObjCSummaryKey(S) ];
573*67e74705SXin Li   }
574*67e74705SXin Li };
575*67e74705SXin Li } // end anonymous namespace
576*67e74705SXin Li 
577*67e74705SXin Li //===----------------------------------------------------------------------===//
578*67e74705SXin Li // Data structures for managing collections of summaries.
579*67e74705SXin Li //===----------------------------------------------------------------------===//
580*67e74705SXin Li 
581*67e74705SXin Li namespace {
582*67e74705SXin Li class RetainSummaryManager {
583*67e74705SXin Li 
584*67e74705SXin Li   //==-----------------------------------------------------------------==//
585*67e74705SXin Li   //  Typedefs.
586*67e74705SXin Li   //==-----------------------------------------------------------------==//
587*67e74705SXin Li 
588*67e74705SXin Li   typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
589*67e74705SXin Li           FuncSummariesTy;
590*67e74705SXin Li 
591*67e74705SXin Li   typedef ObjCSummaryCache ObjCMethodSummariesTy;
592*67e74705SXin Li 
593*67e74705SXin Li   typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
594*67e74705SXin Li 
595*67e74705SXin Li   //==-----------------------------------------------------------------==//
596*67e74705SXin Li   //  Data.
597*67e74705SXin Li   //==-----------------------------------------------------------------==//
598*67e74705SXin Li 
599*67e74705SXin Li   /// Ctx - The ASTContext object for the analyzed ASTs.
600*67e74705SXin Li   ASTContext &Ctx;
601*67e74705SXin Li 
602*67e74705SXin Li   /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
603*67e74705SXin Li   const bool GCEnabled;
604*67e74705SXin Li 
605*67e74705SXin Li   /// Records whether or not the analyzed code runs in ARC mode.
606*67e74705SXin Li   const bool ARCEnabled;
607*67e74705SXin Li 
608*67e74705SXin Li   /// FuncSummaries - A map from FunctionDecls to summaries.
609*67e74705SXin Li   FuncSummariesTy FuncSummaries;
610*67e74705SXin Li 
611*67e74705SXin Li   /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
612*67e74705SXin Li   ///  to summaries.
613*67e74705SXin Li   ObjCMethodSummariesTy ObjCClassMethodSummaries;
614*67e74705SXin Li 
615*67e74705SXin Li   /// ObjCMethodSummaries - A map from selectors to summaries.
616*67e74705SXin Li   ObjCMethodSummariesTy ObjCMethodSummaries;
617*67e74705SXin Li 
618*67e74705SXin Li   /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
619*67e74705SXin Li   ///  and all other data used by the checker.
620*67e74705SXin Li   llvm::BumpPtrAllocator BPAlloc;
621*67e74705SXin Li 
622*67e74705SXin Li   /// AF - A factory for ArgEffects objects.
623*67e74705SXin Li   ArgEffects::Factory AF;
624*67e74705SXin Li 
625*67e74705SXin Li   /// ScratchArgs - A holding buffer for construct ArgEffects.
626*67e74705SXin Li   ArgEffects ScratchArgs;
627*67e74705SXin Li 
628*67e74705SXin Li   /// ObjCAllocRetE - Default return effect for methods returning Objective-C
629*67e74705SXin Li   ///  objects.
630*67e74705SXin Li   RetEffect ObjCAllocRetE;
631*67e74705SXin Li 
632*67e74705SXin Li   /// ObjCInitRetE - Default return effect for init methods returning
633*67e74705SXin Li   ///   Objective-C objects.
634*67e74705SXin Li   RetEffect ObjCInitRetE;
635*67e74705SXin Li 
636*67e74705SXin Li   /// SimpleSummaries - Used for uniquing summaries that don't have special
637*67e74705SXin Li   /// effects.
638*67e74705SXin Li   llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
639*67e74705SXin Li 
640*67e74705SXin Li   //==-----------------------------------------------------------------==//
641*67e74705SXin Li   //  Methods.
642*67e74705SXin Li   //==-----------------------------------------------------------------==//
643*67e74705SXin Li 
644*67e74705SXin Li   /// getArgEffects - Returns a persistent ArgEffects object based on the
645*67e74705SXin Li   ///  data in ScratchArgs.
646*67e74705SXin Li   ArgEffects getArgEffects();
647*67e74705SXin Li 
648*67e74705SXin Li   enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
649*67e74705SXin Li 
650*67e74705SXin Li   const RetainSummary *getUnarySummary(const FunctionType* FT,
651*67e74705SXin Li                                        UnaryFuncKind func);
652*67e74705SXin Li 
653*67e74705SXin Li   const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
654*67e74705SXin Li   const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
655*67e74705SXin Li   const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
656*67e74705SXin Li 
657*67e74705SXin Li   const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
658*67e74705SXin Li 
getPersistentSummary(RetEffect RetEff,ArgEffect ReceiverEff=DoNothing,ArgEffect DefaultEff=MayEscape)659*67e74705SXin Li   const RetainSummary *getPersistentSummary(RetEffect RetEff,
660*67e74705SXin Li                                             ArgEffect ReceiverEff = DoNothing,
661*67e74705SXin Li                                             ArgEffect DefaultEff = MayEscape) {
662*67e74705SXin Li     RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
663*67e74705SXin Li     return getPersistentSummary(Summ);
664*67e74705SXin Li   }
665*67e74705SXin Li 
getDoNothingSummary()666*67e74705SXin Li   const RetainSummary *getDoNothingSummary() {
667*67e74705SXin Li     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
668*67e74705SXin Li   }
669*67e74705SXin Li 
getDefaultSummary()670*67e74705SXin Li   const RetainSummary *getDefaultSummary() {
671*67e74705SXin Li     return getPersistentSummary(RetEffect::MakeNoRet(),
672*67e74705SXin Li                                 DoNothing, MayEscape);
673*67e74705SXin Li   }
674*67e74705SXin Li 
getPersistentStopSummary()675*67e74705SXin Li   const RetainSummary *getPersistentStopSummary() {
676*67e74705SXin Li     return getPersistentSummary(RetEffect::MakeNoRet(),
677*67e74705SXin Li                                 StopTracking, StopTracking);
678*67e74705SXin Li   }
679*67e74705SXin Li 
680*67e74705SXin Li   void InitializeClassMethodSummaries();
681*67e74705SXin Li   void InitializeMethodSummaries();
682*67e74705SXin Li private:
addNSObjectClsMethSummary(Selector S,const RetainSummary * Summ)683*67e74705SXin Li   void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
684*67e74705SXin Li     ObjCClassMethodSummaries[S] = Summ;
685*67e74705SXin Li   }
686*67e74705SXin Li 
addNSObjectMethSummary(Selector S,const RetainSummary * Summ)687*67e74705SXin Li   void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
688*67e74705SXin Li     ObjCMethodSummaries[S] = Summ;
689*67e74705SXin Li   }
690*67e74705SXin Li 
addClassMethSummary(const char * Cls,const char * name,const RetainSummary * Summ,bool isNullary=true)691*67e74705SXin Li   void addClassMethSummary(const char* Cls, const char* name,
692*67e74705SXin Li                            const RetainSummary *Summ, bool isNullary = true) {
693*67e74705SXin Li     IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
694*67e74705SXin Li     Selector S = isNullary ? GetNullarySelector(name, Ctx)
695*67e74705SXin Li                            : GetUnarySelector(name, Ctx);
696*67e74705SXin Li     ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
697*67e74705SXin Li   }
698*67e74705SXin Li 
addInstMethSummary(const char * Cls,const char * nullaryName,const RetainSummary * Summ)699*67e74705SXin Li   void addInstMethSummary(const char* Cls, const char* nullaryName,
700*67e74705SXin Li                           const RetainSummary *Summ) {
701*67e74705SXin Li     IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
702*67e74705SXin Li     Selector S = GetNullarySelector(nullaryName, Ctx);
703*67e74705SXin Li     ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
704*67e74705SXin Li   }
705*67e74705SXin Li 
addMethodSummary(IdentifierInfo * ClsII,ObjCMethodSummariesTy & Summaries,const RetainSummary * Summ,va_list argp)706*67e74705SXin Li   void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
707*67e74705SXin Li                         const RetainSummary *Summ, va_list argp) {
708*67e74705SXin Li     Selector S = getKeywordSelector(Ctx, argp);
709*67e74705SXin Li     Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
710*67e74705SXin Li   }
711*67e74705SXin Li 
addInstMethSummary(const char * Cls,const RetainSummary * Summ,...)712*67e74705SXin Li   void addInstMethSummary(const char* Cls, const RetainSummary * Summ, ...) {
713*67e74705SXin Li     va_list argp;
714*67e74705SXin Li     va_start(argp, Summ);
715*67e74705SXin Li     addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
716*67e74705SXin Li     va_end(argp);
717*67e74705SXin Li   }
718*67e74705SXin Li 
addClsMethSummary(const char * Cls,const RetainSummary * Summ,...)719*67e74705SXin Li   void addClsMethSummary(const char* Cls, const RetainSummary * Summ, ...) {
720*67e74705SXin Li     va_list argp;
721*67e74705SXin Li     va_start(argp, Summ);
722*67e74705SXin Li     addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
723*67e74705SXin Li     va_end(argp);
724*67e74705SXin Li   }
725*67e74705SXin Li 
addClsMethSummary(IdentifierInfo * II,const RetainSummary * Summ,...)726*67e74705SXin Li   void addClsMethSummary(IdentifierInfo *II, const RetainSummary * Summ, ...) {
727*67e74705SXin Li     va_list argp;
728*67e74705SXin Li     va_start(argp, Summ);
729*67e74705SXin Li     addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
730*67e74705SXin Li     va_end(argp);
731*67e74705SXin Li   }
732*67e74705SXin Li 
733*67e74705SXin Li public:
734*67e74705SXin Li 
RetainSummaryManager(ASTContext & ctx,bool gcenabled,bool usesARC)735*67e74705SXin Li   RetainSummaryManager(ASTContext &ctx, bool gcenabled, bool usesARC)
736*67e74705SXin Li    : Ctx(ctx),
737*67e74705SXin Li      GCEnabled(gcenabled),
738*67e74705SXin Li      ARCEnabled(usesARC),
739*67e74705SXin Li      AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
740*67e74705SXin Li      ObjCAllocRetE(gcenabled
741*67e74705SXin Li                     ? RetEffect::MakeGCNotOwned()
742*67e74705SXin Li                     : (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
743*67e74705SXin Li                                : RetEffect::MakeOwned(RetEffect::ObjC, true))),
744*67e74705SXin Li      ObjCInitRetE(gcenabled
745*67e74705SXin Li                     ? RetEffect::MakeGCNotOwned()
746*67e74705SXin Li                     : (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
747*67e74705SXin Li                                : RetEffect::MakeOwnedWhenTrackedReceiver())) {
748*67e74705SXin Li     InitializeClassMethodSummaries();
749*67e74705SXin Li     InitializeMethodSummaries();
750*67e74705SXin Li   }
751*67e74705SXin Li 
752*67e74705SXin Li   const RetainSummary *getSummary(const CallEvent &Call,
753*67e74705SXin Li                                   ProgramStateRef State = nullptr);
754*67e74705SXin Li 
755*67e74705SXin Li   const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
756*67e74705SXin Li 
757*67e74705SXin Li   const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
758*67e74705SXin Li                                         const ObjCMethodDecl *MD,
759*67e74705SXin Li                                         QualType RetTy,
760*67e74705SXin Li                                         ObjCMethodSummariesTy &CachedSummaries);
761*67e74705SXin Li 
762*67e74705SXin Li   const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M,
763*67e74705SXin Li                                                 ProgramStateRef State);
764*67e74705SXin Li 
getClassMethodSummary(const ObjCMethodCall & M)765*67e74705SXin Li   const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
766*67e74705SXin Li     assert(!M.isInstanceMessage());
767*67e74705SXin Li     const ObjCInterfaceDecl *Class = M.getReceiverInterface();
768*67e74705SXin Li 
769*67e74705SXin Li     return getMethodSummary(M.getSelector(), Class, M.getDecl(),
770*67e74705SXin Li                             M.getResultType(), ObjCClassMethodSummaries);
771*67e74705SXin Li   }
772*67e74705SXin Li 
773*67e74705SXin Li   /// getMethodSummary - This version of getMethodSummary is used to query
774*67e74705SXin Li   ///  the summary for the current method being analyzed.
getMethodSummary(const ObjCMethodDecl * MD)775*67e74705SXin Li   const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
776*67e74705SXin Li     const ObjCInterfaceDecl *ID = MD->getClassInterface();
777*67e74705SXin Li     Selector S = MD->getSelector();
778*67e74705SXin Li     QualType ResultTy = MD->getReturnType();
779*67e74705SXin Li 
780*67e74705SXin Li     ObjCMethodSummariesTy *CachedSummaries;
781*67e74705SXin Li     if (MD->isInstanceMethod())
782*67e74705SXin Li       CachedSummaries = &ObjCMethodSummaries;
783*67e74705SXin Li     else
784*67e74705SXin Li       CachedSummaries = &ObjCClassMethodSummaries;
785*67e74705SXin Li 
786*67e74705SXin Li     return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
787*67e74705SXin Li   }
788*67e74705SXin Li 
789*67e74705SXin Li   const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
790*67e74705SXin Li                                                 Selector S, QualType RetTy);
791*67e74705SXin Li 
792*67e74705SXin Li   /// Determine if there is a special return effect for this function or method.
793*67e74705SXin Li   Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
794*67e74705SXin Li                                                   const Decl *D);
795*67e74705SXin Li 
796*67e74705SXin Li   void updateSummaryFromAnnotations(const RetainSummary *&Summ,
797*67e74705SXin Li                                     const ObjCMethodDecl *MD);
798*67e74705SXin Li 
799*67e74705SXin Li   void updateSummaryFromAnnotations(const RetainSummary *&Summ,
800*67e74705SXin Li                                     const FunctionDecl *FD);
801*67e74705SXin Li 
802*67e74705SXin Li   void updateSummaryForCall(const RetainSummary *&Summ,
803*67e74705SXin Li                             const CallEvent &Call);
804*67e74705SXin Li 
isGCEnabled() const805*67e74705SXin Li   bool isGCEnabled() const { return GCEnabled; }
806*67e74705SXin Li 
isARCEnabled() const807*67e74705SXin Li   bool isARCEnabled() const { return ARCEnabled; }
808*67e74705SXin Li 
isARCorGCEnabled() const809*67e74705SXin Li   bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; }
810*67e74705SXin Li 
getObjAllocRetEffect() const811*67e74705SXin Li   RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
812*67e74705SXin Li 
813*67e74705SXin Li   friend class RetainSummaryTemplate;
814*67e74705SXin Li };
815*67e74705SXin Li 
816*67e74705SXin Li // Used to avoid allocating long-term (BPAlloc'd) memory for default retain
817*67e74705SXin Li // summaries. If a function or method looks like it has a default summary, but
818*67e74705SXin Li // it has annotations, the annotations are added to the stack-based template
819*67e74705SXin Li // and then copied into managed memory.
820*67e74705SXin Li class RetainSummaryTemplate {
821*67e74705SXin Li   RetainSummaryManager &Manager;
822*67e74705SXin Li   const RetainSummary *&RealSummary;
823*67e74705SXin Li   RetainSummary ScratchSummary;
824*67e74705SXin Li   bool Accessed;
825*67e74705SXin Li public:
RetainSummaryTemplate(const RetainSummary * & real,RetainSummaryManager & mgr)826*67e74705SXin Li   RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
827*67e74705SXin Li     : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
828*67e74705SXin Li 
~RetainSummaryTemplate()829*67e74705SXin Li   ~RetainSummaryTemplate() {
830*67e74705SXin Li     if (Accessed)
831*67e74705SXin Li       RealSummary = Manager.getPersistentSummary(ScratchSummary);
832*67e74705SXin Li   }
833*67e74705SXin Li 
operator *()834*67e74705SXin Li   RetainSummary &operator*() {
835*67e74705SXin Li     Accessed = true;
836*67e74705SXin Li     return ScratchSummary;
837*67e74705SXin Li   }
838*67e74705SXin Li 
operator ->()839*67e74705SXin Li   RetainSummary *operator->() {
840*67e74705SXin Li     Accessed = true;
841*67e74705SXin Li     return &ScratchSummary;
842*67e74705SXin Li   }
843*67e74705SXin Li };
844*67e74705SXin Li 
845*67e74705SXin Li } // end anonymous namespace
846*67e74705SXin Li 
847*67e74705SXin Li //===----------------------------------------------------------------------===//
848*67e74705SXin Li // Implementation of checker data structures.
849*67e74705SXin Li //===----------------------------------------------------------------------===//
850*67e74705SXin Li 
getArgEffects()851*67e74705SXin Li ArgEffects RetainSummaryManager::getArgEffects() {
852*67e74705SXin Li   ArgEffects AE = ScratchArgs;
853*67e74705SXin Li   ScratchArgs = AF.getEmptyMap();
854*67e74705SXin Li   return AE;
855*67e74705SXin Li }
856*67e74705SXin Li 
857*67e74705SXin Li const RetainSummary *
getPersistentSummary(const RetainSummary & OldSumm)858*67e74705SXin Li RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
859*67e74705SXin Li   // Unique "simple" summaries -- those without ArgEffects.
860*67e74705SXin Li   if (OldSumm.isSimple()) {
861*67e74705SXin Li     llvm::FoldingSetNodeID ID;
862*67e74705SXin Li     OldSumm.Profile(ID);
863*67e74705SXin Li 
864*67e74705SXin Li     void *Pos;
865*67e74705SXin Li     CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
866*67e74705SXin Li 
867*67e74705SXin Li     if (!N) {
868*67e74705SXin Li       N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
869*67e74705SXin Li       new (N) CachedSummaryNode(OldSumm);
870*67e74705SXin Li       SimpleSummaries.InsertNode(N, Pos);
871*67e74705SXin Li     }
872*67e74705SXin Li 
873*67e74705SXin Li     return &N->getValue();
874*67e74705SXin Li   }
875*67e74705SXin Li 
876*67e74705SXin Li   RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
877*67e74705SXin Li   new (Summ) RetainSummary(OldSumm);
878*67e74705SXin Li   return Summ;
879*67e74705SXin Li }
880*67e74705SXin Li 
881*67e74705SXin Li //===----------------------------------------------------------------------===//
882*67e74705SXin Li // Summary creation for functions (largely uses of Core Foundation).
883*67e74705SXin Li //===----------------------------------------------------------------------===//
884*67e74705SXin Li 
isRetain(const FunctionDecl * FD,StringRef FName)885*67e74705SXin Li static bool isRetain(const FunctionDecl *FD, StringRef FName) {
886*67e74705SXin Li   return FName.endswith("Retain");
887*67e74705SXin Li }
888*67e74705SXin Li 
isRelease(const FunctionDecl * FD,StringRef FName)889*67e74705SXin Li static bool isRelease(const FunctionDecl *FD, StringRef FName) {
890*67e74705SXin Li   return FName.endswith("Release");
891*67e74705SXin Li }
892*67e74705SXin Li 
isAutorelease(const FunctionDecl * FD,StringRef FName)893*67e74705SXin Li static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
894*67e74705SXin Li   return FName.endswith("Autorelease");
895*67e74705SXin Li }
896*67e74705SXin Li 
isMakeCollectable(const FunctionDecl * FD,StringRef FName)897*67e74705SXin Li static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) {
898*67e74705SXin Li   // FIXME: Remove FunctionDecl parameter.
899*67e74705SXin Li   // FIXME: Is it really okay if MakeCollectable isn't a suffix?
900*67e74705SXin Li   return FName.find("MakeCollectable") != StringRef::npos;
901*67e74705SXin Li }
902*67e74705SXin Li 
getStopTrackingHardEquivalent(ArgEffect E)903*67e74705SXin Li static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
904*67e74705SXin Li   switch (E) {
905*67e74705SXin Li   case DoNothing:
906*67e74705SXin Li   case Autorelease:
907*67e74705SXin Li   case DecRefBridgedTransferred:
908*67e74705SXin Li   case IncRef:
909*67e74705SXin Li   case IncRefMsg:
910*67e74705SXin Li   case MakeCollectable:
911*67e74705SXin Li   case UnretainedOutParameter:
912*67e74705SXin Li   case RetainedOutParameter:
913*67e74705SXin Li   case MayEscape:
914*67e74705SXin Li   case StopTracking:
915*67e74705SXin Li   case StopTrackingHard:
916*67e74705SXin Li     return StopTrackingHard;
917*67e74705SXin Li   case DecRef:
918*67e74705SXin Li   case DecRefAndStopTrackingHard:
919*67e74705SXin Li     return DecRefAndStopTrackingHard;
920*67e74705SXin Li   case DecRefMsg:
921*67e74705SXin Li   case DecRefMsgAndStopTrackingHard:
922*67e74705SXin Li     return DecRefMsgAndStopTrackingHard;
923*67e74705SXin Li   case Dealloc:
924*67e74705SXin Li     return Dealloc;
925*67e74705SXin Li   }
926*67e74705SXin Li 
927*67e74705SXin Li   llvm_unreachable("Unknown ArgEffect kind");
928*67e74705SXin Li }
929*67e74705SXin Li 
updateSummaryForCall(const RetainSummary * & S,const CallEvent & Call)930*67e74705SXin Li void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
931*67e74705SXin Li                                                 const CallEvent &Call) {
932*67e74705SXin Li   if (Call.hasNonZeroCallbackArg()) {
933*67e74705SXin Li     ArgEffect RecEffect =
934*67e74705SXin Li       getStopTrackingHardEquivalent(S->getReceiverEffect());
935*67e74705SXin Li     ArgEffect DefEffect =
936*67e74705SXin Li       getStopTrackingHardEquivalent(S->getDefaultArgEffect());
937*67e74705SXin Li 
938*67e74705SXin Li     ArgEffects CustomArgEffects = S->getArgEffects();
939*67e74705SXin Li     for (ArgEffects::iterator I = CustomArgEffects.begin(),
940*67e74705SXin Li                               E = CustomArgEffects.end();
941*67e74705SXin Li          I != E; ++I) {
942*67e74705SXin Li       ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
943*67e74705SXin Li       if (Translated != DefEffect)
944*67e74705SXin Li         ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
945*67e74705SXin Li     }
946*67e74705SXin Li 
947*67e74705SXin Li     RetEffect RE = RetEffect::MakeNoRetHard();
948*67e74705SXin Li 
949*67e74705SXin Li     // Special cases where the callback argument CANNOT free the return value.
950*67e74705SXin Li     // This can generally only happen if we know that the callback will only be
951*67e74705SXin Li     // called when the return value is already being deallocated.
952*67e74705SXin Li     if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {
953*67e74705SXin Li       if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
954*67e74705SXin Li         // When the CGBitmapContext is deallocated, the callback here will free
955*67e74705SXin Li         // the associated data buffer.
956*67e74705SXin Li         if (Name->isStr("CGBitmapContextCreateWithData"))
957*67e74705SXin Li           RE = S->getRetEffect();
958*67e74705SXin Li       }
959*67e74705SXin Li     }
960*67e74705SXin Li 
961*67e74705SXin Li     S = getPersistentSummary(RE, RecEffect, DefEffect);
962*67e74705SXin Li   }
963*67e74705SXin Li 
964*67e74705SXin Li   // Special case '[super init];' and '[self init];'
965*67e74705SXin Li   //
966*67e74705SXin Li   // Even though calling '[super init]' without assigning the result to self
967*67e74705SXin Li   // and checking if the parent returns 'nil' is a bad pattern, it is common.
968*67e74705SXin Li   // Additionally, our Self Init checker already warns about it. To avoid
969*67e74705SXin Li   // overwhelming the user with messages from both checkers, we model the case
970*67e74705SXin Li   // of '[super init]' in cases when it is not consumed by another expression
971*67e74705SXin Li   // as if the call preserves the value of 'self'; essentially, assuming it can
972*67e74705SXin Li   // never fail and return 'nil'.
973*67e74705SXin Li   // Note, we don't want to just stop tracking the value since we want the
974*67e74705SXin Li   // RetainCount checker to report leaks and use-after-free if SelfInit checker
975*67e74705SXin Li   // is turned off.
976*67e74705SXin Li   if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
977*67e74705SXin Li     if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
978*67e74705SXin Li 
979*67e74705SXin Li       // Check if the message is not consumed, we know it will not be used in
980*67e74705SXin Li       // an assignment, ex: "self = [super init]".
981*67e74705SXin Li       const Expr *ME = MC->getOriginExpr();
982*67e74705SXin Li       const LocationContext *LCtx = MC->getLocationContext();
983*67e74705SXin Li       ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
984*67e74705SXin Li       if (!PM.isConsumedExpr(ME)) {
985*67e74705SXin Li         RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
986*67e74705SXin Li         ModifiableSummaryTemplate->setReceiverEffect(DoNothing);
987*67e74705SXin Li         ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
988*67e74705SXin Li       }
989*67e74705SXin Li     }
990*67e74705SXin Li   }
991*67e74705SXin Li }
992*67e74705SXin Li 
993*67e74705SXin Li const RetainSummary *
getSummary(const CallEvent & Call,ProgramStateRef State)994*67e74705SXin Li RetainSummaryManager::getSummary(const CallEvent &Call,
995*67e74705SXin Li                                  ProgramStateRef State) {
996*67e74705SXin Li   const RetainSummary *Summ;
997*67e74705SXin Li   switch (Call.getKind()) {
998*67e74705SXin Li   case CE_Function:
999*67e74705SXin Li     Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
1000*67e74705SXin Li     break;
1001*67e74705SXin Li   case CE_CXXMember:
1002*67e74705SXin Li   case CE_CXXMemberOperator:
1003*67e74705SXin Li   case CE_Block:
1004*67e74705SXin Li   case CE_CXXConstructor:
1005*67e74705SXin Li   case CE_CXXDestructor:
1006*67e74705SXin Li   case CE_CXXAllocator:
1007*67e74705SXin Li     // FIXME: These calls are currently unsupported.
1008*67e74705SXin Li     return getPersistentStopSummary();
1009*67e74705SXin Li   case CE_ObjCMessage: {
1010*67e74705SXin Li     const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
1011*67e74705SXin Li     if (Msg.isInstanceMessage())
1012*67e74705SXin Li       Summ = getInstanceMethodSummary(Msg, State);
1013*67e74705SXin Li     else
1014*67e74705SXin Li       Summ = getClassMethodSummary(Msg);
1015*67e74705SXin Li     break;
1016*67e74705SXin Li   }
1017*67e74705SXin Li   }
1018*67e74705SXin Li 
1019*67e74705SXin Li   updateSummaryForCall(Summ, Call);
1020*67e74705SXin Li 
1021*67e74705SXin Li   assert(Summ && "Unknown call type?");
1022*67e74705SXin Li   return Summ;
1023*67e74705SXin Li }
1024*67e74705SXin Li 
1025*67e74705SXin Li const RetainSummary *
getFunctionSummary(const FunctionDecl * FD)1026*67e74705SXin Li RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
1027*67e74705SXin Li   // If we don't know what function we're calling, use our default summary.
1028*67e74705SXin Li   if (!FD)
1029*67e74705SXin Li     return getDefaultSummary();
1030*67e74705SXin Li 
1031*67e74705SXin Li   // Look up a summary in our cache of FunctionDecls -> Summaries.
1032*67e74705SXin Li   FuncSummariesTy::iterator I = FuncSummaries.find(FD);
1033*67e74705SXin Li   if (I != FuncSummaries.end())
1034*67e74705SXin Li     return I->second;
1035*67e74705SXin Li 
1036*67e74705SXin Li   // No summary?  Generate one.
1037*67e74705SXin Li   const RetainSummary *S = nullptr;
1038*67e74705SXin Li   bool AllowAnnotations = true;
1039*67e74705SXin Li 
1040*67e74705SXin Li   do {
1041*67e74705SXin Li     // We generate "stop" summaries for implicitly defined functions.
1042*67e74705SXin Li     if (FD->isImplicit()) {
1043*67e74705SXin Li       S = getPersistentStopSummary();
1044*67e74705SXin Li       break;
1045*67e74705SXin Li     }
1046*67e74705SXin Li 
1047*67e74705SXin Li     // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
1048*67e74705SXin Li     // function's type.
1049*67e74705SXin Li     const FunctionType* FT = FD->getType()->getAs<FunctionType>();
1050*67e74705SXin Li     const IdentifierInfo *II = FD->getIdentifier();
1051*67e74705SXin Li     if (!II)
1052*67e74705SXin Li       break;
1053*67e74705SXin Li 
1054*67e74705SXin Li     StringRef FName = II->getName();
1055*67e74705SXin Li 
1056*67e74705SXin Li     // Strip away preceding '_'.  Doing this here will effect all the checks
1057*67e74705SXin Li     // down below.
1058*67e74705SXin Li     FName = FName.substr(FName.find_first_not_of('_'));
1059*67e74705SXin Li 
1060*67e74705SXin Li     // Inspect the result type.
1061*67e74705SXin Li     QualType RetTy = FT->getReturnType();
1062*67e74705SXin Li 
1063*67e74705SXin Li     // FIXME: This should all be refactored into a chain of "summary lookup"
1064*67e74705SXin Li     //  filters.
1065*67e74705SXin Li     assert(ScratchArgs.isEmpty());
1066*67e74705SXin Li 
1067*67e74705SXin Li     if (FName == "pthread_create" || FName == "pthread_setspecific") {
1068*67e74705SXin Li       // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
1069*67e74705SXin Li       // This will be addressed better with IPA.
1070*67e74705SXin Li       S = getPersistentStopSummary();
1071*67e74705SXin Li     } else if (FName == "NSMakeCollectable") {
1072*67e74705SXin Li       // Handle: id NSMakeCollectable(CFTypeRef)
1073*67e74705SXin Li       S = (RetTy->isObjCIdType())
1074*67e74705SXin Li           ? getUnarySummary(FT, cfmakecollectable)
1075*67e74705SXin Li           : getPersistentStopSummary();
1076*67e74705SXin Li       // The headers on OS X 10.8 use cf_consumed/ns_returns_retained,
1077*67e74705SXin Li       // but we can fully model NSMakeCollectable ourselves.
1078*67e74705SXin Li       AllowAnnotations = false;
1079*67e74705SXin Li     } else if (FName == "CFPlugInInstanceCreate") {
1080*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet());
1081*67e74705SXin Li     } else if (FName == "IOBSDNameMatching" ||
1082*67e74705SXin Li                FName == "IOServiceMatching" ||
1083*67e74705SXin Li                FName == "IOServiceNameMatching" ||
1084*67e74705SXin Li                FName == "IORegistryEntrySearchCFProperty" ||
1085*67e74705SXin Li                FName == "IORegistryEntryIDMatching" ||
1086*67e74705SXin Li                FName == "IOOpenFirmwarePathMatching") {
1087*67e74705SXin Li       // Part of <rdar://problem/6961230>. (IOKit)
1088*67e74705SXin Li       // This should be addressed using a API table.
1089*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
1090*67e74705SXin Li                                DoNothing, DoNothing);
1091*67e74705SXin Li     } else if (FName == "IOServiceGetMatchingService" ||
1092*67e74705SXin Li                FName == "IOServiceGetMatchingServices") {
1093*67e74705SXin Li       // FIXES: <rdar://problem/6326900>
1094*67e74705SXin Li       // This should be addressed using a API table.  This strcmp is also
1095*67e74705SXin Li       // a little gross, but there is no need to super optimize here.
1096*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
1097*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1098*67e74705SXin Li     } else if (FName == "IOServiceAddNotification" ||
1099*67e74705SXin Li                FName == "IOServiceAddMatchingNotification") {
1100*67e74705SXin Li       // Part of <rdar://problem/6961230>. (IOKit)
1101*67e74705SXin Li       // This should be addressed using a API table.
1102*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
1103*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1104*67e74705SXin Li     } else if (FName == "CVPixelBufferCreateWithBytes") {
1105*67e74705SXin Li       // FIXES: <rdar://problem/7283567>
1106*67e74705SXin Li       // Eventually this can be improved by recognizing that the pixel
1107*67e74705SXin Li       // buffer passed to CVPixelBufferCreateWithBytes is released via
1108*67e74705SXin Li       // a callback and doing full IPA to make sure this is done correctly.
1109*67e74705SXin Li       // FIXME: This function has an out parameter that returns an
1110*67e74705SXin Li       // allocated object.
1111*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
1112*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1113*67e74705SXin Li     } else if (FName == "CGBitmapContextCreateWithData") {
1114*67e74705SXin Li       // FIXES: <rdar://problem/7358899>
1115*67e74705SXin Li       // Eventually this can be improved by recognizing that 'releaseInfo'
1116*67e74705SXin Li       // passed to CGBitmapContextCreateWithData is released via
1117*67e74705SXin Li       // a callback and doing full IPA to make sure this is done correctly.
1118*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
1119*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
1120*67e74705SXin Li                                DoNothing, DoNothing);
1121*67e74705SXin Li     } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
1122*67e74705SXin Li       // FIXES: <rdar://problem/7283567>
1123*67e74705SXin Li       // Eventually this can be improved by recognizing that the pixel
1124*67e74705SXin Li       // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
1125*67e74705SXin Li       // via a callback and doing full IPA to make sure this is done
1126*67e74705SXin Li       // correctly.
1127*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
1128*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1129*67e74705SXin Li     } else if (FName == "dispatch_set_context" ||
1130*67e74705SXin Li                FName == "xpc_connection_set_context") {
1131*67e74705SXin Li       // <rdar://problem/11059275> - The analyzer currently doesn't have
1132*67e74705SXin Li       // a good way to reason about the finalizer function for libdispatch.
1133*67e74705SXin Li       // If we pass a context object that is memory managed, stop tracking it.
1134*67e74705SXin Li       // <rdar://problem/13783514> - Same problem, but for XPC.
1135*67e74705SXin Li       // FIXME: this hack should possibly go away once we can handle
1136*67e74705SXin Li       // libdispatch and XPC finalizers.
1137*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
1138*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1139*67e74705SXin Li     } else if (FName.startswith("NSLog")) {
1140*67e74705SXin Li       S = getDoNothingSummary();
1141*67e74705SXin Li     } else if (FName.startswith("NS") &&
1142*67e74705SXin Li                 (FName.find("Insert") != StringRef::npos)) {
1143*67e74705SXin Li       // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
1144*67e74705SXin Li       // be deallocated by NSMapRemove. (radar://11152419)
1145*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
1146*67e74705SXin Li       ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);
1147*67e74705SXin Li       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1148*67e74705SXin Li     }
1149*67e74705SXin Li 
1150*67e74705SXin Li     // Did we get a summary?
1151*67e74705SXin Li     if (S)
1152*67e74705SXin Li       break;
1153*67e74705SXin Li 
1154*67e74705SXin Li     if (RetTy->isPointerType()) {
1155*67e74705SXin Li       // For CoreFoundation ('CF') types.
1156*67e74705SXin Li       if (cocoa::isRefType(RetTy, "CF", FName)) {
1157*67e74705SXin Li         if (isRetain(FD, FName)) {
1158*67e74705SXin Li           S = getUnarySummary(FT, cfretain);
1159*67e74705SXin Li         } else if (isAutorelease(FD, FName)) {
1160*67e74705SXin Li           S = getUnarySummary(FT, cfautorelease);
1161*67e74705SXin Li           // The headers use cf_consumed, but we can fully model CFAutorelease
1162*67e74705SXin Li           // ourselves.
1163*67e74705SXin Li           AllowAnnotations = false;
1164*67e74705SXin Li         } else if (isMakeCollectable(FD, FName)) {
1165*67e74705SXin Li           S = getUnarySummary(FT, cfmakecollectable);
1166*67e74705SXin Li           AllowAnnotations = false;
1167*67e74705SXin Li         } else {
1168*67e74705SXin Li           S = getCFCreateGetRuleSummary(FD);
1169*67e74705SXin Li         }
1170*67e74705SXin Li 
1171*67e74705SXin Li         break;
1172*67e74705SXin Li       }
1173*67e74705SXin Li 
1174*67e74705SXin Li       // For CoreGraphics ('CG') types.
1175*67e74705SXin Li       if (cocoa::isRefType(RetTy, "CG", FName)) {
1176*67e74705SXin Li         if (isRetain(FD, FName))
1177*67e74705SXin Li           S = getUnarySummary(FT, cfretain);
1178*67e74705SXin Li         else
1179*67e74705SXin Li           S = getCFCreateGetRuleSummary(FD);
1180*67e74705SXin Li 
1181*67e74705SXin Li         break;
1182*67e74705SXin Li       }
1183*67e74705SXin Li 
1184*67e74705SXin Li       // For the Disk Arbitration API (DiskArbitration/DADisk.h)
1185*67e74705SXin Li       if (cocoa::isRefType(RetTy, "DADisk") ||
1186*67e74705SXin Li           cocoa::isRefType(RetTy, "DADissenter") ||
1187*67e74705SXin Li           cocoa::isRefType(RetTy, "DASessionRef")) {
1188*67e74705SXin Li         S = getCFCreateGetRuleSummary(FD);
1189*67e74705SXin Li         break;
1190*67e74705SXin Li       }
1191*67e74705SXin Li 
1192*67e74705SXin Li       if (FD->hasAttr<CFAuditedTransferAttr>()) {
1193*67e74705SXin Li         S = getCFCreateGetRuleSummary(FD);
1194*67e74705SXin Li         break;
1195*67e74705SXin Li       }
1196*67e74705SXin Li 
1197*67e74705SXin Li       break;
1198*67e74705SXin Li     }
1199*67e74705SXin Li 
1200*67e74705SXin Li     // Check for release functions, the only kind of functions that we care
1201*67e74705SXin Li     // about that don't return a pointer type.
1202*67e74705SXin Li     if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
1203*67e74705SXin Li       // Test for 'CGCF'.
1204*67e74705SXin Li       FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
1205*67e74705SXin Li 
1206*67e74705SXin Li       if (isRelease(FD, FName))
1207*67e74705SXin Li         S = getUnarySummary(FT, cfrelease);
1208*67e74705SXin Li       else {
1209*67e74705SXin Li         assert (ScratchArgs.isEmpty());
1210*67e74705SXin Li         // Remaining CoreFoundation and CoreGraphics functions.
1211*67e74705SXin Li         // We use to assume that they all strictly followed the ownership idiom
1212*67e74705SXin Li         // and that ownership cannot be transferred.  While this is technically
1213*67e74705SXin Li         // correct, many methods allow a tracked object to escape.  For example:
1214*67e74705SXin Li         //
1215*67e74705SXin Li         //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
1216*67e74705SXin Li         //   CFDictionaryAddValue(y, key, x);
1217*67e74705SXin Li         //   CFRelease(x);
1218*67e74705SXin Li         //   ... it is okay to use 'x' since 'y' has a reference to it
1219*67e74705SXin Li         //
1220*67e74705SXin Li         // We handle this and similar cases with the follow heuristic.  If the
1221*67e74705SXin Li         // function name contains "InsertValue", "SetValue", "AddValue",
1222*67e74705SXin Li         // "AppendValue", or "SetAttribute", then we assume that arguments may
1223*67e74705SXin Li         // "escape."  This means that something else holds on to the object,
1224*67e74705SXin Li         // allowing it be used even after its local retain count drops to 0.
1225*67e74705SXin Li         ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
1226*67e74705SXin Li                        StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
1227*67e74705SXin Li                        StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
1228*67e74705SXin Li                        StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
1229*67e74705SXin Li                        StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
1230*67e74705SXin Li                       ? MayEscape : DoNothing;
1231*67e74705SXin Li 
1232*67e74705SXin Li         S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
1233*67e74705SXin Li       }
1234*67e74705SXin Li     }
1235*67e74705SXin Li   }
1236*67e74705SXin Li   while (0);
1237*67e74705SXin Li 
1238*67e74705SXin Li   // If we got all the way here without any luck, use a default summary.
1239*67e74705SXin Li   if (!S)
1240*67e74705SXin Li     S = getDefaultSummary();
1241*67e74705SXin Li 
1242*67e74705SXin Li   // Annotations override defaults.
1243*67e74705SXin Li   if (AllowAnnotations)
1244*67e74705SXin Li     updateSummaryFromAnnotations(S, FD);
1245*67e74705SXin Li 
1246*67e74705SXin Li   FuncSummaries[FD] = S;
1247*67e74705SXin Li   return S;
1248*67e74705SXin Li }
1249*67e74705SXin Li 
1250*67e74705SXin Li const RetainSummary *
getCFCreateGetRuleSummary(const FunctionDecl * FD)1251*67e74705SXin Li RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
1252*67e74705SXin Li   if (coreFoundation::followsCreateRule(FD))
1253*67e74705SXin Li     return getCFSummaryCreateRule(FD);
1254*67e74705SXin Li 
1255*67e74705SXin Li   return getCFSummaryGetRule(FD);
1256*67e74705SXin Li }
1257*67e74705SXin Li 
1258*67e74705SXin Li const RetainSummary *
getUnarySummary(const FunctionType * FT,UnaryFuncKind func)1259*67e74705SXin Li RetainSummaryManager::getUnarySummary(const FunctionType* FT,
1260*67e74705SXin Li                                       UnaryFuncKind func) {
1261*67e74705SXin Li 
1262*67e74705SXin Li   // Sanity check that this is *really* a unary function.  This can
1263*67e74705SXin Li   // happen if people do weird things.
1264*67e74705SXin Li   const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
1265*67e74705SXin Li   if (!FTP || FTP->getNumParams() != 1)
1266*67e74705SXin Li     return getPersistentStopSummary();
1267*67e74705SXin Li 
1268*67e74705SXin Li   assert (ScratchArgs.isEmpty());
1269*67e74705SXin Li 
1270*67e74705SXin Li   ArgEffect Effect;
1271*67e74705SXin Li   switch (func) {
1272*67e74705SXin Li   case cfretain: Effect = IncRef; break;
1273*67e74705SXin Li   case cfrelease: Effect = DecRef; break;
1274*67e74705SXin Li   case cfautorelease: Effect = Autorelease; break;
1275*67e74705SXin Li   case cfmakecollectable: Effect = MakeCollectable; break;
1276*67e74705SXin Li   }
1277*67e74705SXin Li 
1278*67e74705SXin Li   ScratchArgs = AF.add(ScratchArgs, 0, Effect);
1279*67e74705SXin Li   return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1280*67e74705SXin Li }
1281*67e74705SXin Li 
1282*67e74705SXin Li const RetainSummary *
getCFSummaryCreateRule(const FunctionDecl * FD)1283*67e74705SXin Li RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
1284*67e74705SXin Li   assert (ScratchArgs.isEmpty());
1285*67e74705SXin Li 
1286*67e74705SXin Li   return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1287*67e74705SXin Li }
1288*67e74705SXin Li 
1289*67e74705SXin Li const RetainSummary *
getCFSummaryGetRule(const FunctionDecl * FD)1290*67e74705SXin Li RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
1291*67e74705SXin Li   assert (ScratchArgs.isEmpty());
1292*67e74705SXin Li   return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1293*67e74705SXin Li                               DoNothing, DoNothing);
1294*67e74705SXin Li }
1295*67e74705SXin Li 
1296*67e74705SXin Li //===----------------------------------------------------------------------===//
1297*67e74705SXin Li // Summary creation for Selectors.
1298*67e74705SXin Li //===----------------------------------------------------------------------===//
1299*67e74705SXin Li 
1300*67e74705SXin Li Optional<RetEffect>
getRetEffectFromAnnotations(QualType RetTy,const Decl * D)1301*67e74705SXin Li RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
1302*67e74705SXin Li                                                   const Decl *D) {
1303*67e74705SXin Li   if (cocoa::isCocoaObjectRef(RetTy)) {
1304*67e74705SXin Li     if (D->hasAttr<NSReturnsRetainedAttr>())
1305*67e74705SXin Li       return ObjCAllocRetE;
1306*67e74705SXin Li 
1307*67e74705SXin Li     if (D->hasAttr<NSReturnsNotRetainedAttr>() ||
1308*67e74705SXin Li         D->hasAttr<NSReturnsAutoreleasedAttr>())
1309*67e74705SXin Li       return RetEffect::MakeNotOwned(RetEffect::ObjC);
1310*67e74705SXin Li 
1311*67e74705SXin Li   } else if (!RetTy->isPointerType()) {
1312*67e74705SXin Li     return None;
1313*67e74705SXin Li   }
1314*67e74705SXin Li 
1315*67e74705SXin Li   if (D->hasAttr<CFReturnsRetainedAttr>())
1316*67e74705SXin Li     return RetEffect::MakeOwned(RetEffect::CF, true);
1317*67e74705SXin Li 
1318*67e74705SXin Li   if (D->hasAttr<CFReturnsNotRetainedAttr>())
1319*67e74705SXin Li     return RetEffect::MakeNotOwned(RetEffect::CF);
1320*67e74705SXin Li 
1321*67e74705SXin Li   return None;
1322*67e74705SXin Li }
1323*67e74705SXin Li 
1324*67e74705SXin Li void
updateSummaryFromAnnotations(const RetainSummary * & Summ,const FunctionDecl * FD)1325*67e74705SXin Li RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
1326*67e74705SXin Li                                                    const FunctionDecl *FD) {
1327*67e74705SXin Li   if (!FD)
1328*67e74705SXin Li     return;
1329*67e74705SXin Li 
1330*67e74705SXin Li   assert(Summ && "Must have a summary to add annotations to.");
1331*67e74705SXin Li   RetainSummaryTemplate Template(Summ, *this);
1332*67e74705SXin Li 
1333*67e74705SXin Li   // Effects on the parameters.
1334*67e74705SXin Li   unsigned parm_idx = 0;
1335*67e74705SXin Li   for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
1336*67e74705SXin Li          pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
1337*67e74705SXin Li     const ParmVarDecl *pd = *pi;
1338*67e74705SXin Li     if (pd->hasAttr<NSConsumedAttr>())
1339*67e74705SXin Li       Template->addArg(AF, parm_idx, DecRefMsg);
1340*67e74705SXin Li     else if (pd->hasAttr<CFConsumedAttr>())
1341*67e74705SXin Li       Template->addArg(AF, parm_idx, DecRef);
1342*67e74705SXin Li     else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
1343*67e74705SXin Li       QualType PointeeTy = pd->getType()->getPointeeType();
1344*67e74705SXin Li       if (!PointeeTy.isNull())
1345*67e74705SXin Li         if (coreFoundation::isCFObjectRef(PointeeTy))
1346*67e74705SXin Li           Template->addArg(AF, parm_idx, RetainedOutParameter);
1347*67e74705SXin Li     } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
1348*67e74705SXin Li       QualType PointeeTy = pd->getType()->getPointeeType();
1349*67e74705SXin Li       if (!PointeeTy.isNull())
1350*67e74705SXin Li         if (coreFoundation::isCFObjectRef(PointeeTy))
1351*67e74705SXin Li           Template->addArg(AF, parm_idx, UnretainedOutParameter);
1352*67e74705SXin Li     }
1353*67e74705SXin Li   }
1354*67e74705SXin Li 
1355*67e74705SXin Li   QualType RetTy = FD->getReturnType();
1356*67e74705SXin Li   if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
1357*67e74705SXin Li     Template->setRetEffect(*RetE);
1358*67e74705SXin Li }
1359*67e74705SXin Li 
1360*67e74705SXin Li void
updateSummaryFromAnnotations(const RetainSummary * & Summ,const ObjCMethodDecl * MD)1361*67e74705SXin Li RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
1362*67e74705SXin Li                                                    const ObjCMethodDecl *MD) {
1363*67e74705SXin Li   if (!MD)
1364*67e74705SXin Li     return;
1365*67e74705SXin Li 
1366*67e74705SXin Li   assert(Summ && "Must have a valid summary to add annotations to");
1367*67e74705SXin Li   RetainSummaryTemplate Template(Summ, *this);
1368*67e74705SXin Li 
1369*67e74705SXin Li   // Effects on the receiver.
1370*67e74705SXin Li   if (MD->hasAttr<NSConsumesSelfAttr>())
1371*67e74705SXin Li     Template->setReceiverEffect(DecRefMsg);
1372*67e74705SXin Li 
1373*67e74705SXin Li   // Effects on the parameters.
1374*67e74705SXin Li   unsigned parm_idx = 0;
1375*67e74705SXin Li   for (ObjCMethodDecl::param_const_iterator
1376*67e74705SXin Li          pi=MD->param_begin(), pe=MD->param_end();
1377*67e74705SXin Li        pi != pe; ++pi, ++parm_idx) {
1378*67e74705SXin Li     const ParmVarDecl *pd = *pi;
1379*67e74705SXin Li     if (pd->hasAttr<NSConsumedAttr>())
1380*67e74705SXin Li       Template->addArg(AF, parm_idx, DecRefMsg);
1381*67e74705SXin Li     else if (pd->hasAttr<CFConsumedAttr>()) {
1382*67e74705SXin Li       Template->addArg(AF, parm_idx, DecRef);
1383*67e74705SXin Li     } else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
1384*67e74705SXin Li       QualType PointeeTy = pd->getType()->getPointeeType();
1385*67e74705SXin Li       if (!PointeeTy.isNull())
1386*67e74705SXin Li         if (coreFoundation::isCFObjectRef(PointeeTy))
1387*67e74705SXin Li           Template->addArg(AF, parm_idx, RetainedOutParameter);
1388*67e74705SXin Li     } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
1389*67e74705SXin Li       QualType PointeeTy = pd->getType()->getPointeeType();
1390*67e74705SXin Li       if (!PointeeTy.isNull())
1391*67e74705SXin Li         if (coreFoundation::isCFObjectRef(PointeeTy))
1392*67e74705SXin Li           Template->addArg(AF, parm_idx, UnretainedOutParameter);
1393*67e74705SXin Li     }
1394*67e74705SXin Li   }
1395*67e74705SXin Li 
1396*67e74705SXin Li   QualType RetTy = MD->getReturnType();
1397*67e74705SXin Li   if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
1398*67e74705SXin Li     Template->setRetEffect(*RetE);
1399*67e74705SXin Li }
1400*67e74705SXin Li 
1401*67e74705SXin Li const RetainSummary *
getStandardMethodSummary(const ObjCMethodDecl * MD,Selector S,QualType RetTy)1402*67e74705SXin Li RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
1403*67e74705SXin Li                                                Selector S, QualType RetTy) {
1404*67e74705SXin Li   // Any special effects?
1405*67e74705SXin Li   ArgEffect ReceiverEff = DoNothing;
1406*67e74705SXin Li   RetEffect ResultEff = RetEffect::MakeNoRet();
1407*67e74705SXin Li 
1408*67e74705SXin Li   // Check the method family, and apply any default annotations.
1409*67e74705SXin Li   switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
1410*67e74705SXin Li     case OMF_None:
1411*67e74705SXin Li     case OMF_initialize:
1412*67e74705SXin Li     case OMF_performSelector:
1413*67e74705SXin Li       // Assume all Objective-C methods follow Cocoa Memory Management rules.
1414*67e74705SXin Li       // FIXME: Does the non-threaded performSelector family really belong here?
1415*67e74705SXin Li       // The selector could be, say, @selector(copy).
1416*67e74705SXin Li       if (cocoa::isCocoaObjectRef(RetTy))
1417*67e74705SXin Li         ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);
1418*67e74705SXin Li       else if (coreFoundation::isCFObjectRef(RetTy)) {
1419*67e74705SXin Li         // ObjCMethodDecl currently doesn't consider CF objects as valid return
1420*67e74705SXin Li         // values for alloc, new, copy, or mutableCopy, so we have to
1421*67e74705SXin Li         // double-check with the selector. This is ugly, but there aren't that
1422*67e74705SXin Li         // many Objective-C methods that return CF objects, right?
1423*67e74705SXin Li         if (MD) {
1424*67e74705SXin Li           switch (S.getMethodFamily()) {
1425*67e74705SXin Li           case OMF_alloc:
1426*67e74705SXin Li           case OMF_new:
1427*67e74705SXin Li           case OMF_copy:
1428*67e74705SXin Li           case OMF_mutableCopy:
1429*67e74705SXin Li             ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
1430*67e74705SXin Li             break;
1431*67e74705SXin Li           default:
1432*67e74705SXin Li             ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1433*67e74705SXin Li             break;
1434*67e74705SXin Li           }
1435*67e74705SXin Li         } else {
1436*67e74705SXin Li           ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1437*67e74705SXin Li         }
1438*67e74705SXin Li       }
1439*67e74705SXin Li       break;
1440*67e74705SXin Li     case OMF_init:
1441*67e74705SXin Li       ResultEff = ObjCInitRetE;
1442*67e74705SXin Li       ReceiverEff = DecRefMsg;
1443*67e74705SXin Li       break;
1444*67e74705SXin Li     case OMF_alloc:
1445*67e74705SXin Li     case OMF_new:
1446*67e74705SXin Li     case OMF_copy:
1447*67e74705SXin Li     case OMF_mutableCopy:
1448*67e74705SXin Li       if (cocoa::isCocoaObjectRef(RetTy))
1449*67e74705SXin Li         ResultEff = ObjCAllocRetE;
1450*67e74705SXin Li       else if (coreFoundation::isCFObjectRef(RetTy))
1451*67e74705SXin Li         ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
1452*67e74705SXin Li       break;
1453*67e74705SXin Li     case OMF_autorelease:
1454*67e74705SXin Li       ReceiverEff = Autorelease;
1455*67e74705SXin Li       break;
1456*67e74705SXin Li     case OMF_retain:
1457*67e74705SXin Li       ReceiverEff = IncRefMsg;
1458*67e74705SXin Li       break;
1459*67e74705SXin Li     case OMF_release:
1460*67e74705SXin Li       ReceiverEff = DecRefMsg;
1461*67e74705SXin Li       break;
1462*67e74705SXin Li     case OMF_dealloc:
1463*67e74705SXin Li       ReceiverEff = Dealloc;
1464*67e74705SXin Li       break;
1465*67e74705SXin Li     case OMF_self:
1466*67e74705SXin Li       // -self is handled specially by the ExprEngine to propagate the receiver.
1467*67e74705SXin Li       break;
1468*67e74705SXin Li     case OMF_retainCount:
1469*67e74705SXin Li     case OMF_finalize:
1470*67e74705SXin Li       // These methods don't return objects.
1471*67e74705SXin Li       break;
1472*67e74705SXin Li   }
1473*67e74705SXin Li 
1474*67e74705SXin Li   // If one of the arguments in the selector has the keyword 'delegate' we
1475*67e74705SXin Li   // should stop tracking the reference count for the receiver.  This is
1476*67e74705SXin Li   // because the reference count is quite possibly handled by a delegate
1477*67e74705SXin Li   // method.
1478*67e74705SXin Li   if (S.isKeywordSelector()) {
1479*67e74705SXin Li     for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
1480*67e74705SXin Li       StringRef Slot = S.getNameForSlot(i);
1481*67e74705SXin Li       if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
1482*67e74705SXin Li         if (ResultEff == ObjCInitRetE)
1483*67e74705SXin Li           ResultEff = RetEffect::MakeNoRetHard();
1484*67e74705SXin Li         else
1485*67e74705SXin Li           ReceiverEff = StopTrackingHard;
1486*67e74705SXin Li       }
1487*67e74705SXin Li     }
1488*67e74705SXin Li   }
1489*67e74705SXin Li 
1490*67e74705SXin Li   if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&
1491*67e74705SXin Li       ResultEff.getKind() == RetEffect::NoRet)
1492*67e74705SXin Li     return getDefaultSummary();
1493*67e74705SXin Li 
1494*67e74705SXin Li   return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);
1495*67e74705SXin Li }
1496*67e74705SXin Li 
1497*67e74705SXin Li const RetainSummary *
getInstanceMethodSummary(const ObjCMethodCall & Msg,ProgramStateRef State)1498*67e74705SXin Li RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
1499*67e74705SXin Li                                                ProgramStateRef State) {
1500*67e74705SXin Li   const ObjCInterfaceDecl *ReceiverClass = nullptr;
1501*67e74705SXin Li 
1502*67e74705SXin Li   // We do better tracking of the type of the object than the core ExprEngine.
1503*67e74705SXin Li   // See if we have its type in our private state.
1504*67e74705SXin Li   // FIXME: Eventually replace the use of state->get<RefBindings> with
1505*67e74705SXin Li   // a generic API for reasoning about the Objective-C types of symbolic
1506*67e74705SXin Li   // objects.
1507*67e74705SXin Li   SVal ReceiverV = Msg.getReceiverSVal();
1508*67e74705SXin Li   if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
1509*67e74705SXin Li     if (const RefVal *T = getRefBinding(State, Sym))
1510*67e74705SXin Li       if (const ObjCObjectPointerType *PT =
1511*67e74705SXin Li             T->getType()->getAs<ObjCObjectPointerType>())
1512*67e74705SXin Li         ReceiverClass = PT->getInterfaceDecl();
1513*67e74705SXin Li 
1514*67e74705SXin Li   // If we don't know what kind of object this is, fall back to its static type.
1515*67e74705SXin Li   if (!ReceiverClass)
1516*67e74705SXin Li     ReceiverClass = Msg.getReceiverInterface();
1517*67e74705SXin Li 
1518*67e74705SXin Li   // FIXME: The receiver could be a reference to a class, meaning that
1519*67e74705SXin Li   //  we should use the class method.
1520*67e74705SXin Li   // id x = [NSObject class];
1521*67e74705SXin Li   // [x performSelector:... withObject:... afterDelay:...];
1522*67e74705SXin Li   Selector S = Msg.getSelector();
1523*67e74705SXin Li   const ObjCMethodDecl *Method = Msg.getDecl();
1524*67e74705SXin Li   if (!Method && ReceiverClass)
1525*67e74705SXin Li     Method = ReceiverClass->getInstanceMethod(S);
1526*67e74705SXin Li 
1527*67e74705SXin Li   return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
1528*67e74705SXin Li                           ObjCMethodSummaries);
1529*67e74705SXin Li }
1530*67e74705SXin Li 
1531*67e74705SXin Li const RetainSummary *
getMethodSummary(Selector S,const ObjCInterfaceDecl * ID,const ObjCMethodDecl * MD,QualType RetTy,ObjCMethodSummariesTy & CachedSummaries)1532*67e74705SXin Li RetainSummaryManager::getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
1533*67e74705SXin Li                                        const ObjCMethodDecl *MD, QualType RetTy,
1534*67e74705SXin Li                                        ObjCMethodSummariesTy &CachedSummaries) {
1535*67e74705SXin Li 
1536*67e74705SXin Li   // Look up a summary in our summary cache.
1537*67e74705SXin Li   const RetainSummary *Summ = CachedSummaries.find(ID, S);
1538*67e74705SXin Li 
1539*67e74705SXin Li   if (!Summ) {
1540*67e74705SXin Li     Summ = getStandardMethodSummary(MD, S, RetTy);
1541*67e74705SXin Li 
1542*67e74705SXin Li     // Annotations override defaults.
1543*67e74705SXin Li     updateSummaryFromAnnotations(Summ, MD);
1544*67e74705SXin Li 
1545*67e74705SXin Li     // Memoize the summary.
1546*67e74705SXin Li     CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1547*67e74705SXin Li   }
1548*67e74705SXin Li 
1549*67e74705SXin Li   return Summ;
1550*67e74705SXin Li }
1551*67e74705SXin Li 
InitializeClassMethodSummaries()1552*67e74705SXin Li void RetainSummaryManager::InitializeClassMethodSummaries() {
1553*67e74705SXin Li   assert(ScratchArgs.isEmpty());
1554*67e74705SXin Li   // Create the [NSAssertionHandler currentHander] summary.
1555*67e74705SXin Li   addClassMethSummary("NSAssertionHandler", "currentHandler",
1556*67e74705SXin Li                 getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
1557*67e74705SXin Li 
1558*67e74705SXin Li   // Create the [NSAutoreleasePool addObject:] summary.
1559*67e74705SXin Li   ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
1560*67e74705SXin Li   addClassMethSummary("NSAutoreleasePool", "addObject",
1561*67e74705SXin Li                       getPersistentSummary(RetEffect::MakeNoRet(),
1562*67e74705SXin Li                                            DoNothing, Autorelease));
1563*67e74705SXin Li }
1564*67e74705SXin Li 
InitializeMethodSummaries()1565*67e74705SXin Li void RetainSummaryManager::InitializeMethodSummaries() {
1566*67e74705SXin Li 
1567*67e74705SXin Li   assert (ScratchArgs.isEmpty());
1568*67e74705SXin Li 
1569*67e74705SXin Li   // Create the "init" selector.  It just acts as a pass-through for the
1570*67e74705SXin Li   // receiver.
1571*67e74705SXin Li   const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
1572*67e74705SXin Li   addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
1573*67e74705SXin Li 
1574*67e74705SXin Li   // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
1575*67e74705SXin Li   // claims the receiver and returns a retained object.
1576*67e74705SXin Li   addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
1577*67e74705SXin Li                          InitSumm);
1578*67e74705SXin Li 
1579*67e74705SXin Li   // The next methods are allocators.
1580*67e74705SXin Li   const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1581*67e74705SXin Li   const RetainSummary *CFAllocSumm =
1582*67e74705SXin Li     getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1583*67e74705SXin Li 
1584*67e74705SXin Li   // Create the "retain" selector.
1585*67e74705SXin Li   RetEffect NoRet = RetEffect::MakeNoRet();
1586*67e74705SXin Li   const RetainSummary *Summ = getPersistentSummary(NoRet, IncRefMsg);
1587*67e74705SXin Li   addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
1588*67e74705SXin Li 
1589*67e74705SXin Li   // Create the "release" selector.
1590*67e74705SXin Li   Summ = getPersistentSummary(NoRet, DecRefMsg);
1591*67e74705SXin Li   addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
1592*67e74705SXin Li 
1593*67e74705SXin Li   // Create the -dealloc summary.
1594*67e74705SXin Li   Summ = getPersistentSummary(NoRet, Dealloc);
1595*67e74705SXin Li   addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
1596*67e74705SXin Li 
1597*67e74705SXin Li   // Create the "autorelease" selector.
1598*67e74705SXin Li   Summ = getPersistentSummary(NoRet, Autorelease);
1599*67e74705SXin Li   addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
1600*67e74705SXin Li 
1601*67e74705SXin Li   // For NSWindow, allocated objects are (initially) self-owned.
1602*67e74705SXin Li   // FIXME: For now we opt for false negatives with NSWindow, as these objects
1603*67e74705SXin Li   //  self-own themselves.  However, they only do this once they are displayed.
1604*67e74705SXin Li   //  Thus, we need to track an NSWindow's display status.
1605*67e74705SXin Li   //  This is tracked in <rdar://problem/6062711>.
1606*67e74705SXin Li   //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1607*67e74705SXin Li   const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1608*67e74705SXin Li                                                    StopTracking,
1609*67e74705SXin Li                                                    StopTracking);
1610*67e74705SXin Li 
1611*67e74705SXin Li   addClassMethSummary("NSWindow", "alloc", NoTrackYet);
1612*67e74705SXin Li 
1613*67e74705SXin Li   // For NSPanel (which subclasses NSWindow), allocated objects are not
1614*67e74705SXin Li   //  self-owned.
1615*67e74705SXin Li   // FIXME: For now we don't track NSPanels. object for the same reason
1616*67e74705SXin Li   //   as for NSWindow objects.
1617*67e74705SXin Li   addClassMethSummary("NSPanel", "alloc", NoTrackYet);
1618*67e74705SXin Li 
1619*67e74705SXin Li   // For NSNull, objects returned by +null are singletons that ignore
1620*67e74705SXin Li   // retain/release semantics.  Just don't track them.
1621*67e74705SXin Li   // <rdar://problem/12858915>
1622*67e74705SXin Li   addClassMethSummary("NSNull", "null", NoTrackYet);
1623*67e74705SXin Li 
1624*67e74705SXin Li   // Don't track allocated autorelease pools, as it is okay to prematurely
1625*67e74705SXin Li   // exit a method.
1626*67e74705SXin Li   addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
1627*67e74705SXin Li   addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
1628*67e74705SXin Li   addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
1629*67e74705SXin Li 
1630*67e74705SXin Li   // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
1631*67e74705SXin Li   addInstMethSummary("QCRenderer", AllocSumm,
1632*67e74705SXin Li                      "createSnapshotImageOfType", nullptr);
1633*67e74705SXin Li   addInstMethSummary("QCView", AllocSumm,
1634*67e74705SXin Li                      "createSnapshotImageOfType", nullptr);
1635*67e74705SXin Li 
1636*67e74705SXin Li   // Create summaries for CIContext, 'createCGImage' and
1637*67e74705SXin Li   // 'createCGLayerWithSize'.  These objects are CF objects, and are not
1638*67e74705SXin Li   // automatically garbage collected.
1639*67e74705SXin Li   addInstMethSummary("CIContext", CFAllocSumm,
1640*67e74705SXin Li                      "createCGImage", "fromRect", nullptr);
1641*67e74705SXin Li   addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
1642*67e74705SXin Li                      "format", "colorSpace", nullptr);
1643*67e74705SXin Li   addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info",
1644*67e74705SXin Li                      nullptr);
1645*67e74705SXin Li }
1646*67e74705SXin Li 
1647*67e74705SXin Li //===----------------------------------------------------------------------===//
1648*67e74705SXin Li // Error reporting.
1649*67e74705SXin Li //===----------------------------------------------------------------------===//
1650*67e74705SXin Li namespace {
1651*67e74705SXin Li   typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
1652*67e74705SXin Li     SummaryLogTy;
1653*67e74705SXin Li 
1654*67e74705SXin Li   //===-------------===//
1655*67e74705SXin Li   // Bug Descriptions. //
1656*67e74705SXin Li   //===-------------===//
1657*67e74705SXin Li 
1658*67e74705SXin Li   class CFRefBug : public BugType {
1659*67e74705SXin Li   protected:
CFRefBug(const CheckerBase * checker,StringRef name)1660*67e74705SXin Li     CFRefBug(const CheckerBase *checker, StringRef name)
1661*67e74705SXin Li         : BugType(checker, name, categories::MemoryCoreFoundationObjectiveC) {}
1662*67e74705SXin Li 
1663*67e74705SXin Li   public:
1664*67e74705SXin Li 
1665*67e74705SXin Li     // FIXME: Eventually remove.
1666*67e74705SXin Li     virtual const char *getDescription() const = 0;
1667*67e74705SXin Li 
isLeak() const1668*67e74705SXin Li     virtual bool isLeak() const { return false; }
1669*67e74705SXin Li   };
1670*67e74705SXin Li 
1671*67e74705SXin Li   class UseAfterRelease : public CFRefBug {
1672*67e74705SXin Li   public:
UseAfterRelease(const CheckerBase * checker)1673*67e74705SXin Li     UseAfterRelease(const CheckerBase *checker)
1674*67e74705SXin Li         : CFRefBug(checker, "Use-after-release") {}
1675*67e74705SXin Li 
getDescription() const1676*67e74705SXin Li     const char *getDescription() const override {
1677*67e74705SXin Li       return "Reference-counted object is used after it is released";
1678*67e74705SXin Li     }
1679*67e74705SXin Li   };
1680*67e74705SXin Li 
1681*67e74705SXin Li   class BadRelease : public CFRefBug {
1682*67e74705SXin Li   public:
BadRelease(const CheckerBase * checker)1683*67e74705SXin Li     BadRelease(const CheckerBase *checker) : CFRefBug(checker, "Bad release") {}
1684*67e74705SXin Li 
getDescription() const1685*67e74705SXin Li     const char *getDescription() const override {
1686*67e74705SXin Li       return "Incorrect decrement of the reference count of an object that is "
1687*67e74705SXin Li              "not owned at this point by the caller";
1688*67e74705SXin Li     }
1689*67e74705SXin Li   };
1690*67e74705SXin Li 
1691*67e74705SXin Li   class DeallocGC : public CFRefBug {
1692*67e74705SXin Li   public:
DeallocGC(const CheckerBase * checker)1693*67e74705SXin Li     DeallocGC(const CheckerBase *checker)
1694*67e74705SXin Li         : CFRefBug(checker, "-dealloc called while using garbage collection") {}
1695*67e74705SXin Li 
getDescription() const1696*67e74705SXin Li     const char *getDescription() const override {
1697*67e74705SXin Li       return "-dealloc called while using garbage collection";
1698*67e74705SXin Li     }
1699*67e74705SXin Li   };
1700*67e74705SXin Li 
1701*67e74705SXin Li   class DeallocNotOwned : public CFRefBug {
1702*67e74705SXin Li   public:
DeallocNotOwned(const CheckerBase * checker)1703*67e74705SXin Li     DeallocNotOwned(const CheckerBase *checker)
1704*67e74705SXin Li         : CFRefBug(checker, "-dealloc sent to non-exclusively owned object") {}
1705*67e74705SXin Li 
getDescription() const1706*67e74705SXin Li     const char *getDescription() const override {
1707*67e74705SXin Li       return "-dealloc sent to object that may be referenced elsewhere";
1708*67e74705SXin Li     }
1709*67e74705SXin Li   };
1710*67e74705SXin Li 
1711*67e74705SXin Li   class OverAutorelease : public CFRefBug {
1712*67e74705SXin Li   public:
OverAutorelease(const CheckerBase * checker)1713*67e74705SXin Li     OverAutorelease(const CheckerBase *checker)
1714*67e74705SXin Li         : CFRefBug(checker, "Object autoreleased too many times") {}
1715*67e74705SXin Li 
getDescription() const1716*67e74705SXin Li     const char *getDescription() const override {
1717*67e74705SXin Li       return "Object autoreleased too many times";
1718*67e74705SXin Li     }
1719*67e74705SXin Li   };
1720*67e74705SXin Li 
1721*67e74705SXin Li   class ReturnedNotOwnedForOwned : public CFRefBug {
1722*67e74705SXin Li   public:
ReturnedNotOwnedForOwned(const CheckerBase * checker)1723*67e74705SXin Li     ReturnedNotOwnedForOwned(const CheckerBase *checker)
1724*67e74705SXin Li         : CFRefBug(checker, "Method should return an owned object") {}
1725*67e74705SXin Li 
getDescription() const1726*67e74705SXin Li     const char *getDescription() const override {
1727*67e74705SXin Li       return "Object with a +0 retain count returned to caller where a +1 "
1728*67e74705SXin Li              "(owning) retain count is expected";
1729*67e74705SXin Li     }
1730*67e74705SXin Li   };
1731*67e74705SXin Li 
1732*67e74705SXin Li   class Leak : public CFRefBug {
1733*67e74705SXin Li   public:
Leak(const CheckerBase * checker,StringRef name)1734*67e74705SXin Li     Leak(const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
1735*67e74705SXin Li       // Leaks should not be reported if they are post-dominated by a sink.
1736*67e74705SXin Li       setSuppressOnSink(true);
1737*67e74705SXin Li     }
1738*67e74705SXin Li 
getDescription() const1739*67e74705SXin Li     const char *getDescription() const override { return ""; }
1740*67e74705SXin Li 
isLeak() const1741*67e74705SXin Li     bool isLeak() const override { return true; }
1742*67e74705SXin Li   };
1743*67e74705SXin Li 
1744*67e74705SXin Li   //===---------===//
1745*67e74705SXin Li   // Bug Reports.  //
1746*67e74705SXin Li   //===---------===//
1747*67e74705SXin Li 
1748*67e74705SXin Li   class CFRefReportVisitor : public BugReporterVisitorImpl<CFRefReportVisitor> {
1749*67e74705SXin Li   protected:
1750*67e74705SXin Li     SymbolRef Sym;
1751*67e74705SXin Li     const SummaryLogTy &SummaryLog;
1752*67e74705SXin Li     bool GCEnabled;
1753*67e74705SXin Li 
1754*67e74705SXin Li   public:
CFRefReportVisitor(SymbolRef sym,bool gcEnabled,const SummaryLogTy & log)1755*67e74705SXin Li     CFRefReportVisitor(SymbolRef sym, bool gcEnabled, const SummaryLogTy &log)
1756*67e74705SXin Li        : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
1757*67e74705SXin Li 
Profile(llvm::FoldingSetNodeID & ID) const1758*67e74705SXin Li     void Profile(llvm::FoldingSetNodeID &ID) const override {
1759*67e74705SXin Li       static int x = 0;
1760*67e74705SXin Li       ID.AddPointer(&x);
1761*67e74705SXin Li       ID.AddPointer(Sym);
1762*67e74705SXin Li     }
1763*67e74705SXin Li 
1764*67e74705SXin Li     PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
1765*67e74705SXin Li                                    const ExplodedNode *PrevN,
1766*67e74705SXin Li                                    BugReporterContext &BRC,
1767*67e74705SXin Li                                    BugReport &BR) override;
1768*67e74705SXin Li 
1769*67e74705SXin Li     std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
1770*67e74705SXin Li                                                     const ExplodedNode *N,
1771*67e74705SXin Li                                                     BugReport &BR) override;
1772*67e74705SXin Li   };
1773*67e74705SXin Li 
1774*67e74705SXin Li   class CFRefLeakReportVisitor : public CFRefReportVisitor {
1775*67e74705SXin Li   public:
CFRefLeakReportVisitor(SymbolRef sym,bool GCEnabled,const SummaryLogTy & log)1776*67e74705SXin Li     CFRefLeakReportVisitor(SymbolRef sym, bool GCEnabled,
1777*67e74705SXin Li                            const SummaryLogTy &log)
1778*67e74705SXin Li        : CFRefReportVisitor(sym, GCEnabled, log) {}
1779*67e74705SXin Li 
1780*67e74705SXin Li     std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
1781*67e74705SXin Li                                                     const ExplodedNode *N,
1782*67e74705SXin Li                                                     BugReport &BR) override;
1783*67e74705SXin Li 
clone() const1784*67e74705SXin Li     std::unique_ptr<BugReporterVisitor> clone() const override {
1785*67e74705SXin Li       // The curiously-recurring template pattern only works for one level of
1786*67e74705SXin Li       // subclassing. Rather than make a new template base for
1787*67e74705SXin Li       // CFRefReportVisitor, we simply override clone() to do the right thing.
1788*67e74705SXin Li       // This could be trouble someday if BugReporterVisitorImpl is ever
1789*67e74705SXin Li       // used for something else besides a convenient implementation of clone().
1790*67e74705SXin Li       return llvm::make_unique<CFRefLeakReportVisitor>(*this);
1791*67e74705SXin Li     }
1792*67e74705SXin Li   };
1793*67e74705SXin Li 
1794*67e74705SXin Li   class CFRefReport : public BugReport {
1795*67e74705SXin Li     void addGCModeDescription(const LangOptions &LOpts, bool GCEnabled);
1796*67e74705SXin Li 
1797*67e74705SXin Li   public:
CFRefReport(CFRefBug & D,const LangOptions & LOpts,bool GCEnabled,const SummaryLogTy & Log,ExplodedNode * n,SymbolRef sym,bool registerVisitor=true)1798*67e74705SXin Li     CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
1799*67e74705SXin Li                 const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
1800*67e74705SXin Li                 bool registerVisitor = true)
1801*67e74705SXin Li       : BugReport(D, D.getDescription(), n) {
1802*67e74705SXin Li       if (registerVisitor)
1803*67e74705SXin Li         addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1804*67e74705SXin Li       addGCModeDescription(LOpts, GCEnabled);
1805*67e74705SXin Li     }
1806*67e74705SXin Li 
CFRefReport(CFRefBug & D,const LangOptions & LOpts,bool GCEnabled,const SummaryLogTy & Log,ExplodedNode * n,SymbolRef sym,StringRef endText)1807*67e74705SXin Li     CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
1808*67e74705SXin Li                 const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
1809*67e74705SXin Li                 StringRef endText)
1810*67e74705SXin Li       : BugReport(D, D.getDescription(), endText, n) {
1811*67e74705SXin Li       addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1812*67e74705SXin Li       addGCModeDescription(LOpts, GCEnabled);
1813*67e74705SXin Li     }
1814*67e74705SXin Li 
getRanges()1815*67e74705SXin Li     llvm::iterator_range<ranges_iterator> getRanges() override {
1816*67e74705SXin Li       const CFRefBug& BugTy = static_cast<CFRefBug&>(getBugType());
1817*67e74705SXin Li       if (!BugTy.isLeak())
1818*67e74705SXin Li         return BugReport::getRanges();
1819*67e74705SXin Li       return llvm::make_range(ranges_iterator(), ranges_iterator());
1820*67e74705SXin Li     }
1821*67e74705SXin Li   };
1822*67e74705SXin Li 
1823*67e74705SXin Li   class CFRefLeakReport : public CFRefReport {
1824*67e74705SXin Li     const MemRegion* AllocBinding;
1825*67e74705SXin Li   public:
1826*67e74705SXin Li     CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
1827*67e74705SXin Li                     const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
1828*67e74705SXin Li                     CheckerContext &Ctx,
1829*67e74705SXin Li                     bool IncludeAllocationLine);
1830*67e74705SXin Li 
getLocation(const SourceManager & SM) const1831*67e74705SXin Li     PathDiagnosticLocation getLocation(const SourceManager &SM) const override {
1832*67e74705SXin Li       assert(Location.isValid());
1833*67e74705SXin Li       return Location;
1834*67e74705SXin Li     }
1835*67e74705SXin Li   };
1836*67e74705SXin Li } // end anonymous namespace
1837*67e74705SXin Li 
addGCModeDescription(const LangOptions & LOpts,bool GCEnabled)1838*67e74705SXin Li void CFRefReport::addGCModeDescription(const LangOptions &LOpts,
1839*67e74705SXin Li                                        bool GCEnabled) {
1840*67e74705SXin Li   const char *GCModeDescription = nullptr;
1841*67e74705SXin Li 
1842*67e74705SXin Li   switch (LOpts.getGC()) {
1843*67e74705SXin Li   case LangOptions::GCOnly:
1844*67e74705SXin Li     assert(GCEnabled);
1845*67e74705SXin Li     GCModeDescription = "Code is compiled to only use garbage collection";
1846*67e74705SXin Li     break;
1847*67e74705SXin Li 
1848*67e74705SXin Li   case LangOptions::NonGC:
1849*67e74705SXin Li     assert(!GCEnabled);
1850*67e74705SXin Li     GCModeDescription = "Code is compiled to use reference counts";
1851*67e74705SXin Li     break;
1852*67e74705SXin Li 
1853*67e74705SXin Li   case LangOptions::HybridGC:
1854*67e74705SXin Li     if (GCEnabled) {
1855*67e74705SXin Li       GCModeDescription = "Code is compiled to use either garbage collection "
1856*67e74705SXin Li                           "(GC) or reference counts (non-GC).  The bug occurs "
1857*67e74705SXin Li                           "with GC enabled";
1858*67e74705SXin Li       break;
1859*67e74705SXin Li     } else {
1860*67e74705SXin Li       GCModeDescription = "Code is compiled to use either garbage collection "
1861*67e74705SXin Li                           "(GC) or reference counts (non-GC).  The bug occurs "
1862*67e74705SXin Li                           "in non-GC mode";
1863*67e74705SXin Li       break;
1864*67e74705SXin Li     }
1865*67e74705SXin Li   }
1866*67e74705SXin Li 
1867*67e74705SXin Li   assert(GCModeDescription && "invalid/unknown GC mode");
1868*67e74705SXin Li   addExtraText(GCModeDescription);
1869*67e74705SXin Li }
1870*67e74705SXin Li 
isNumericLiteralExpression(const Expr * E)1871*67e74705SXin Li static bool isNumericLiteralExpression(const Expr *E) {
1872*67e74705SXin Li   // FIXME: This set of cases was copied from SemaExprObjC.
1873*67e74705SXin Li   return isa<IntegerLiteral>(E) ||
1874*67e74705SXin Li          isa<CharacterLiteral>(E) ||
1875*67e74705SXin Li          isa<FloatingLiteral>(E) ||
1876*67e74705SXin Li          isa<ObjCBoolLiteralExpr>(E) ||
1877*67e74705SXin Li          isa<CXXBoolLiteralExpr>(E);
1878*67e74705SXin Li }
1879*67e74705SXin Li 
1880*67e74705SXin Li /// Returns true if this stack frame is for an Objective-C method that is a
1881*67e74705SXin Li /// property getter or setter whose body has been synthesized by the analyzer.
isSynthesizedAccessor(const StackFrameContext * SFC)1882*67e74705SXin Li static bool isSynthesizedAccessor(const StackFrameContext *SFC) {
1883*67e74705SXin Li   auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
1884*67e74705SXin Li   if (!Method || !Method->isPropertyAccessor())
1885*67e74705SXin Li     return false;
1886*67e74705SXin Li 
1887*67e74705SXin Li   return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
1888*67e74705SXin Li }
1889*67e74705SXin Li 
VisitNode(const ExplodedNode * N,const ExplodedNode * PrevN,BugReporterContext & BRC,BugReport & BR)1890*67e74705SXin Li PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
1891*67e74705SXin Li                                                    const ExplodedNode *PrevN,
1892*67e74705SXin Li                                                    BugReporterContext &BRC,
1893*67e74705SXin Li                                                    BugReport &BR) {
1894*67e74705SXin Li   // FIXME: We will eventually need to handle non-statement-based events
1895*67e74705SXin Li   // (__attribute__((cleanup))).
1896*67e74705SXin Li   if (!N->getLocation().getAs<StmtPoint>())
1897*67e74705SXin Li     return nullptr;
1898*67e74705SXin Li 
1899*67e74705SXin Li   // Check if the type state has changed.
1900*67e74705SXin Li   ProgramStateRef PrevSt = PrevN->getState();
1901*67e74705SXin Li   ProgramStateRef CurrSt = N->getState();
1902*67e74705SXin Li   const LocationContext *LCtx = N->getLocationContext();
1903*67e74705SXin Li 
1904*67e74705SXin Li   const RefVal* CurrT = getRefBinding(CurrSt, Sym);
1905*67e74705SXin Li   if (!CurrT) return nullptr;
1906*67e74705SXin Li 
1907*67e74705SXin Li   const RefVal &CurrV = *CurrT;
1908*67e74705SXin Li   const RefVal *PrevT = getRefBinding(PrevSt, Sym);
1909*67e74705SXin Li 
1910*67e74705SXin Li   // Create a string buffer to constain all the useful things we want
1911*67e74705SXin Li   // to tell the user.
1912*67e74705SXin Li   std::string sbuf;
1913*67e74705SXin Li   llvm::raw_string_ostream os(sbuf);
1914*67e74705SXin Li 
1915*67e74705SXin Li   // This is the allocation site since the previous node had no bindings
1916*67e74705SXin Li   // for this symbol.
1917*67e74705SXin Li   if (!PrevT) {
1918*67e74705SXin Li     const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
1919*67e74705SXin Li 
1920*67e74705SXin Li     if (isa<ObjCIvarRefExpr>(S) &&
1921*67e74705SXin Li         isSynthesizedAccessor(LCtx->getCurrentStackFrame())) {
1922*67e74705SXin Li       S = LCtx->getCurrentStackFrame()->getCallSite();
1923*67e74705SXin Li     }
1924*67e74705SXin Li 
1925*67e74705SXin Li     if (isa<ObjCArrayLiteral>(S)) {
1926*67e74705SXin Li       os << "NSArray literal is an object with a +0 retain count";
1927*67e74705SXin Li     }
1928*67e74705SXin Li     else if (isa<ObjCDictionaryLiteral>(S)) {
1929*67e74705SXin Li       os << "NSDictionary literal is an object with a +0 retain count";
1930*67e74705SXin Li     }
1931*67e74705SXin Li     else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
1932*67e74705SXin Li       if (isNumericLiteralExpression(BL->getSubExpr()))
1933*67e74705SXin Li         os << "NSNumber literal is an object with a +0 retain count";
1934*67e74705SXin Li       else {
1935*67e74705SXin Li         const ObjCInterfaceDecl *BoxClass = nullptr;
1936*67e74705SXin Li         if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
1937*67e74705SXin Li           BoxClass = Method->getClassInterface();
1938*67e74705SXin Li 
1939*67e74705SXin Li         // We should always be able to find the boxing class interface,
1940*67e74705SXin Li         // but consider this future-proofing.
1941*67e74705SXin Li         if (BoxClass)
1942*67e74705SXin Li           os << *BoxClass << " b";
1943*67e74705SXin Li         else
1944*67e74705SXin Li           os << "B";
1945*67e74705SXin Li 
1946*67e74705SXin Li         os << "oxed expression produces an object with a +0 retain count";
1947*67e74705SXin Li       }
1948*67e74705SXin Li     }
1949*67e74705SXin Li     else if (isa<ObjCIvarRefExpr>(S)) {
1950*67e74705SXin Li       os << "Object loaded from instance variable";
1951*67e74705SXin Li     }
1952*67e74705SXin Li     else {
1953*67e74705SXin Li       if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1954*67e74705SXin Li         // Get the name of the callee (if it is available).
1955*67e74705SXin Li         SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
1956*67e74705SXin Li         if (const FunctionDecl *FD = X.getAsFunctionDecl())
1957*67e74705SXin Li           os << "Call to function '" << *FD << '\'';
1958*67e74705SXin Li         else
1959*67e74705SXin Li           os << "function call";
1960*67e74705SXin Li       }
1961*67e74705SXin Li       else {
1962*67e74705SXin Li         assert(isa<ObjCMessageExpr>(S));
1963*67e74705SXin Li         CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
1964*67e74705SXin Li         CallEventRef<ObjCMethodCall> Call
1965*67e74705SXin Li           = Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
1966*67e74705SXin Li 
1967*67e74705SXin Li         switch (Call->getMessageKind()) {
1968*67e74705SXin Li         case OCM_Message:
1969*67e74705SXin Li           os << "Method";
1970*67e74705SXin Li           break;
1971*67e74705SXin Li         case OCM_PropertyAccess:
1972*67e74705SXin Li           os << "Property";
1973*67e74705SXin Li           break;
1974*67e74705SXin Li         case OCM_Subscript:
1975*67e74705SXin Li           os << "Subscript";
1976*67e74705SXin Li           break;
1977*67e74705SXin Li         }
1978*67e74705SXin Li       }
1979*67e74705SXin Li 
1980*67e74705SXin Li       if (CurrV.getObjKind() == RetEffect::CF) {
1981*67e74705SXin Li         os << " returns a Core Foundation object with a ";
1982*67e74705SXin Li       }
1983*67e74705SXin Li       else {
1984*67e74705SXin Li         assert (CurrV.getObjKind() == RetEffect::ObjC);
1985*67e74705SXin Li         os << " returns an Objective-C object with a ";
1986*67e74705SXin Li       }
1987*67e74705SXin Li 
1988*67e74705SXin Li       if (CurrV.isOwned()) {
1989*67e74705SXin Li         os << "+1 retain count";
1990*67e74705SXin Li 
1991*67e74705SXin Li         if (GCEnabled) {
1992*67e74705SXin Li           assert(CurrV.getObjKind() == RetEffect::CF);
1993*67e74705SXin Li           os << ".  "
1994*67e74705SXin Li           "Core Foundation objects are not automatically garbage collected.";
1995*67e74705SXin Li         }
1996*67e74705SXin Li       }
1997*67e74705SXin Li       else {
1998*67e74705SXin Li         assert (CurrV.isNotOwned());
1999*67e74705SXin Li         os << "+0 retain count";
2000*67e74705SXin Li       }
2001*67e74705SXin Li     }
2002*67e74705SXin Li 
2003*67e74705SXin Li     PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
2004*67e74705SXin Li                                   N->getLocationContext());
2005*67e74705SXin Li     return new PathDiagnosticEventPiece(Pos, os.str());
2006*67e74705SXin Li   }
2007*67e74705SXin Li 
2008*67e74705SXin Li   // Gather up the effects that were performed on the object at this
2009*67e74705SXin Li   // program point
2010*67e74705SXin Li   SmallVector<ArgEffect, 2> AEffects;
2011*67e74705SXin Li 
2012*67e74705SXin Li   const ExplodedNode *OrigNode = BRC.getNodeResolver().getOriginalNode(N);
2013*67e74705SXin Li   if (const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
2014*67e74705SXin Li     // We only have summaries attached to nodes after evaluating CallExpr and
2015*67e74705SXin Li     // ObjCMessageExprs.
2016*67e74705SXin Li     const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
2017*67e74705SXin Li 
2018*67e74705SXin Li     if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2019*67e74705SXin Li       // Iterate through the parameter expressions and see if the symbol
2020*67e74705SXin Li       // was ever passed as an argument.
2021*67e74705SXin Li       unsigned i = 0;
2022*67e74705SXin Li 
2023*67e74705SXin Li       for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
2024*67e74705SXin Li            AI!=AE; ++AI, ++i) {
2025*67e74705SXin Li 
2026*67e74705SXin Li         // Retrieve the value of the argument.  Is it the symbol
2027*67e74705SXin Li         // we are interested in?
2028*67e74705SXin Li         if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
2029*67e74705SXin Li           continue;
2030*67e74705SXin Li 
2031*67e74705SXin Li         // We have an argument.  Get the effect!
2032*67e74705SXin Li         AEffects.push_back(Summ->getArg(i));
2033*67e74705SXin Li       }
2034*67e74705SXin Li     }
2035*67e74705SXin Li     else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
2036*67e74705SXin Li       if (const Expr *receiver = ME->getInstanceReceiver())
2037*67e74705SXin Li         if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
2038*67e74705SXin Li               .getAsLocSymbol() == Sym) {
2039*67e74705SXin Li           // The symbol we are tracking is the receiver.
2040*67e74705SXin Li           AEffects.push_back(Summ->getReceiverEffect());
2041*67e74705SXin Li         }
2042*67e74705SXin Li     }
2043*67e74705SXin Li   }
2044*67e74705SXin Li 
2045*67e74705SXin Li   do {
2046*67e74705SXin Li     // Get the previous type state.
2047*67e74705SXin Li     RefVal PrevV = *PrevT;
2048*67e74705SXin Li 
2049*67e74705SXin Li     // Specially handle -dealloc.
2050*67e74705SXin Li     if (!GCEnabled && std::find(AEffects.begin(), AEffects.end(), Dealloc) !=
2051*67e74705SXin Li                           AEffects.end()) {
2052*67e74705SXin Li       // Determine if the object's reference count was pushed to zero.
2053*67e74705SXin Li       assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
2054*67e74705SXin Li       // We may not have transitioned to 'release' if we hit an error.
2055*67e74705SXin Li       // This case is handled elsewhere.
2056*67e74705SXin Li       if (CurrV.getKind() == RefVal::Released) {
2057*67e74705SXin Li         assert(CurrV.getCombinedCounts() == 0);
2058*67e74705SXin Li         os << "Object released by directly sending the '-dealloc' message";
2059*67e74705SXin Li         break;
2060*67e74705SXin Li       }
2061*67e74705SXin Li     }
2062*67e74705SXin Li 
2063*67e74705SXin Li     // Specially handle CFMakeCollectable and friends.
2064*67e74705SXin Li     if (std::find(AEffects.begin(), AEffects.end(), MakeCollectable) !=
2065*67e74705SXin Li         AEffects.end()) {
2066*67e74705SXin Li       // Get the name of the function.
2067*67e74705SXin Li       const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
2068*67e74705SXin Li       SVal X =
2069*67e74705SXin Li         CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
2070*67e74705SXin Li       const FunctionDecl *FD = X.getAsFunctionDecl();
2071*67e74705SXin Li 
2072*67e74705SXin Li       if (GCEnabled) {
2073*67e74705SXin Li         // Determine if the object's reference count was pushed to zero.
2074*67e74705SXin Li         assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
2075*67e74705SXin Li 
2076*67e74705SXin Li         os << "In GC mode a call to '" << *FD
2077*67e74705SXin Li         <<  "' decrements an object's retain count and registers the "
2078*67e74705SXin Li         "object with the garbage collector. ";
2079*67e74705SXin Li 
2080*67e74705SXin Li         if (CurrV.getKind() == RefVal::Released) {
2081*67e74705SXin Li           assert(CurrV.getCount() == 0);
2082*67e74705SXin Li           os << "Since it now has a 0 retain count the object can be "
2083*67e74705SXin Li           "automatically collected by the garbage collector.";
2084*67e74705SXin Li         }
2085*67e74705SXin Li         else
2086*67e74705SXin Li           os << "An object must have a 0 retain count to be garbage collected. "
2087*67e74705SXin Li           "After this call its retain count is +" << CurrV.getCount()
2088*67e74705SXin Li           << '.';
2089*67e74705SXin Li       }
2090*67e74705SXin Li       else
2091*67e74705SXin Li         os << "When GC is not enabled a call to '" << *FD
2092*67e74705SXin Li         << "' has no effect on its argument.";
2093*67e74705SXin Li 
2094*67e74705SXin Li       // Nothing more to say.
2095*67e74705SXin Li       break;
2096*67e74705SXin Li     }
2097*67e74705SXin Li 
2098*67e74705SXin Li     // Determine if the typestate has changed.
2099*67e74705SXin Li     if (!PrevV.hasSameState(CurrV))
2100*67e74705SXin Li       switch (CurrV.getKind()) {
2101*67e74705SXin Li         case RefVal::Owned:
2102*67e74705SXin Li         case RefVal::NotOwned:
2103*67e74705SXin Li           if (PrevV.getCount() == CurrV.getCount()) {
2104*67e74705SXin Li             // Did an autorelease message get sent?
2105*67e74705SXin Li             if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2106*67e74705SXin Li               return nullptr;
2107*67e74705SXin Li 
2108*67e74705SXin Li             assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2109*67e74705SXin Li             os << "Object autoreleased";
2110*67e74705SXin Li             break;
2111*67e74705SXin Li           }
2112*67e74705SXin Li 
2113*67e74705SXin Li           if (PrevV.getCount() > CurrV.getCount())
2114*67e74705SXin Li             os << "Reference count decremented.";
2115*67e74705SXin Li           else
2116*67e74705SXin Li             os << "Reference count incremented.";
2117*67e74705SXin Li 
2118*67e74705SXin Li           if (unsigned Count = CurrV.getCount())
2119*67e74705SXin Li             os << " The object now has a +" << Count << " retain count.";
2120*67e74705SXin Li 
2121*67e74705SXin Li           if (PrevV.getKind() == RefVal::Released) {
2122*67e74705SXin Li             assert(GCEnabled && CurrV.getCount() > 0);
2123*67e74705SXin Li             os << " The object is not eligible for garbage collection until "
2124*67e74705SXin Li                   "the retain count reaches 0 again.";
2125*67e74705SXin Li           }
2126*67e74705SXin Li 
2127*67e74705SXin Li           break;
2128*67e74705SXin Li 
2129*67e74705SXin Li         case RefVal::Released:
2130*67e74705SXin Li           if (CurrV.getIvarAccessHistory() ==
2131*67e74705SXin Li                 RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
2132*67e74705SXin Li               CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
2133*67e74705SXin Li             os << "Strong instance variable relinquished. ";
2134*67e74705SXin Li           }
2135*67e74705SXin Li           os << "Object released.";
2136*67e74705SXin Li           break;
2137*67e74705SXin Li 
2138*67e74705SXin Li         case RefVal::ReturnedOwned:
2139*67e74705SXin Li           // Autoreleases can be applied after marking a node ReturnedOwned.
2140*67e74705SXin Li           if (CurrV.getAutoreleaseCount())
2141*67e74705SXin Li             return nullptr;
2142*67e74705SXin Li 
2143*67e74705SXin Li           os << "Object returned to caller as an owning reference (single "
2144*67e74705SXin Li                 "retain count transferred to caller)";
2145*67e74705SXin Li           break;
2146*67e74705SXin Li 
2147*67e74705SXin Li         case RefVal::ReturnedNotOwned:
2148*67e74705SXin Li           os << "Object returned to caller with a +0 retain count";
2149*67e74705SXin Li           break;
2150*67e74705SXin Li 
2151*67e74705SXin Li         default:
2152*67e74705SXin Li           return nullptr;
2153*67e74705SXin Li       }
2154*67e74705SXin Li 
2155*67e74705SXin Li     // Emit any remaining diagnostics for the argument effects (if any).
2156*67e74705SXin Li     for (SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
2157*67e74705SXin Li          E=AEffects.end(); I != E; ++I) {
2158*67e74705SXin Li 
2159*67e74705SXin Li       // A bunch of things have alternate behavior under GC.
2160*67e74705SXin Li       if (GCEnabled)
2161*67e74705SXin Li         switch (*I) {
2162*67e74705SXin Li           default: break;
2163*67e74705SXin Li           case Autorelease:
2164*67e74705SXin Li             os << "In GC mode an 'autorelease' has no effect.";
2165*67e74705SXin Li             continue;
2166*67e74705SXin Li           case IncRefMsg:
2167*67e74705SXin Li             os << "In GC mode the 'retain' message has no effect.";
2168*67e74705SXin Li             continue;
2169*67e74705SXin Li           case DecRefMsg:
2170*67e74705SXin Li             os << "In GC mode the 'release' message has no effect.";
2171*67e74705SXin Li             continue;
2172*67e74705SXin Li         }
2173*67e74705SXin Li     }
2174*67e74705SXin Li   } while (0);
2175*67e74705SXin Li 
2176*67e74705SXin Li   if (os.str().empty())
2177*67e74705SXin Li     return nullptr; // We have nothing to say!
2178*67e74705SXin Li 
2179*67e74705SXin Li   const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
2180*67e74705SXin Li   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
2181*67e74705SXin Li                                 N->getLocationContext());
2182*67e74705SXin Li   PathDiagnosticPiece *P = new PathDiagnosticEventPiece(Pos, os.str());
2183*67e74705SXin Li 
2184*67e74705SXin Li   // Add the range by scanning the children of the statement for any bindings
2185*67e74705SXin Li   // to Sym.
2186*67e74705SXin Li   for (const Stmt *Child : S->children())
2187*67e74705SXin Li     if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
2188*67e74705SXin Li       if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
2189*67e74705SXin Li         P->addRange(Exp->getSourceRange());
2190*67e74705SXin Li         break;
2191*67e74705SXin Li       }
2192*67e74705SXin Li 
2193*67e74705SXin Li   return P;
2194*67e74705SXin Li }
2195*67e74705SXin Li 
2196*67e74705SXin Li namespace {
2197*67e74705SXin Li // Find the first node in the current function context that referred to the
2198*67e74705SXin Li // tracked symbol and the memory location that value was stored to. Note, the
2199*67e74705SXin Li // value is only reported if the allocation occurred in the same function as
2200*67e74705SXin Li // the leak. The function can also return a location context, which should be
2201*67e74705SXin Li // treated as interesting.
2202*67e74705SXin Li struct AllocationInfo {
2203*67e74705SXin Li   const ExplodedNode* N;
2204*67e74705SXin Li   const MemRegion *R;
2205*67e74705SXin Li   const LocationContext *InterestingMethodContext;
AllocationInfo__anon5ac500470711::AllocationInfo2206*67e74705SXin Li   AllocationInfo(const ExplodedNode *InN,
2207*67e74705SXin Li                  const MemRegion *InR,
2208*67e74705SXin Li                  const LocationContext *InInterestingMethodContext) :
2209*67e74705SXin Li     N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2210*67e74705SXin Li };
2211*67e74705SXin Li } // end anonymous namespace
2212*67e74705SXin Li 
2213*67e74705SXin Li static AllocationInfo
GetAllocationSite(ProgramStateManager & StateMgr,const ExplodedNode * N,SymbolRef Sym)2214*67e74705SXin Li GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
2215*67e74705SXin Li                   SymbolRef Sym) {
2216*67e74705SXin Li   const ExplodedNode *AllocationNode = N;
2217*67e74705SXin Li   const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
2218*67e74705SXin Li   const MemRegion *FirstBinding = nullptr;
2219*67e74705SXin Li   const LocationContext *LeakContext = N->getLocationContext();
2220*67e74705SXin Li 
2221*67e74705SXin Li   // The location context of the init method called on the leaked object, if
2222*67e74705SXin Li   // available.
2223*67e74705SXin Li   const LocationContext *InitMethodContext = nullptr;
2224*67e74705SXin Li 
2225*67e74705SXin Li   while (N) {
2226*67e74705SXin Li     ProgramStateRef St = N->getState();
2227*67e74705SXin Li     const LocationContext *NContext = N->getLocationContext();
2228*67e74705SXin Li 
2229*67e74705SXin Li     if (!getRefBinding(St, Sym))
2230*67e74705SXin Li       break;
2231*67e74705SXin Li 
2232*67e74705SXin Li     StoreManager::FindUniqueBinding FB(Sym);
2233*67e74705SXin Li     StateMgr.iterBindings(St, FB);
2234*67e74705SXin Li 
2235*67e74705SXin Li     if (FB) {
2236*67e74705SXin Li       const MemRegion *R = FB.getRegion();
2237*67e74705SXin Li       const VarRegion *VR = R->getBaseRegion()->getAs<VarRegion>();
2238*67e74705SXin Li       // Do not show local variables belonging to a function other than
2239*67e74705SXin Li       // where the error is reported.
2240*67e74705SXin Li       if (!VR || VR->getStackFrame() == LeakContext->getCurrentStackFrame())
2241*67e74705SXin Li         FirstBinding = R;
2242*67e74705SXin Li     }
2243*67e74705SXin Li 
2244*67e74705SXin Li     // AllocationNode is the last node in which the symbol was tracked.
2245*67e74705SXin Li     AllocationNode = N;
2246*67e74705SXin Li 
2247*67e74705SXin Li     // AllocationNodeInCurrentContext, is the last node in the current or
2248*67e74705SXin Li     // parent context in which the symbol was tracked.
2249*67e74705SXin Li     //
2250*67e74705SXin Li     // Note that the allocation site might be in the parent conext. For example,
2251*67e74705SXin Li     // the case where an allocation happens in a block that captures a reference
2252*67e74705SXin Li     // to it and that reference is overwritten/dropped by another call to
2253*67e74705SXin Li     // the block.
2254*67e74705SXin Li     if (NContext == LeakContext || NContext->isParentOf(LeakContext))
2255*67e74705SXin Li       AllocationNodeInCurrentOrParentContext = N;
2256*67e74705SXin Li 
2257*67e74705SXin Li     // Find the last init that was called on the given symbol and store the
2258*67e74705SXin Li     // init method's location context.
2259*67e74705SXin Li     if (!InitMethodContext)
2260*67e74705SXin Li       if (Optional<CallEnter> CEP = N->getLocation().getAs<CallEnter>()) {
2261*67e74705SXin Li         const Stmt *CE = CEP->getCallExpr();
2262*67e74705SXin Li         if (const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2263*67e74705SXin Li           const Stmt *RecExpr = ME->getInstanceReceiver();
2264*67e74705SXin Li           if (RecExpr) {
2265*67e74705SXin Li             SVal RecV = St->getSVal(RecExpr, NContext);
2266*67e74705SXin Li             if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
2267*67e74705SXin Li               InitMethodContext = CEP->getCalleeContext();
2268*67e74705SXin Li           }
2269*67e74705SXin Li         }
2270*67e74705SXin Li       }
2271*67e74705SXin Li 
2272*67e74705SXin Li     N = N->pred_empty() ? nullptr : *(N->pred_begin());
2273*67e74705SXin Li   }
2274*67e74705SXin Li 
2275*67e74705SXin Li   // If we are reporting a leak of the object that was allocated with alloc,
2276*67e74705SXin Li   // mark its init method as interesting.
2277*67e74705SXin Li   const LocationContext *InterestingMethodContext = nullptr;
2278*67e74705SXin Li   if (InitMethodContext) {
2279*67e74705SXin Li     const ProgramPoint AllocPP = AllocationNode->getLocation();
2280*67e74705SXin Li     if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
2281*67e74705SXin Li       if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
2282*67e74705SXin Li         if (ME->getMethodFamily() == OMF_alloc)
2283*67e74705SXin Li           InterestingMethodContext = InitMethodContext;
2284*67e74705SXin Li   }
2285*67e74705SXin Li 
2286*67e74705SXin Li   // If allocation happened in a function different from the leak node context,
2287*67e74705SXin Li   // do not report the binding.
2288*67e74705SXin Li   assert(N && "Could not find allocation node");
2289*67e74705SXin Li   if (N->getLocationContext() != LeakContext) {
2290*67e74705SXin Li     FirstBinding = nullptr;
2291*67e74705SXin Li   }
2292*67e74705SXin Li 
2293*67e74705SXin Li   return AllocationInfo(AllocationNodeInCurrentOrParentContext,
2294*67e74705SXin Li                         FirstBinding,
2295*67e74705SXin Li                         InterestingMethodContext);
2296*67e74705SXin Li }
2297*67e74705SXin Li 
2298*67e74705SXin Li std::unique_ptr<PathDiagnosticPiece>
getEndPath(BugReporterContext & BRC,const ExplodedNode * EndN,BugReport & BR)2299*67e74705SXin Li CFRefReportVisitor::getEndPath(BugReporterContext &BRC,
2300*67e74705SXin Li                                const ExplodedNode *EndN, BugReport &BR) {
2301*67e74705SXin Li   BR.markInteresting(Sym);
2302*67e74705SXin Li   return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
2303*67e74705SXin Li }
2304*67e74705SXin Li 
2305*67e74705SXin Li std::unique_ptr<PathDiagnosticPiece>
getEndPath(BugReporterContext & BRC,const ExplodedNode * EndN,BugReport & BR)2306*67e74705SXin Li CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
2307*67e74705SXin Li                                    const ExplodedNode *EndN, BugReport &BR) {
2308*67e74705SXin Li 
2309*67e74705SXin Li   // Tell the BugReporterContext to report cases when the tracked symbol is
2310*67e74705SXin Li   // assigned to different variables, etc.
2311*67e74705SXin Li   BR.markInteresting(Sym);
2312*67e74705SXin Li 
2313*67e74705SXin Li   // We are reporting a leak.  Walk up the graph to get to the first node where
2314*67e74705SXin Li   // the symbol appeared, and also get the first VarDecl that tracked object
2315*67e74705SXin Li   // is stored to.
2316*67e74705SXin Li   AllocationInfo AllocI =
2317*67e74705SXin Li     GetAllocationSite(BRC.getStateManager(), EndN, Sym);
2318*67e74705SXin Li 
2319*67e74705SXin Li   const MemRegion* FirstBinding = AllocI.R;
2320*67e74705SXin Li   BR.markInteresting(AllocI.InterestingMethodContext);
2321*67e74705SXin Li 
2322*67e74705SXin Li   SourceManager& SM = BRC.getSourceManager();
2323*67e74705SXin Li 
2324*67e74705SXin Li   // Compute an actual location for the leak.  Sometimes a leak doesn't
2325*67e74705SXin Li   // occur at an actual statement (e.g., transition between blocks; end
2326*67e74705SXin Li   // of function) so we need to walk the graph and compute a real location.
2327*67e74705SXin Li   const ExplodedNode *LeakN = EndN;
2328*67e74705SXin Li   PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
2329*67e74705SXin Li 
2330*67e74705SXin Li   std::string sbuf;
2331*67e74705SXin Li   llvm::raw_string_ostream os(sbuf);
2332*67e74705SXin Li 
2333*67e74705SXin Li   os << "Object leaked: ";
2334*67e74705SXin Li 
2335*67e74705SXin Li   if (FirstBinding) {
2336*67e74705SXin Li     os << "object allocated and stored into '"
2337*67e74705SXin Li        << FirstBinding->getString() << '\'';
2338*67e74705SXin Li   }
2339*67e74705SXin Li   else
2340*67e74705SXin Li     os << "allocated object";
2341*67e74705SXin Li 
2342*67e74705SXin Li   // Get the retain count.
2343*67e74705SXin Li   const RefVal* RV = getRefBinding(EndN->getState(), Sym);
2344*67e74705SXin Li   assert(RV);
2345*67e74705SXin Li 
2346*67e74705SXin Li   if (RV->getKind() == RefVal::ErrorLeakReturned) {
2347*67e74705SXin Li     // FIXME: Per comments in rdar://6320065, "create" only applies to CF
2348*67e74705SXin Li     // objects.  Only "copy", "alloc", "retain" and "new" transfer ownership
2349*67e74705SXin Li     // to the caller for NS objects.
2350*67e74705SXin Li     const Decl *D = &EndN->getCodeDecl();
2351*67e74705SXin Li 
2352*67e74705SXin Li     os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
2353*67e74705SXin Li                                   : " is returned from a function ");
2354*67e74705SXin Li 
2355*67e74705SXin Li     if (D->hasAttr<CFReturnsNotRetainedAttr>())
2356*67e74705SXin Li       os << "that is annotated as CF_RETURNS_NOT_RETAINED";
2357*67e74705SXin Li     else if (D->hasAttr<NSReturnsNotRetainedAttr>())
2358*67e74705SXin Li       os << "that is annotated as NS_RETURNS_NOT_RETAINED";
2359*67e74705SXin Li     else {
2360*67e74705SXin Li       if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
2361*67e74705SXin Li         os << "whose name ('" << MD->getSelector().getAsString()
2362*67e74705SXin Li            << "') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
2363*67e74705SXin Li               "  This violates the naming convention rules"
2364*67e74705SXin Li               " given in the Memory Management Guide for Cocoa";
2365*67e74705SXin Li       }
2366*67e74705SXin Li       else {
2367*67e74705SXin Li         const FunctionDecl *FD = cast<FunctionDecl>(D);
2368*67e74705SXin Li         os << "whose name ('" << *FD
2369*67e74705SXin Li            << "') does not contain 'Copy' or 'Create'.  This violates the naming"
2370*67e74705SXin Li               " convention rules given in the Memory Management Guide for Core"
2371*67e74705SXin Li               " Foundation";
2372*67e74705SXin Li       }
2373*67e74705SXin Li     }
2374*67e74705SXin Li   }
2375*67e74705SXin Li   else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2376*67e74705SXin Li     const ObjCMethodDecl &MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
2377*67e74705SXin Li     os << " and returned from method '" << MD.getSelector().getAsString()
2378*67e74705SXin Li        << "' is potentially leaked when using garbage collection.  Callers "
2379*67e74705SXin Li           "of this method do not expect a returned object with a +1 retain "
2380*67e74705SXin Li           "count since they expect the object to be managed by the garbage "
2381*67e74705SXin Li           "collector";
2382*67e74705SXin Li   }
2383*67e74705SXin Li   else
2384*67e74705SXin Li     os << " is not referenced later in this execution path and has a retain "
2385*67e74705SXin Li           "count of +" << RV->getCount();
2386*67e74705SXin Li 
2387*67e74705SXin Li   return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
2388*67e74705SXin Li }
2389*67e74705SXin Li 
CFRefLeakReport(CFRefBug & D,const LangOptions & LOpts,bool GCEnabled,const SummaryLogTy & Log,ExplodedNode * n,SymbolRef sym,CheckerContext & Ctx,bool IncludeAllocationLine)2390*67e74705SXin Li CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
2391*67e74705SXin Li                                  bool GCEnabled, const SummaryLogTy &Log,
2392*67e74705SXin Li                                  ExplodedNode *n, SymbolRef sym,
2393*67e74705SXin Li                                  CheckerContext &Ctx,
2394*67e74705SXin Li                                  bool IncludeAllocationLine)
2395*67e74705SXin Li   : CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) {
2396*67e74705SXin Li 
2397*67e74705SXin Li   // Most bug reports are cached at the location where they occurred.
2398*67e74705SXin Li   // With leaks, we want to unique them by the location where they were
2399*67e74705SXin Li   // allocated, and only report a single path.  To do this, we need to find
2400*67e74705SXin Li   // the allocation site of a piece of tracked memory, which we do via a
2401*67e74705SXin Li   // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
2402*67e74705SXin Li   // Note that this is *not* the trimmed graph; we are guaranteed, however,
2403*67e74705SXin Li   // that all ancestor nodes that represent the allocation site have the
2404*67e74705SXin Li   // same SourceLocation.
2405*67e74705SXin Li   const ExplodedNode *AllocNode = nullptr;
2406*67e74705SXin Li 
2407*67e74705SXin Li   const SourceManager& SMgr = Ctx.getSourceManager();
2408*67e74705SXin Li 
2409*67e74705SXin Li   AllocationInfo AllocI =
2410*67e74705SXin Li     GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
2411*67e74705SXin Li 
2412*67e74705SXin Li   AllocNode = AllocI.N;
2413*67e74705SXin Li   AllocBinding = AllocI.R;
2414*67e74705SXin Li   markInteresting(AllocI.InterestingMethodContext);
2415*67e74705SXin Li 
2416*67e74705SXin Li   // Get the SourceLocation for the allocation site.
2417*67e74705SXin Li   // FIXME: This will crash the analyzer if an allocation comes from an
2418*67e74705SXin Li   // implicit call (ex: a destructor call).
2419*67e74705SXin Li   // (Currently there are no such allocations in Cocoa, though.)
2420*67e74705SXin Li   const Stmt *AllocStmt = nullptr;
2421*67e74705SXin Li   ProgramPoint P = AllocNode->getLocation();
2422*67e74705SXin Li   if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
2423*67e74705SXin Li     AllocStmt = Exit->getCalleeContext()->getCallSite();
2424*67e74705SXin Li   else
2425*67e74705SXin Li     AllocStmt = P.castAs<PostStmt>().getStmt();
2426*67e74705SXin Li   assert(AllocStmt && "Cannot find allocation statement");
2427*67e74705SXin Li 
2428*67e74705SXin Li   PathDiagnosticLocation AllocLocation =
2429*67e74705SXin Li     PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
2430*67e74705SXin Li                                         AllocNode->getLocationContext());
2431*67e74705SXin Li   Location = AllocLocation;
2432*67e74705SXin Li 
2433*67e74705SXin Li   // Set uniqieing info, which will be used for unique the bug reports. The
2434*67e74705SXin Li   // leaks should be uniqued on the allocation site.
2435*67e74705SXin Li   UniqueingLocation = AllocLocation;
2436*67e74705SXin Li   UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2437*67e74705SXin Li 
2438*67e74705SXin Li   // Fill in the description of the bug.
2439*67e74705SXin Li   Description.clear();
2440*67e74705SXin Li   llvm::raw_string_ostream os(Description);
2441*67e74705SXin Li   os << "Potential leak ";
2442*67e74705SXin Li   if (GCEnabled)
2443*67e74705SXin Li     os << "(when using garbage collection) ";
2444*67e74705SXin Li   os << "of an object";
2445*67e74705SXin Li 
2446*67e74705SXin Li   if (AllocBinding) {
2447*67e74705SXin Li     os << " stored into '" << AllocBinding->getString() << '\'';
2448*67e74705SXin Li     if (IncludeAllocationLine) {
2449*67e74705SXin Li       FullSourceLoc SL(AllocStmt->getLocStart(), Ctx.getSourceManager());
2450*67e74705SXin Li       os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
2451*67e74705SXin Li     }
2452*67e74705SXin Li   }
2453*67e74705SXin Li 
2454*67e74705SXin Li   addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
2455*67e74705SXin Li }
2456*67e74705SXin Li 
2457*67e74705SXin Li //===----------------------------------------------------------------------===//
2458*67e74705SXin Li // Main checker logic.
2459*67e74705SXin Li //===----------------------------------------------------------------------===//
2460*67e74705SXin Li 
2461*67e74705SXin Li namespace {
2462*67e74705SXin Li class RetainCountChecker
2463*67e74705SXin Li   : public Checker< check::Bind,
2464*67e74705SXin Li                     check::DeadSymbols,
2465*67e74705SXin Li                     check::EndAnalysis,
2466*67e74705SXin Li                     check::EndFunction,
2467*67e74705SXin Li                     check::PostStmt<BlockExpr>,
2468*67e74705SXin Li                     check::PostStmt<CastExpr>,
2469*67e74705SXin Li                     check::PostStmt<ObjCArrayLiteral>,
2470*67e74705SXin Li                     check::PostStmt<ObjCDictionaryLiteral>,
2471*67e74705SXin Li                     check::PostStmt<ObjCBoxedExpr>,
2472*67e74705SXin Li                     check::PostStmt<ObjCIvarRefExpr>,
2473*67e74705SXin Li                     check::PostCall,
2474*67e74705SXin Li                     check::PreStmt<ReturnStmt>,
2475*67e74705SXin Li                     check::RegionChanges,
2476*67e74705SXin Li                     eval::Assume,
2477*67e74705SXin Li                     eval::Call > {
2478*67e74705SXin Li   mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
2479*67e74705SXin Li   mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
2480*67e74705SXin Li   mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2481*67e74705SXin Li   mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
2482*67e74705SXin Li   mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2483*67e74705SXin Li 
2484*67e74705SXin Li   typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
2485*67e74705SXin Li 
2486*67e74705SXin Li   // This map is only used to ensure proper deletion of any allocated tags.
2487*67e74705SXin Li   mutable SymbolTagMap DeadSymbolTags;
2488*67e74705SXin Li 
2489*67e74705SXin Li   mutable std::unique_ptr<RetainSummaryManager> Summaries;
2490*67e74705SXin Li   mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
2491*67e74705SXin Li   mutable SummaryLogTy SummaryLog;
2492*67e74705SXin Li   mutable bool ShouldResetSummaryLog;
2493*67e74705SXin Li 
2494*67e74705SXin Li   /// Optional setting to indicate if leak reports should include
2495*67e74705SXin Li   /// the allocation line.
2496*67e74705SXin Li   mutable bool IncludeAllocationLine;
2497*67e74705SXin Li 
2498*67e74705SXin Li public:
RetainCountChecker(AnalyzerOptions & AO)2499*67e74705SXin Li   RetainCountChecker(AnalyzerOptions &AO)
2500*67e74705SXin Li     : ShouldResetSummaryLog(false),
2501*67e74705SXin Li       IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
2502*67e74705SXin Li 
~RetainCountChecker()2503*67e74705SXin Li   ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); }
2504*67e74705SXin Li 
checkEndAnalysis(ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng) const2505*67e74705SXin Li   void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
2506*67e74705SXin Li                         ExprEngine &Eng) const {
2507*67e74705SXin Li     // FIXME: This is a hack to make sure the summary log gets cleared between
2508*67e74705SXin Li     // analyses of different code bodies.
2509*67e74705SXin Li     //
2510*67e74705SXin Li     // Why is this necessary? Because a checker's lifetime is tied to a
2511*67e74705SXin Li     // translation unit, but an ExplodedGraph's lifetime is just a code body.
2512*67e74705SXin Li     // Once in a blue moon, a new ExplodedNode will have the same address as an
2513*67e74705SXin Li     // old one with an associated summary, and the bug report visitor gets very
2514*67e74705SXin Li     // confused. (To make things worse, the summary lifetime is currently also
2515*67e74705SXin Li     // tied to a code body, so we get a crash instead of incorrect results.)
2516*67e74705SXin Li     //
2517*67e74705SXin Li     // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
2518*67e74705SXin Li     // changes, things will start going wrong again. Really the lifetime of this
2519*67e74705SXin Li     // log needs to be tied to either the specific nodes in it or the entire
2520*67e74705SXin Li     // ExplodedGraph, not to a specific part of the code being analyzed.
2521*67e74705SXin Li     //
2522*67e74705SXin Li     // (Also, having stateful local data means that the same checker can't be
2523*67e74705SXin Li     // used from multiple threads, but a lot of checkers have incorrect
2524*67e74705SXin Li     // assumptions about that anyway. So that wasn't a priority at the time of
2525*67e74705SXin Li     // this fix.)
2526*67e74705SXin Li     //
2527*67e74705SXin Li     // This happens at the end of analysis, but bug reports are emitted /after/
2528*67e74705SXin Li     // this point. So we can't just clear the summary log now. Instead, we mark
2529*67e74705SXin Li     // that the next time we access the summary log, it should be cleared.
2530*67e74705SXin Li 
2531*67e74705SXin Li     // If we never reset the summary log during /this/ code body analysis,
2532*67e74705SXin Li     // there were no new summaries. There might still have been summaries from
2533*67e74705SXin Li     // the /last/ analysis, so clear them out to make sure the bug report
2534*67e74705SXin Li     // visitors don't get confused.
2535*67e74705SXin Li     if (ShouldResetSummaryLog)
2536*67e74705SXin Li       SummaryLog.clear();
2537*67e74705SXin Li 
2538*67e74705SXin Li     ShouldResetSummaryLog = !SummaryLog.empty();
2539*67e74705SXin Li   }
2540*67e74705SXin Li 
getLeakWithinFunctionBug(const LangOptions & LOpts,bool GCEnabled) const2541*67e74705SXin Li   CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts,
2542*67e74705SXin Li                                      bool GCEnabled) const {
2543*67e74705SXin Li     if (GCEnabled) {
2544*67e74705SXin Li       if (!leakWithinFunctionGC)
2545*67e74705SXin Li         leakWithinFunctionGC.reset(new Leak(this, "Leak of object when using "
2546*67e74705SXin Li                                                   "garbage collection"));
2547*67e74705SXin Li       return leakWithinFunctionGC.get();
2548*67e74705SXin Li     } else {
2549*67e74705SXin Li       if (!leakWithinFunction) {
2550*67e74705SXin Li         if (LOpts.getGC() == LangOptions::HybridGC) {
2551*67e74705SXin Li           leakWithinFunction.reset(new Leak(this,
2552*67e74705SXin Li                                             "Leak of object when not using "
2553*67e74705SXin Li                                             "garbage collection (GC) in "
2554*67e74705SXin Li                                             "dual GC/non-GC code"));
2555*67e74705SXin Li         } else {
2556*67e74705SXin Li           leakWithinFunction.reset(new Leak(this, "Leak"));
2557*67e74705SXin Li         }
2558*67e74705SXin Li       }
2559*67e74705SXin Li       return leakWithinFunction.get();
2560*67e74705SXin Li     }
2561*67e74705SXin Li   }
2562*67e74705SXin Li 
getLeakAtReturnBug(const LangOptions & LOpts,bool GCEnabled) const2563*67e74705SXin Li   CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts, bool GCEnabled) const {
2564*67e74705SXin Li     if (GCEnabled) {
2565*67e74705SXin Li       if (!leakAtReturnGC)
2566*67e74705SXin Li         leakAtReturnGC.reset(new Leak(this,
2567*67e74705SXin Li                                       "Leak of returned object when using "
2568*67e74705SXin Li                                       "garbage collection"));
2569*67e74705SXin Li       return leakAtReturnGC.get();
2570*67e74705SXin Li     } else {
2571*67e74705SXin Li       if (!leakAtReturn) {
2572*67e74705SXin Li         if (LOpts.getGC() == LangOptions::HybridGC) {
2573*67e74705SXin Li           leakAtReturn.reset(new Leak(this,
2574*67e74705SXin Li                                       "Leak of returned object when not using "
2575*67e74705SXin Li                                       "garbage collection (GC) in dual "
2576*67e74705SXin Li                                       "GC/non-GC code"));
2577*67e74705SXin Li         } else {
2578*67e74705SXin Li           leakAtReturn.reset(new Leak(this, "Leak of returned object"));
2579*67e74705SXin Li         }
2580*67e74705SXin Li       }
2581*67e74705SXin Li       return leakAtReturn.get();
2582*67e74705SXin Li     }
2583*67e74705SXin Li   }
2584*67e74705SXin Li 
getSummaryManager(ASTContext & Ctx,bool GCEnabled) const2585*67e74705SXin Li   RetainSummaryManager &getSummaryManager(ASTContext &Ctx,
2586*67e74705SXin Li                                           bool GCEnabled) const {
2587*67e74705SXin Li     // FIXME: We don't support ARC being turned on and off during one analysis.
2588*67e74705SXin Li     // (nor, for that matter, do we support changing ASTContexts)
2589*67e74705SXin Li     bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
2590*67e74705SXin Li     if (GCEnabled) {
2591*67e74705SXin Li       if (!SummariesGC)
2592*67e74705SXin Li         SummariesGC.reset(new RetainSummaryManager(Ctx, true, ARCEnabled));
2593*67e74705SXin Li       else
2594*67e74705SXin Li         assert(SummariesGC->isARCEnabled() == ARCEnabled);
2595*67e74705SXin Li       return *SummariesGC;
2596*67e74705SXin Li     } else {
2597*67e74705SXin Li       if (!Summaries)
2598*67e74705SXin Li         Summaries.reset(new RetainSummaryManager(Ctx, false, ARCEnabled));
2599*67e74705SXin Li       else
2600*67e74705SXin Li         assert(Summaries->isARCEnabled() == ARCEnabled);
2601*67e74705SXin Li       return *Summaries;
2602*67e74705SXin Li     }
2603*67e74705SXin Li   }
2604*67e74705SXin Li 
getSummaryManager(CheckerContext & C) const2605*67e74705SXin Li   RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
2606*67e74705SXin Li     return getSummaryManager(C.getASTContext(), C.isObjCGCEnabled());
2607*67e74705SXin Li   }
2608*67e74705SXin Li 
2609*67e74705SXin Li   void printState(raw_ostream &Out, ProgramStateRef State,
2610*67e74705SXin Li                   const char *NL, const char *Sep) const override;
2611*67e74705SXin Li 
2612*67e74705SXin Li   void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
2613*67e74705SXin Li   void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
2614*67e74705SXin Li   void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
2615*67e74705SXin Li 
2616*67e74705SXin Li   void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
2617*67e74705SXin Li   void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
2618*67e74705SXin Li   void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
2619*67e74705SXin Li 
2620*67e74705SXin Li   void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
2621*67e74705SXin Li 
2622*67e74705SXin Li   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
2623*67e74705SXin Li 
2624*67e74705SXin Li   void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
2625*67e74705SXin Li                     CheckerContext &C) const;
2626*67e74705SXin Li 
2627*67e74705SXin Li   void processSummaryOfInlined(const RetainSummary &Summ,
2628*67e74705SXin Li                                const CallEvent &Call,
2629*67e74705SXin Li                                CheckerContext &C) const;
2630*67e74705SXin Li 
2631*67e74705SXin Li   bool evalCall(const CallExpr *CE, CheckerContext &C) const;
2632*67e74705SXin Li 
2633*67e74705SXin Li   ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
2634*67e74705SXin Li                                  bool Assumption) const;
2635*67e74705SXin Li 
2636*67e74705SXin Li   ProgramStateRef
2637*67e74705SXin Li   checkRegionChanges(ProgramStateRef state,
2638*67e74705SXin Li                      const InvalidatedSymbols *invalidated,
2639*67e74705SXin Li                      ArrayRef<const MemRegion *> ExplicitRegions,
2640*67e74705SXin Li                      ArrayRef<const MemRegion *> Regions,
2641*67e74705SXin Li                      const CallEvent *Call) const;
2642*67e74705SXin Li 
wantsRegionChangeUpdate(ProgramStateRef state) const2643*67e74705SXin Li   bool wantsRegionChangeUpdate(ProgramStateRef state) const {
2644*67e74705SXin Li     return true;
2645*67e74705SXin Li   }
2646*67e74705SXin Li 
2647*67e74705SXin Li   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
2648*67e74705SXin Li   void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
2649*67e74705SXin Li                                 ExplodedNode *Pred, RetEffect RE, RefVal X,
2650*67e74705SXin Li                                 SymbolRef Sym, ProgramStateRef state) const;
2651*67e74705SXin Li 
2652*67e74705SXin Li   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
2653*67e74705SXin Li   void checkEndFunction(CheckerContext &C) const;
2654*67e74705SXin Li 
2655*67e74705SXin Li   ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
2656*67e74705SXin Li                                RefVal V, ArgEffect E, RefVal::Kind &hasErr,
2657*67e74705SXin Li                                CheckerContext &C) const;
2658*67e74705SXin Li 
2659*67e74705SXin Li   void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
2660*67e74705SXin Li                            RefVal::Kind ErrorKind, SymbolRef Sym,
2661*67e74705SXin Li                            CheckerContext &C) const;
2662*67e74705SXin Li 
2663*67e74705SXin Li   void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
2664*67e74705SXin Li 
2665*67e74705SXin Li   const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const;
2666*67e74705SXin Li 
2667*67e74705SXin Li   ProgramStateRef handleSymbolDeath(ProgramStateRef state,
2668*67e74705SXin Li                                     SymbolRef sid, RefVal V,
2669*67e74705SXin Li                                     SmallVectorImpl<SymbolRef> &Leaked) const;
2670*67e74705SXin Li 
2671*67e74705SXin Li   ProgramStateRef
2672*67e74705SXin Li   handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
2673*67e74705SXin Li                           const ProgramPointTag *Tag, CheckerContext &Ctx,
2674*67e74705SXin Li                           SymbolRef Sym, RefVal V) const;
2675*67e74705SXin Li 
2676*67e74705SXin Li   ExplodedNode *processLeaks(ProgramStateRef state,
2677*67e74705SXin Li                              SmallVectorImpl<SymbolRef> &Leaked,
2678*67e74705SXin Li                              CheckerContext &Ctx,
2679*67e74705SXin Li                              ExplodedNode *Pred = nullptr) const;
2680*67e74705SXin Li };
2681*67e74705SXin Li } // end anonymous namespace
2682*67e74705SXin Li 
2683*67e74705SXin Li namespace {
2684*67e74705SXin Li class StopTrackingCallback final : public SymbolVisitor {
2685*67e74705SXin Li   ProgramStateRef state;
2686*67e74705SXin Li public:
StopTrackingCallback(ProgramStateRef st)2687*67e74705SXin Li   StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
getState() const2688*67e74705SXin Li   ProgramStateRef getState() const { return state; }
2689*67e74705SXin Li 
VisitSymbol(SymbolRef sym)2690*67e74705SXin Li   bool VisitSymbol(SymbolRef sym) override {
2691*67e74705SXin Li     state = state->remove<RefBindings>(sym);
2692*67e74705SXin Li     return true;
2693*67e74705SXin Li   }
2694*67e74705SXin Li };
2695*67e74705SXin Li } // end anonymous namespace
2696*67e74705SXin Li 
2697*67e74705SXin Li //===----------------------------------------------------------------------===//
2698*67e74705SXin Li // Handle statements that may have an effect on refcounts.
2699*67e74705SXin Li //===----------------------------------------------------------------------===//
2700*67e74705SXin Li 
checkPostStmt(const BlockExpr * BE,CheckerContext & C) const2701*67e74705SXin Li void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
2702*67e74705SXin Li                                        CheckerContext &C) const {
2703*67e74705SXin Li 
2704*67e74705SXin Li   // Scan the BlockDecRefExprs for any object the retain count checker
2705*67e74705SXin Li   // may be tracking.
2706*67e74705SXin Li   if (!BE->getBlockDecl()->hasCaptures())
2707*67e74705SXin Li     return;
2708*67e74705SXin Li 
2709*67e74705SXin Li   ProgramStateRef state = C.getState();
2710*67e74705SXin Li   const BlockDataRegion *R =
2711*67e74705SXin Li     cast<BlockDataRegion>(state->getSVal(BE,
2712*67e74705SXin Li                                          C.getLocationContext()).getAsRegion());
2713*67e74705SXin Li 
2714*67e74705SXin Li   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
2715*67e74705SXin Li                                             E = R->referenced_vars_end();
2716*67e74705SXin Li 
2717*67e74705SXin Li   if (I == E)
2718*67e74705SXin Li     return;
2719*67e74705SXin Li 
2720*67e74705SXin Li   // FIXME: For now we invalidate the tracking of all symbols passed to blocks
2721*67e74705SXin Li   // via captured variables, even though captured variables result in a copy
2722*67e74705SXin Li   // and in implicit increment/decrement of a retain count.
2723*67e74705SXin Li   SmallVector<const MemRegion*, 10> Regions;
2724*67e74705SXin Li   const LocationContext *LC = C.getLocationContext();
2725*67e74705SXin Li   MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
2726*67e74705SXin Li 
2727*67e74705SXin Li   for ( ; I != E; ++I) {
2728*67e74705SXin Li     const VarRegion *VR = I.getCapturedRegion();
2729*67e74705SXin Li     if (VR->getSuperRegion() == R) {
2730*67e74705SXin Li       VR = MemMgr.getVarRegion(VR->getDecl(), LC);
2731*67e74705SXin Li     }
2732*67e74705SXin Li     Regions.push_back(VR);
2733*67e74705SXin Li   }
2734*67e74705SXin Li 
2735*67e74705SXin Li   state =
2736*67e74705SXin Li     state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2737*67e74705SXin Li                                     Regions.data() + Regions.size()).getState();
2738*67e74705SXin Li   C.addTransition(state);
2739*67e74705SXin Li }
2740*67e74705SXin Li 
checkPostStmt(const CastExpr * CE,CheckerContext & C) const2741*67e74705SXin Li void RetainCountChecker::checkPostStmt(const CastExpr *CE,
2742*67e74705SXin Li                                        CheckerContext &C) const {
2743*67e74705SXin Li   const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
2744*67e74705SXin Li   if (!BE)
2745*67e74705SXin Li     return;
2746*67e74705SXin Li 
2747*67e74705SXin Li   ArgEffect AE = IncRef;
2748*67e74705SXin Li 
2749*67e74705SXin Li   switch (BE->getBridgeKind()) {
2750*67e74705SXin Li     case clang::OBC_Bridge:
2751*67e74705SXin Li       // Do nothing.
2752*67e74705SXin Li       return;
2753*67e74705SXin Li     case clang::OBC_BridgeRetained:
2754*67e74705SXin Li       AE = IncRef;
2755*67e74705SXin Li       break;
2756*67e74705SXin Li     case clang::OBC_BridgeTransfer:
2757*67e74705SXin Li       AE = DecRefBridgedTransferred;
2758*67e74705SXin Li       break;
2759*67e74705SXin Li   }
2760*67e74705SXin Li 
2761*67e74705SXin Li   ProgramStateRef state = C.getState();
2762*67e74705SXin Li   SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
2763*67e74705SXin Li   if (!Sym)
2764*67e74705SXin Li     return;
2765*67e74705SXin Li   const RefVal* T = getRefBinding(state, Sym);
2766*67e74705SXin Li   if (!T)
2767*67e74705SXin Li     return;
2768*67e74705SXin Li 
2769*67e74705SXin Li   RefVal::Kind hasErr = (RefVal::Kind) 0;
2770*67e74705SXin Li   state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2771*67e74705SXin Li 
2772*67e74705SXin Li   if (hasErr) {
2773*67e74705SXin Li     // FIXME: If we get an error during a bridge cast, should we report it?
2774*67e74705SXin Li     return;
2775*67e74705SXin Li   }
2776*67e74705SXin Li 
2777*67e74705SXin Li   C.addTransition(state);
2778*67e74705SXin Li }
2779*67e74705SXin Li 
processObjCLiterals(CheckerContext & C,const Expr * Ex) const2780*67e74705SXin Li void RetainCountChecker::processObjCLiterals(CheckerContext &C,
2781*67e74705SXin Li                                              const Expr *Ex) const {
2782*67e74705SXin Li   ProgramStateRef state = C.getState();
2783*67e74705SXin Li   const ExplodedNode *pred = C.getPredecessor();
2784*67e74705SXin Li   for (const Stmt *Child : Ex->children()) {
2785*67e74705SXin Li     SVal V = state->getSVal(Child, pred->getLocationContext());
2786*67e74705SXin Li     if (SymbolRef sym = V.getAsSymbol())
2787*67e74705SXin Li       if (const RefVal* T = getRefBinding(state, sym)) {
2788*67e74705SXin Li         RefVal::Kind hasErr = (RefVal::Kind) 0;
2789*67e74705SXin Li         state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
2790*67e74705SXin Li         if (hasErr) {
2791*67e74705SXin Li           processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
2792*67e74705SXin Li           return;
2793*67e74705SXin Li         }
2794*67e74705SXin Li       }
2795*67e74705SXin Li   }
2796*67e74705SXin Li 
2797*67e74705SXin Li   // Return the object as autoreleased.
2798*67e74705SXin Li   //  RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
2799*67e74705SXin Li   if (SymbolRef sym =
2800*67e74705SXin Li         state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
2801*67e74705SXin Li     QualType ResultTy = Ex->getType();
2802*67e74705SXin Li     state = setRefBinding(state, sym,
2803*67e74705SXin Li                           RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
2804*67e74705SXin Li   }
2805*67e74705SXin Li 
2806*67e74705SXin Li   C.addTransition(state);
2807*67e74705SXin Li }
2808*67e74705SXin Li 
checkPostStmt(const ObjCArrayLiteral * AL,CheckerContext & C) const2809*67e74705SXin Li void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
2810*67e74705SXin Li                                        CheckerContext &C) const {
2811*67e74705SXin Li   // Apply the 'MayEscape' to all values.
2812*67e74705SXin Li   processObjCLiterals(C, AL);
2813*67e74705SXin Li }
2814*67e74705SXin Li 
checkPostStmt(const ObjCDictionaryLiteral * DL,CheckerContext & C) const2815*67e74705SXin Li void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
2816*67e74705SXin Li                                        CheckerContext &C) const {
2817*67e74705SXin Li   // Apply the 'MayEscape' to all keys and values.
2818*67e74705SXin Li   processObjCLiterals(C, DL);
2819*67e74705SXin Li }
2820*67e74705SXin Li 
checkPostStmt(const ObjCBoxedExpr * Ex,CheckerContext & C) const2821*67e74705SXin Li void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
2822*67e74705SXin Li                                        CheckerContext &C) const {
2823*67e74705SXin Li   const ExplodedNode *Pred = C.getPredecessor();
2824*67e74705SXin Li   const LocationContext *LCtx = Pred->getLocationContext();
2825*67e74705SXin Li   ProgramStateRef State = Pred->getState();
2826*67e74705SXin Li 
2827*67e74705SXin Li   if (SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
2828*67e74705SXin Li     QualType ResultTy = Ex->getType();
2829*67e74705SXin Li     State = setRefBinding(State, Sym,
2830*67e74705SXin Li                           RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
2831*67e74705SXin Li   }
2832*67e74705SXin Li 
2833*67e74705SXin Li   C.addTransition(State);
2834*67e74705SXin Li }
2835*67e74705SXin Li 
checkPostStmt(const ObjCIvarRefExpr * IRE,CheckerContext & C) const2836*67e74705SXin Li void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
2837*67e74705SXin Li                                        CheckerContext &C) const {
2838*67e74705SXin Li   Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
2839*67e74705SXin Li   if (!IVarLoc)
2840*67e74705SXin Li     return;
2841*67e74705SXin Li 
2842*67e74705SXin Li   ProgramStateRef State = C.getState();
2843*67e74705SXin Li   SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
2844*67e74705SXin Li   if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion()))
2845*67e74705SXin Li     return;
2846*67e74705SXin Li 
2847*67e74705SXin Li   // Accessing an ivar directly is unusual. If we've done that, be more
2848*67e74705SXin Li   // forgiving about what the surrounding code is allowed to do.
2849*67e74705SXin Li 
2850*67e74705SXin Li   QualType Ty = Sym->getType();
2851*67e74705SXin Li   RetEffect::ObjKind Kind;
2852*67e74705SXin Li   if (Ty->isObjCRetainableType())
2853*67e74705SXin Li     Kind = RetEffect::ObjC;
2854*67e74705SXin Li   else if (coreFoundation::isCFObjectRef(Ty))
2855*67e74705SXin Li     Kind = RetEffect::CF;
2856*67e74705SXin Li   else
2857*67e74705SXin Li     return;
2858*67e74705SXin Li 
2859*67e74705SXin Li   // If the value is already known to be nil, don't bother tracking it.
2860*67e74705SXin Li   ConstraintManager &CMgr = State->getConstraintManager();
2861*67e74705SXin Li   if (CMgr.isNull(State, Sym).isConstrainedTrue())
2862*67e74705SXin Li     return;
2863*67e74705SXin Li 
2864*67e74705SXin Li   if (const RefVal *RV = getRefBinding(State, Sym)) {
2865*67e74705SXin Li     // If we've seen this symbol before, or we're only seeing it now because
2866*67e74705SXin Li     // of something the analyzer has synthesized, don't do anything.
2867*67e74705SXin Li     if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
2868*67e74705SXin Li         isSynthesizedAccessor(C.getStackFrame())) {
2869*67e74705SXin Li       return;
2870*67e74705SXin Li     }
2871*67e74705SXin Li 
2872*67e74705SXin Li     // Note that this value has been loaded from an ivar.
2873*67e74705SXin Li     C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
2874*67e74705SXin Li     return;
2875*67e74705SXin Li   }
2876*67e74705SXin Li 
2877*67e74705SXin Li   RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
2878*67e74705SXin Li 
2879*67e74705SXin Li   // In a synthesized accessor, the effective retain count is +0.
2880*67e74705SXin Li   if (isSynthesizedAccessor(C.getStackFrame())) {
2881*67e74705SXin Li     C.addTransition(setRefBinding(State, Sym, PlusZero));
2882*67e74705SXin Li     return;
2883*67e74705SXin Li   }
2884*67e74705SXin Li 
2885*67e74705SXin Li   State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
2886*67e74705SXin Li   C.addTransition(State);
2887*67e74705SXin Li }
2888*67e74705SXin Li 
checkPostCall(const CallEvent & Call,CheckerContext & C) const2889*67e74705SXin Li void RetainCountChecker::checkPostCall(const CallEvent &Call,
2890*67e74705SXin Li                                        CheckerContext &C) const {
2891*67e74705SXin Li   RetainSummaryManager &Summaries = getSummaryManager(C);
2892*67e74705SXin Li   const RetainSummary *Summ = Summaries.getSummary(Call, C.getState());
2893*67e74705SXin Li 
2894*67e74705SXin Li   if (C.wasInlined) {
2895*67e74705SXin Li     processSummaryOfInlined(*Summ, Call, C);
2896*67e74705SXin Li     return;
2897*67e74705SXin Li   }
2898*67e74705SXin Li   checkSummary(*Summ, Call, C);
2899*67e74705SXin Li }
2900*67e74705SXin Li 
2901*67e74705SXin Li /// GetReturnType - Used to get the return type of a message expression or
2902*67e74705SXin Li ///  function call with the intention of affixing that type to a tracked symbol.
2903*67e74705SXin Li ///  While the return type can be queried directly from RetEx, when
2904*67e74705SXin Li ///  invoking class methods we augment to the return type to be that of
2905*67e74705SXin Li ///  a pointer to the class (as opposed it just being id).
2906*67e74705SXin Li // FIXME: We may be able to do this with related result types instead.
2907*67e74705SXin Li // This function is probably overestimating.
GetReturnType(const Expr * RetE,ASTContext & Ctx)2908*67e74705SXin Li static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
2909*67e74705SXin Li   QualType RetTy = RetE->getType();
2910*67e74705SXin Li   // If RetE is not a message expression just return its type.
2911*67e74705SXin Li   // If RetE is a message expression, return its types if it is something
2912*67e74705SXin Li   /// more specific than id.
2913*67e74705SXin Li   if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
2914*67e74705SXin Li     if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
2915*67e74705SXin Li       if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2916*67e74705SXin Li           PT->isObjCClassType()) {
2917*67e74705SXin Li         // At this point we know the return type of the message expression is
2918*67e74705SXin Li         // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
2919*67e74705SXin Li         // is a call to a class method whose type we can resolve.  In such
2920*67e74705SXin Li         // cases, promote the return type to XXX* (where XXX is the class).
2921*67e74705SXin Li         const ObjCInterfaceDecl *D = ME->getReceiverInterface();
2922*67e74705SXin Li         return !D ? RetTy :
2923*67e74705SXin Li                     Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
2924*67e74705SXin Li       }
2925*67e74705SXin Li 
2926*67e74705SXin Li   return RetTy;
2927*67e74705SXin Li }
2928*67e74705SXin Li 
2929*67e74705SXin Li // We don't always get the exact modeling of the function with regards to the
2930*67e74705SXin Li // retain count checker even when the function is inlined. For example, we need
2931*67e74705SXin Li // to stop tracking the symbols which were marked with StopTrackingHard.
processSummaryOfInlined(const RetainSummary & Summ,const CallEvent & CallOrMsg,CheckerContext & C) const2932*67e74705SXin Li void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
2933*67e74705SXin Li                                                  const CallEvent &CallOrMsg,
2934*67e74705SXin Li                                                  CheckerContext &C) const {
2935*67e74705SXin Li   ProgramStateRef state = C.getState();
2936*67e74705SXin Li 
2937*67e74705SXin Li   // Evaluate the effect of the arguments.
2938*67e74705SXin Li   for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
2939*67e74705SXin Li     if (Summ.getArg(idx) == StopTrackingHard) {
2940*67e74705SXin Li       SVal V = CallOrMsg.getArgSVal(idx);
2941*67e74705SXin Li       if (SymbolRef Sym = V.getAsLocSymbol()) {
2942*67e74705SXin Li         state = removeRefBinding(state, Sym);
2943*67e74705SXin Li       }
2944*67e74705SXin Li     }
2945*67e74705SXin Li   }
2946*67e74705SXin Li 
2947*67e74705SXin Li   // Evaluate the effect on the message receiver.
2948*67e74705SXin Li   const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
2949*67e74705SXin Li   if (MsgInvocation) {
2950*67e74705SXin Li     if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
2951*67e74705SXin Li       if (Summ.getReceiverEffect() == StopTrackingHard) {
2952*67e74705SXin Li         state = removeRefBinding(state, Sym);
2953*67e74705SXin Li       }
2954*67e74705SXin Li     }
2955*67e74705SXin Li   }
2956*67e74705SXin Li 
2957*67e74705SXin Li   // Consult the summary for the return value.
2958*67e74705SXin Li   RetEffect RE = Summ.getRetEffect();
2959*67e74705SXin Li   if (RE.getKind() == RetEffect::NoRetHard) {
2960*67e74705SXin Li     SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
2961*67e74705SXin Li     if (Sym)
2962*67e74705SXin Li       state = removeRefBinding(state, Sym);
2963*67e74705SXin Li   }
2964*67e74705SXin Li 
2965*67e74705SXin Li   C.addTransition(state);
2966*67e74705SXin Li }
2967*67e74705SXin Li 
updateOutParameter(ProgramStateRef State,SVal ArgVal,ArgEffect Effect)2968*67e74705SXin Li static ProgramStateRef updateOutParameter(ProgramStateRef State,
2969*67e74705SXin Li                                           SVal ArgVal,
2970*67e74705SXin Li                                           ArgEffect Effect) {
2971*67e74705SXin Li   auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
2972*67e74705SXin Li   if (!ArgRegion)
2973*67e74705SXin Li     return State;
2974*67e74705SXin Li 
2975*67e74705SXin Li   QualType PointeeTy = ArgRegion->getValueType();
2976*67e74705SXin Li   if (!coreFoundation::isCFObjectRef(PointeeTy))
2977*67e74705SXin Li     return State;
2978*67e74705SXin Li 
2979*67e74705SXin Li   SVal PointeeVal = State->getSVal(ArgRegion);
2980*67e74705SXin Li   SymbolRef Pointee = PointeeVal.getAsLocSymbol();
2981*67e74705SXin Li   if (!Pointee)
2982*67e74705SXin Li     return State;
2983*67e74705SXin Li 
2984*67e74705SXin Li   switch (Effect) {
2985*67e74705SXin Li   case UnretainedOutParameter:
2986*67e74705SXin Li     State = setRefBinding(State, Pointee,
2987*67e74705SXin Li                           RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
2988*67e74705SXin Li     break;
2989*67e74705SXin Li   case RetainedOutParameter:
2990*67e74705SXin Li     // Do nothing. Retained out parameters will either point to a +1 reference
2991*67e74705SXin Li     // or NULL, but the way you check for failure differs depending on the API.
2992*67e74705SXin Li     // Consequently, we don't have a good way to track them yet.
2993*67e74705SXin Li     break;
2994*67e74705SXin Li 
2995*67e74705SXin Li   default:
2996*67e74705SXin Li     llvm_unreachable("only for out parameters");
2997*67e74705SXin Li   }
2998*67e74705SXin Li 
2999*67e74705SXin Li   return State;
3000*67e74705SXin Li }
3001*67e74705SXin Li 
checkSummary(const RetainSummary & Summ,const CallEvent & CallOrMsg,CheckerContext & C) const3002*67e74705SXin Li void RetainCountChecker::checkSummary(const RetainSummary &Summ,
3003*67e74705SXin Li                                       const CallEvent &CallOrMsg,
3004*67e74705SXin Li                                       CheckerContext &C) const {
3005*67e74705SXin Li   ProgramStateRef state = C.getState();
3006*67e74705SXin Li 
3007*67e74705SXin Li   // Evaluate the effect of the arguments.
3008*67e74705SXin Li   RefVal::Kind hasErr = (RefVal::Kind) 0;
3009*67e74705SXin Li   SourceRange ErrorRange;
3010*67e74705SXin Li   SymbolRef ErrorSym = nullptr;
3011*67e74705SXin Li 
3012*67e74705SXin Li   for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
3013*67e74705SXin Li     SVal V = CallOrMsg.getArgSVal(idx);
3014*67e74705SXin Li 
3015*67e74705SXin Li     ArgEffect Effect = Summ.getArg(idx);
3016*67e74705SXin Li     if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
3017*67e74705SXin Li       state = updateOutParameter(state, V, Effect);
3018*67e74705SXin Li     } else if (SymbolRef Sym = V.getAsLocSymbol()) {
3019*67e74705SXin Li       if (const RefVal *T = getRefBinding(state, Sym)) {
3020*67e74705SXin Li         state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
3021*67e74705SXin Li         if (hasErr) {
3022*67e74705SXin Li           ErrorRange = CallOrMsg.getArgSourceRange(idx);
3023*67e74705SXin Li           ErrorSym = Sym;
3024*67e74705SXin Li           break;
3025*67e74705SXin Li         }
3026*67e74705SXin Li       }
3027*67e74705SXin Li     }
3028*67e74705SXin Li   }
3029*67e74705SXin Li 
3030*67e74705SXin Li   // Evaluate the effect on the message receiver.
3031*67e74705SXin Li   bool ReceiverIsTracked = false;
3032*67e74705SXin Li   if (!hasErr) {
3033*67e74705SXin Li     const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
3034*67e74705SXin Li     if (MsgInvocation) {
3035*67e74705SXin Li       if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
3036*67e74705SXin Li         if (const RefVal *T = getRefBinding(state, Sym)) {
3037*67e74705SXin Li           ReceiverIsTracked = true;
3038*67e74705SXin Li           state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
3039*67e74705SXin Li                                  hasErr, C);
3040*67e74705SXin Li           if (hasErr) {
3041*67e74705SXin Li             ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
3042*67e74705SXin Li             ErrorSym = Sym;
3043*67e74705SXin Li           }
3044*67e74705SXin Li         }
3045*67e74705SXin Li       }
3046*67e74705SXin Li     }
3047*67e74705SXin Li   }
3048*67e74705SXin Li 
3049*67e74705SXin Li   // Process any errors.
3050*67e74705SXin Li   if (hasErr) {
3051*67e74705SXin Li     processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
3052*67e74705SXin Li     return;
3053*67e74705SXin Li   }
3054*67e74705SXin Li 
3055*67e74705SXin Li   // Consult the summary for the return value.
3056*67e74705SXin Li   RetEffect RE = Summ.getRetEffect();
3057*67e74705SXin Li 
3058*67e74705SXin Li   if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
3059*67e74705SXin Li     if (ReceiverIsTracked)
3060*67e74705SXin Li       RE = getSummaryManager(C).getObjAllocRetEffect();
3061*67e74705SXin Li     else
3062*67e74705SXin Li       RE = RetEffect::MakeNoRet();
3063*67e74705SXin Li   }
3064*67e74705SXin Li 
3065*67e74705SXin Li   switch (RE.getKind()) {
3066*67e74705SXin Li     default:
3067*67e74705SXin Li       llvm_unreachable("Unhandled RetEffect.");
3068*67e74705SXin Li 
3069*67e74705SXin Li     case RetEffect::NoRet:
3070*67e74705SXin Li     case RetEffect::NoRetHard:
3071*67e74705SXin Li       // No work necessary.
3072*67e74705SXin Li       break;
3073*67e74705SXin Li 
3074*67e74705SXin Li     case RetEffect::OwnedAllocatedSymbol:
3075*67e74705SXin Li     case RetEffect::OwnedSymbol: {
3076*67e74705SXin Li       SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
3077*67e74705SXin Li       if (!Sym)
3078*67e74705SXin Li         break;
3079*67e74705SXin Li 
3080*67e74705SXin Li       // Use the result type from the CallEvent as it automatically adjusts
3081*67e74705SXin Li       // for methods/functions that return references.
3082*67e74705SXin Li       QualType ResultTy = CallOrMsg.getResultType();
3083*67e74705SXin Li       state = setRefBinding(state, Sym, RefVal::makeOwned(RE.getObjKind(),
3084*67e74705SXin Li                                                           ResultTy));
3085*67e74705SXin Li 
3086*67e74705SXin Li       // FIXME: Add a flag to the checker where allocations are assumed to
3087*67e74705SXin Li       // *not* fail.
3088*67e74705SXin Li       break;
3089*67e74705SXin Li     }
3090*67e74705SXin Li 
3091*67e74705SXin Li     case RetEffect::GCNotOwnedSymbol:
3092*67e74705SXin Li     case RetEffect::NotOwnedSymbol: {
3093*67e74705SXin Li       const Expr *Ex = CallOrMsg.getOriginExpr();
3094*67e74705SXin Li       SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
3095*67e74705SXin Li       if (!Sym)
3096*67e74705SXin Li         break;
3097*67e74705SXin Li       assert(Ex);
3098*67e74705SXin Li       // Use GetReturnType in order to give [NSFoo alloc] the type NSFoo *.
3099*67e74705SXin Li       QualType ResultTy = GetReturnType(Ex, C.getASTContext());
3100*67e74705SXin Li       state = setRefBinding(state, Sym, RefVal::makeNotOwned(RE.getObjKind(),
3101*67e74705SXin Li                                                              ResultTy));
3102*67e74705SXin Li       break;
3103*67e74705SXin Li     }
3104*67e74705SXin Li   }
3105*67e74705SXin Li 
3106*67e74705SXin Li   // This check is actually necessary; otherwise the statement builder thinks
3107*67e74705SXin Li   // we've hit a previously-found path.
3108*67e74705SXin Li   // Normally addTransition takes care of this, but we want the node pointer.
3109*67e74705SXin Li   ExplodedNode *NewNode;
3110*67e74705SXin Li   if (state == C.getState()) {
3111*67e74705SXin Li     NewNode = C.getPredecessor();
3112*67e74705SXin Li   } else {
3113*67e74705SXin Li     NewNode = C.addTransition(state);
3114*67e74705SXin Li   }
3115*67e74705SXin Li 
3116*67e74705SXin Li   // Annotate the node with summary we used.
3117*67e74705SXin Li   if (NewNode) {
3118*67e74705SXin Li     // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
3119*67e74705SXin Li     if (ShouldResetSummaryLog) {
3120*67e74705SXin Li       SummaryLog.clear();
3121*67e74705SXin Li       ShouldResetSummaryLog = false;
3122*67e74705SXin Li     }
3123*67e74705SXin Li     SummaryLog[NewNode] = &Summ;
3124*67e74705SXin Li   }
3125*67e74705SXin Li }
3126*67e74705SXin Li 
3127*67e74705SXin Li ProgramStateRef
updateSymbol(ProgramStateRef state,SymbolRef sym,RefVal V,ArgEffect E,RefVal::Kind & hasErr,CheckerContext & C) const3128*67e74705SXin Li RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
3129*67e74705SXin Li                                  RefVal V, ArgEffect E, RefVal::Kind &hasErr,
3130*67e74705SXin Li                                  CheckerContext &C) const {
3131*67e74705SXin Li   // In GC mode [... release] and [... retain] do nothing.
3132*67e74705SXin Li   // In ARC mode they shouldn't exist at all, but we just ignore them.
3133*67e74705SXin Li   bool IgnoreRetainMsg = C.isObjCGCEnabled();
3134*67e74705SXin Li   if (!IgnoreRetainMsg)
3135*67e74705SXin Li     IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
3136*67e74705SXin Li 
3137*67e74705SXin Li   switch (E) {
3138*67e74705SXin Li   default:
3139*67e74705SXin Li     break;
3140*67e74705SXin Li   case IncRefMsg:
3141*67e74705SXin Li     E = IgnoreRetainMsg ? DoNothing : IncRef;
3142*67e74705SXin Li     break;
3143*67e74705SXin Li   case DecRefMsg:
3144*67e74705SXin Li     E = IgnoreRetainMsg ? DoNothing : DecRef;
3145*67e74705SXin Li     break;
3146*67e74705SXin Li   case DecRefMsgAndStopTrackingHard:
3147*67e74705SXin Li     E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
3148*67e74705SXin Li     break;
3149*67e74705SXin Li   case MakeCollectable:
3150*67e74705SXin Li     E = C.isObjCGCEnabled() ? DecRef : DoNothing;
3151*67e74705SXin Li     break;
3152*67e74705SXin Li   }
3153*67e74705SXin Li 
3154*67e74705SXin Li   // Handle all use-after-releases.
3155*67e74705SXin Li   if (!C.isObjCGCEnabled() && V.getKind() == RefVal::Released) {
3156*67e74705SXin Li     V = V ^ RefVal::ErrorUseAfterRelease;
3157*67e74705SXin Li     hasErr = V.getKind();
3158*67e74705SXin Li     return setRefBinding(state, sym, V);
3159*67e74705SXin Li   }
3160*67e74705SXin Li 
3161*67e74705SXin Li   switch (E) {
3162*67e74705SXin Li     case DecRefMsg:
3163*67e74705SXin Li     case IncRefMsg:
3164*67e74705SXin Li     case MakeCollectable:
3165*67e74705SXin Li     case DecRefMsgAndStopTrackingHard:
3166*67e74705SXin Li       llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
3167*67e74705SXin Li 
3168*67e74705SXin Li     case UnretainedOutParameter:
3169*67e74705SXin Li     case RetainedOutParameter:
3170*67e74705SXin Li       llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
3171*67e74705SXin Li                        "not have ref state.");
3172*67e74705SXin Li 
3173*67e74705SXin Li     case Dealloc:
3174*67e74705SXin Li       // Any use of -dealloc in GC is *bad*.
3175*67e74705SXin Li       if (C.isObjCGCEnabled()) {
3176*67e74705SXin Li         V = V ^ RefVal::ErrorDeallocGC;
3177*67e74705SXin Li         hasErr = V.getKind();
3178*67e74705SXin Li         break;
3179*67e74705SXin Li       }
3180*67e74705SXin Li 
3181*67e74705SXin Li       switch (V.getKind()) {
3182*67e74705SXin Li         default:
3183*67e74705SXin Li           llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
3184*67e74705SXin Li         case RefVal::Owned:
3185*67e74705SXin Li           // The object immediately transitions to the released state.
3186*67e74705SXin Li           V = V ^ RefVal::Released;
3187*67e74705SXin Li           V.clearCounts();
3188*67e74705SXin Li           return setRefBinding(state, sym, V);
3189*67e74705SXin Li         case RefVal::NotOwned:
3190*67e74705SXin Li           V = V ^ RefVal::ErrorDeallocNotOwned;
3191*67e74705SXin Li           hasErr = V.getKind();
3192*67e74705SXin Li           break;
3193*67e74705SXin Li       }
3194*67e74705SXin Li       break;
3195*67e74705SXin Li 
3196*67e74705SXin Li     case MayEscape:
3197*67e74705SXin Li       if (V.getKind() == RefVal::Owned) {
3198*67e74705SXin Li         V = V ^ RefVal::NotOwned;
3199*67e74705SXin Li         break;
3200*67e74705SXin Li       }
3201*67e74705SXin Li 
3202*67e74705SXin Li       // Fall-through.
3203*67e74705SXin Li 
3204*67e74705SXin Li     case DoNothing:
3205*67e74705SXin Li       return state;
3206*67e74705SXin Li 
3207*67e74705SXin Li     case Autorelease:
3208*67e74705SXin Li       if (C.isObjCGCEnabled())
3209*67e74705SXin Li         return state;
3210*67e74705SXin Li       // Update the autorelease counts.
3211*67e74705SXin Li       V = V.autorelease();
3212*67e74705SXin Li       break;
3213*67e74705SXin Li 
3214*67e74705SXin Li     case StopTracking:
3215*67e74705SXin Li     case StopTrackingHard:
3216*67e74705SXin Li       return removeRefBinding(state, sym);
3217*67e74705SXin Li 
3218*67e74705SXin Li     case IncRef:
3219*67e74705SXin Li       switch (V.getKind()) {
3220*67e74705SXin Li         default:
3221*67e74705SXin Li           llvm_unreachable("Invalid RefVal state for a retain.");
3222*67e74705SXin Li         case RefVal::Owned:
3223*67e74705SXin Li         case RefVal::NotOwned:
3224*67e74705SXin Li           V = V + 1;
3225*67e74705SXin Li           break;
3226*67e74705SXin Li         case RefVal::Released:
3227*67e74705SXin Li           // Non-GC cases are handled above.
3228*67e74705SXin Li           assert(C.isObjCGCEnabled());
3229*67e74705SXin Li           V = (V ^ RefVal::Owned) + 1;
3230*67e74705SXin Li           break;
3231*67e74705SXin Li       }
3232*67e74705SXin Li       break;
3233*67e74705SXin Li 
3234*67e74705SXin Li     case DecRef:
3235*67e74705SXin Li     case DecRefBridgedTransferred:
3236*67e74705SXin Li     case DecRefAndStopTrackingHard:
3237*67e74705SXin Li       switch (V.getKind()) {
3238*67e74705SXin Li         default:
3239*67e74705SXin Li           // case 'RefVal::Released' handled above.
3240*67e74705SXin Li           llvm_unreachable("Invalid RefVal state for a release.");
3241*67e74705SXin Li 
3242*67e74705SXin Li         case RefVal::Owned:
3243*67e74705SXin Li           assert(V.getCount() > 0);
3244*67e74705SXin Li           if (V.getCount() == 1) {
3245*67e74705SXin Li             if (E == DecRefBridgedTransferred ||
3246*67e74705SXin Li                 V.getIvarAccessHistory() ==
3247*67e74705SXin Li                   RefVal::IvarAccessHistory::AccessedDirectly)
3248*67e74705SXin Li               V = V ^ RefVal::NotOwned;
3249*67e74705SXin Li             else
3250*67e74705SXin Li               V = V ^ RefVal::Released;
3251*67e74705SXin Li           } else if (E == DecRefAndStopTrackingHard) {
3252*67e74705SXin Li             return removeRefBinding(state, sym);
3253*67e74705SXin Li           }
3254*67e74705SXin Li 
3255*67e74705SXin Li           V = V - 1;
3256*67e74705SXin Li           break;
3257*67e74705SXin Li 
3258*67e74705SXin Li         case RefVal::NotOwned:
3259*67e74705SXin Li           if (V.getCount() > 0) {
3260*67e74705SXin Li             if (E == DecRefAndStopTrackingHard)
3261*67e74705SXin Li               return removeRefBinding(state, sym);
3262*67e74705SXin Li             V = V - 1;
3263*67e74705SXin Li           } else if (V.getIvarAccessHistory() ==
3264*67e74705SXin Li                        RefVal::IvarAccessHistory::AccessedDirectly) {
3265*67e74705SXin Li             // Assume that the instance variable was holding on the object at
3266*67e74705SXin Li             // +1, and we just didn't know.
3267*67e74705SXin Li             if (E == DecRefAndStopTrackingHard)
3268*67e74705SXin Li               return removeRefBinding(state, sym);
3269*67e74705SXin Li             V = V.releaseViaIvar() ^ RefVal::Released;
3270*67e74705SXin Li           } else {
3271*67e74705SXin Li             V = V ^ RefVal::ErrorReleaseNotOwned;
3272*67e74705SXin Li             hasErr = V.getKind();
3273*67e74705SXin Li           }
3274*67e74705SXin Li           break;
3275*67e74705SXin Li 
3276*67e74705SXin Li         case RefVal::Released:
3277*67e74705SXin Li           // Non-GC cases are handled above.
3278*67e74705SXin Li           assert(C.isObjCGCEnabled());
3279*67e74705SXin Li           V = V ^ RefVal::ErrorUseAfterRelease;
3280*67e74705SXin Li           hasErr = V.getKind();
3281*67e74705SXin Li           break;
3282*67e74705SXin Li       }
3283*67e74705SXin Li       break;
3284*67e74705SXin Li   }
3285*67e74705SXin Li   return setRefBinding(state, sym, V);
3286*67e74705SXin Li }
3287*67e74705SXin Li 
processNonLeakError(ProgramStateRef St,SourceRange ErrorRange,RefVal::Kind ErrorKind,SymbolRef Sym,CheckerContext & C) const3288*67e74705SXin Li void RetainCountChecker::processNonLeakError(ProgramStateRef St,
3289*67e74705SXin Li                                              SourceRange ErrorRange,
3290*67e74705SXin Li                                              RefVal::Kind ErrorKind,
3291*67e74705SXin Li                                              SymbolRef Sym,
3292*67e74705SXin Li                                              CheckerContext &C) const {
3293*67e74705SXin Li   // HACK: Ignore retain-count issues on values accessed through ivars,
3294*67e74705SXin Li   // because of cases like this:
3295*67e74705SXin Li   //   [_contentView retain];
3296*67e74705SXin Li   //   [_contentView removeFromSuperview];
3297*67e74705SXin Li   //   [self addSubview:_contentView]; // invalidates 'self'
3298*67e74705SXin Li   //   [_contentView release];
3299*67e74705SXin Li   if (const RefVal *RV = getRefBinding(St, Sym))
3300*67e74705SXin Li     if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3301*67e74705SXin Li       return;
3302*67e74705SXin Li 
3303*67e74705SXin Li   ExplodedNode *N = C.generateErrorNode(St);
3304*67e74705SXin Li   if (!N)
3305*67e74705SXin Li     return;
3306*67e74705SXin Li 
3307*67e74705SXin Li   CFRefBug *BT;
3308*67e74705SXin Li   switch (ErrorKind) {
3309*67e74705SXin Li     default:
3310*67e74705SXin Li       llvm_unreachable("Unhandled error.");
3311*67e74705SXin Li     case RefVal::ErrorUseAfterRelease:
3312*67e74705SXin Li       if (!useAfterRelease)
3313*67e74705SXin Li         useAfterRelease.reset(new UseAfterRelease(this));
3314*67e74705SXin Li       BT = useAfterRelease.get();
3315*67e74705SXin Li       break;
3316*67e74705SXin Li     case RefVal::ErrorReleaseNotOwned:
3317*67e74705SXin Li       if (!releaseNotOwned)
3318*67e74705SXin Li         releaseNotOwned.reset(new BadRelease(this));
3319*67e74705SXin Li       BT = releaseNotOwned.get();
3320*67e74705SXin Li       break;
3321*67e74705SXin Li     case RefVal::ErrorDeallocGC:
3322*67e74705SXin Li       if (!deallocGC)
3323*67e74705SXin Li         deallocGC.reset(new DeallocGC(this));
3324*67e74705SXin Li       BT = deallocGC.get();
3325*67e74705SXin Li       break;
3326*67e74705SXin Li     case RefVal::ErrorDeallocNotOwned:
3327*67e74705SXin Li       if (!deallocNotOwned)
3328*67e74705SXin Li         deallocNotOwned.reset(new DeallocNotOwned(this));
3329*67e74705SXin Li       BT = deallocNotOwned.get();
3330*67e74705SXin Li       break;
3331*67e74705SXin Li   }
3332*67e74705SXin Li 
3333*67e74705SXin Li   assert(BT);
3334*67e74705SXin Li   auto report = std::unique_ptr<BugReport>(
3335*67e74705SXin Li       new CFRefReport(*BT, C.getASTContext().getLangOpts(), C.isObjCGCEnabled(),
3336*67e74705SXin Li                       SummaryLog, N, Sym));
3337*67e74705SXin Li   report->addRange(ErrorRange);
3338*67e74705SXin Li   C.emitReport(std::move(report));
3339*67e74705SXin Li }
3340*67e74705SXin Li 
3341*67e74705SXin Li //===----------------------------------------------------------------------===//
3342*67e74705SXin Li // Handle the return values of retain-count-related functions.
3343*67e74705SXin Li //===----------------------------------------------------------------------===//
3344*67e74705SXin Li 
evalCall(const CallExpr * CE,CheckerContext & C) const3345*67e74705SXin Li bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
3346*67e74705SXin Li   // Get the callee. We're only interested in simple C functions.
3347*67e74705SXin Li   ProgramStateRef state = C.getState();
3348*67e74705SXin Li   const FunctionDecl *FD = C.getCalleeDecl(CE);
3349*67e74705SXin Li   if (!FD)
3350*67e74705SXin Li     return false;
3351*67e74705SXin Li 
3352*67e74705SXin Li   IdentifierInfo *II = FD->getIdentifier();
3353*67e74705SXin Li   if (!II)
3354*67e74705SXin Li     return false;
3355*67e74705SXin Li 
3356*67e74705SXin Li   // For now, we're only handling the functions that return aliases of their
3357*67e74705SXin Li   // arguments: CFRetain and CFMakeCollectable (and their families).
3358*67e74705SXin Li   // Eventually we should add other functions we can model entirely,
3359*67e74705SXin Li   // such as CFRelease, which don't invalidate their arguments or globals.
3360*67e74705SXin Li   if (CE->getNumArgs() != 1)
3361*67e74705SXin Li     return false;
3362*67e74705SXin Li 
3363*67e74705SXin Li   // Get the name of the function.
3364*67e74705SXin Li   StringRef FName = II->getName();
3365*67e74705SXin Li   FName = FName.substr(FName.find_first_not_of('_'));
3366*67e74705SXin Li 
3367*67e74705SXin Li   // See if it's one of the specific functions we know how to eval.
3368*67e74705SXin Li   bool canEval = false;
3369*67e74705SXin Li 
3370*67e74705SXin Li   QualType ResultTy = CE->getCallReturnType(C.getASTContext());
3371*67e74705SXin Li   if (ResultTy->isObjCIdType()) {
3372*67e74705SXin Li     // Handle: id NSMakeCollectable(CFTypeRef)
3373*67e74705SXin Li     canEval = II->isStr("NSMakeCollectable");
3374*67e74705SXin Li   } else if (ResultTy->isPointerType()) {
3375*67e74705SXin Li     // Handle: (CF|CG)Retain
3376*67e74705SXin Li     //         CFAutorelease
3377*67e74705SXin Li     //         CFMakeCollectable
3378*67e74705SXin Li     // It's okay to be a little sloppy here (CGMakeCollectable doesn't exist).
3379*67e74705SXin Li     if (cocoa::isRefType(ResultTy, "CF", FName) ||
3380*67e74705SXin Li         cocoa::isRefType(ResultTy, "CG", FName)) {
3381*67e74705SXin Li       canEval = isRetain(FD, FName) || isAutorelease(FD, FName) ||
3382*67e74705SXin Li                 isMakeCollectable(FD, FName);
3383*67e74705SXin Li     }
3384*67e74705SXin Li   }
3385*67e74705SXin Li 
3386*67e74705SXin Li   if (!canEval)
3387*67e74705SXin Li     return false;
3388*67e74705SXin Li 
3389*67e74705SXin Li   // Bind the return value.
3390*67e74705SXin Li   const LocationContext *LCtx = C.getLocationContext();
3391*67e74705SXin Li   SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
3392*67e74705SXin Li   if (RetVal.isUnknown()) {
3393*67e74705SXin Li     // If the receiver is unknown, conjure a return value.
3394*67e74705SXin Li     SValBuilder &SVB = C.getSValBuilder();
3395*67e74705SXin Li     RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
3396*67e74705SXin Li   }
3397*67e74705SXin Li   state = state->BindExpr(CE, LCtx, RetVal, false);
3398*67e74705SXin Li 
3399*67e74705SXin Li   // FIXME: This should not be necessary, but otherwise the argument seems to be
3400*67e74705SXin Li   // considered alive during the next statement.
3401*67e74705SXin Li   if (const MemRegion *ArgRegion = RetVal.getAsRegion()) {
3402*67e74705SXin Li     // Save the refcount status of the argument.
3403*67e74705SXin Li     SymbolRef Sym = RetVal.getAsLocSymbol();
3404*67e74705SXin Li     const RefVal *Binding = nullptr;
3405*67e74705SXin Li     if (Sym)
3406*67e74705SXin Li       Binding = getRefBinding(state, Sym);
3407*67e74705SXin Li 
3408*67e74705SXin Li     // Invalidate the argument region.
3409*67e74705SXin Li     state = state->invalidateRegions(ArgRegion, CE, C.blockCount(), LCtx,
3410*67e74705SXin Li                                      /*CausesPointerEscape*/ false);
3411*67e74705SXin Li 
3412*67e74705SXin Li     // Restore the refcount status of the argument.
3413*67e74705SXin Li     if (Binding)
3414*67e74705SXin Li       state = setRefBinding(state, Sym, *Binding);
3415*67e74705SXin Li   }
3416*67e74705SXin Li 
3417*67e74705SXin Li   C.addTransition(state);
3418*67e74705SXin Li   return true;
3419*67e74705SXin Li }
3420*67e74705SXin Li 
3421*67e74705SXin Li //===----------------------------------------------------------------------===//
3422*67e74705SXin Li // Handle return statements.
3423*67e74705SXin Li //===----------------------------------------------------------------------===//
3424*67e74705SXin Li 
checkPreStmt(const ReturnStmt * S,CheckerContext & C) const3425*67e74705SXin Li void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
3426*67e74705SXin Li                                       CheckerContext &C) const {
3427*67e74705SXin Li 
3428*67e74705SXin Li   // Only adjust the reference count if this is the top-level call frame,
3429*67e74705SXin Li   // and not the result of inlining.  In the future, we should do
3430*67e74705SXin Li   // better checking even for inlined calls, and see if they match
3431*67e74705SXin Li   // with their expected semantics (e.g., the method should return a retained
3432*67e74705SXin Li   // object, etc.).
3433*67e74705SXin Li   if (!C.inTopFrame())
3434*67e74705SXin Li     return;
3435*67e74705SXin Li 
3436*67e74705SXin Li   const Expr *RetE = S->getRetValue();
3437*67e74705SXin Li   if (!RetE)
3438*67e74705SXin Li     return;
3439*67e74705SXin Li 
3440*67e74705SXin Li   ProgramStateRef state = C.getState();
3441*67e74705SXin Li   SymbolRef Sym =
3442*67e74705SXin Li     state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
3443*67e74705SXin Li   if (!Sym)
3444*67e74705SXin Li     return;
3445*67e74705SXin Li 
3446*67e74705SXin Li   // Get the reference count binding (if any).
3447*67e74705SXin Li   const RefVal *T = getRefBinding(state, Sym);
3448*67e74705SXin Li   if (!T)
3449*67e74705SXin Li     return;
3450*67e74705SXin Li 
3451*67e74705SXin Li   // Change the reference count.
3452*67e74705SXin Li   RefVal X = *T;
3453*67e74705SXin Li 
3454*67e74705SXin Li   switch (X.getKind()) {
3455*67e74705SXin Li     case RefVal::Owned: {
3456*67e74705SXin Li       unsigned cnt = X.getCount();
3457*67e74705SXin Li       assert(cnt > 0);
3458*67e74705SXin Li       X.setCount(cnt - 1);
3459*67e74705SXin Li       X = X ^ RefVal::ReturnedOwned;
3460*67e74705SXin Li       break;
3461*67e74705SXin Li     }
3462*67e74705SXin Li 
3463*67e74705SXin Li     case RefVal::NotOwned: {
3464*67e74705SXin Li       unsigned cnt = X.getCount();
3465*67e74705SXin Li       if (cnt) {
3466*67e74705SXin Li         X.setCount(cnt - 1);
3467*67e74705SXin Li         X = X ^ RefVal::ReturnedOwned;
3468*67e74705SXin Li       }
3469*67e74705SXin Li       else {
3470*67e74705SXin Li         X = X ^ RefVal::ReturnedNotOwned;
3471*67e74705SXin Li       }
3472*67e74705SXin Li       break;
3473*67e74705SXin Li     }
3474*67e74705SXin Li 
3475*67e74705SXin Li     default:
3476*67e74705SXin Li       return;
3477*67e74705SXin Li   }
3478*67e74705SXin Li 
3479*67e74705SXin Li   // Update the binding.
3480*67e74705SXin Li   state = setRefBinding(state, Sym, X);
3481*67e74705SXin Li   ExplodedNode *Pred = C.addTransition(state);
3482*67e74705SXin Li 
3483*67e74705SXin Li   // At this point we have updated the state properly.
3484*67e74705SXin Li   // Everything after this is merely checking to see if the return value has
3485*67e74705SXin Li   // been over- or under-retained.
3486*67e74705SXin Li 
3487*67e74705SXin Li   // Did we cache out?
3488*67e74705SXin Li   if (!Pred)
3489*67e74705SXin Li     return;
3490*67e74705SXin Li 
3491*67e74705SXin Li   // Update the autorelease counts.
3492*67e74705SXin Li   static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
3493*67e74705SXin Li   state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3494*67e74705SXin Li 
3495*67e74705SXin Li   // Did we cache out?
3496*67e74705SXin Li   if (!state)
3497*67e74705SXin Li     return;
3498*67e74705SXin Li 
3499*67e74705SXin Li   // Get the updated binding.
3500*67e74705SXin Li   T = getRefBinding(state, Sym);
3501*67e74705SXin Li   assert(T);
3502*67e74705SXin Li   X = *T;
3503*67e74705SXin Li 
3504*67e74705SXin Li   // Consult the summary of the enclosing method.
3505*67e74705SXin Li   RetainSummaryManager &Summaries = getSummaryManager(C);
3506*67e74705SXin Li   const Decl *CD = &Pred->getCodeDecl();
3507*67e74705SXin Li   RetEffect RE = RetEffect::MakeNoRet();
3508*67e74705SXin Li 
3509*67e74705SXin Li   // FIXME: What is the convention for blocks? Is there one?
3510*67e74705SXin Li   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
3511*67e74705SXin Li     const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3512*67e74705SXin Li     RE = Summ->getRetEffect();
3513*67e74705SXin Li   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3514*67e74705SXin Li     if (!isa<CXXMethodDecl>(FD)) {
3515*67e74705SXin Li       const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3516*67e74705SXin Li       RE = Summ->getRetEffect();
3517*67e74705SXin Li     }
3518*67e74705SXin Li   }
3519*67e74705SXin Li 
3520*67e74705SXin Li   checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3521*67e74705SXin Li }
3522*67e74705SXin Li 
checkReturnWithRetEffect(const ReturnStmt * S,CheckerContext & C,ExplodedNode * Pred,RetEffect RE,RefVal X,SymbolRef Sym,ProgramStateRef state) const3523*67e74705SXin Li void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
3524*67e74705SXin Li                                                   CheckerContext &C,
3525*67e74705SXin Li                                                   ExplodedNode *Pred,
3526*67e74705SXin Li                                                   RetEffect RE, RefVal X,
3527*67e74705SXin Li                                                   SymbolRef Sym,
3528*67e74705SXin Li                                                   ProgramStateRef state) const {
3529*67e74705SXin Li   // HACK: Ignore retain-count issues on values accessed through ivars,
3530*67e74705SXin Li   // because of cases like this:
3531*67e74705SXin Li   //   [_contentView retain];
3532*67e74705SXin Li   //   [_contentView removeFromSuperview];
3533*67e74705SXin Li   //   [self addSubview:_contentView]; // invalidates 'self'
3534*67e74705SXin Li   //   [_contentView release];
3535*67e74705SXin Li   if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3536*67e74705SXin Li     return;
3537*67e74705SXin Li 
3538*67e74705SXin Li   // Any leaks or other errors?
3539*67e74705SXin Li   if (X.isReturnedOwned() && X.getCount() == 0) {
3540*67e74705SXin Li     if (RE.getKind() != RetEffect::NoRet) {
3541*67e74705SXin Li       bool hasError = false;
3542*67e74705SXin Li       if (C.isObjCGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
3543*67e74705SXin Li         // Things are more complicated with garbage collection.  If the
3544*67e74705SXin Li         // returned object is suppose to be an Objective-C object, we have
3545*67e74705SXin Li         // a leak (as the caller expects a GC'ed object) because no
3546*67e74705SXin Li         // method should return ownership unless it returns a CF object.
3547*67e74705SXin Li         hasError = true;
3548*67e74705SXin Li         X = X ^ RefVal::ErrorGCLeakReturned;
3549*67e74705SXin Li       }
3550*67e74705SXin Li       else if (!RE.isOwned()) {
3551*67e74705SXin Li         // Either we are using GC and the returned object is a CF type
3552*67e74705SXin Li         // or we aren't using GC.  In either case, we expect that the
3553*67e74705SXin Li         // enclosing method is expected to return ownership.
3554*67e74705SXin Li         hasError = true;
3555*67e74705SXin Li         X = X ^ RefVal::ErrorLeakReturned;
3556*67e74705SXin Li       }
3557*67e74705SXin Li 
3558*67e74705SXin Li       if (hasError) {
3559*67e74705SXin Li         // Generate an error node.
3560*67e74705SXin Li         state = setRefBinding(state, Sym, X);
3561*67e74705SXin Li 
3562*67e74705SXin Li         static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
3563*67e74705SXin Li         ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
3564*67e74705SXin Li         if (N) {
3565*67e74705SXin Li           const LangOptions &LOpts = C.getASTContext().getLangOpts();
3566*67e74705SXin Li           bool GCEnabled = C.isObjCGCEnabled();
3567*67e74705SXin Li           C.emitReport(std::unique_ptr<BugReport>(new CFRefLeakReport(
3568*67e74705SXin Li               *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
3569*67e74705SXin Li               SummaryLog, N, Sym, C, IncludeAllocationLine)));
3570*67e74705SXin Li         }
3571*67e74705SXin Li       }
3572*67e74705SXin Li     }
3573*67e74705SXin Li   } else if (X.isReturnedNotOwned()) {
3574*67e74705SXin Li     if (RE.isOwned()) {
3575*67e74705SXin Li       if (X.getIvarAccessHistory() ==
3576*67e74705SXin Li             RefVal::IvarAccessHistory::AccessedDirectly) {
3577*67e74705SXin Li         // Assume the method was trying to transfer a +1 reference from a
3578*67e74705SXin Li         // strong ivar to the caller.
3579*67e74705SXin Li         state = setRefBinding(state, Sym,
3580*67e74705SXin Li                               X.releaseViaIvar() ^ RefVal::ReturnedOwned);
3581*67e74705SXin Li       } else {
3582*67e74705SXin Li         // Trying to return a not owned object to a caller expecting an
3583*67e74705SXin Li         // owned object.
3584*67e74705SXin Li         state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3585*67e74705SXin Li 
3586*67e74705SXin Li         static CheckerProgramPointTag
3587*67e74705SXin Li             ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
3588*67e74705SXin Li 
3589*67e74705SXin Li         ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
3590*67e74705SXin Li         if (N) {
3591*67e74705SXin Li           if (!returnNotOwnedForOwned)
3592*67e74705SXin Li             returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
3593*67e74705SXin Li 
3594*67e74705SXin Li           C.emitReport(std::unique_ptr<BugReport>(new CFRefReport(
3595*67e74705SXin Li               *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
3596*67e74705SXin Li               C.isObjCGCEnabled(), SummaryLog, N, Sym)));
3597*67e74705SXin Li         }
3598*67e74705SXin Li       }
3599*67e74705SXin Li     }
3600*67e74705SXin Li   }
3601*67e74705SXin Li }
3602*67e74705SXin Li 
3603*67e74705SXin Li //===----------------------------------------------------------------------===//
3604*67e74705SXin Li // Check various ways a symbol can be invalidated.
3605*67e74705SXin Li //===----------------------------------------------------------------------===//
3606*67e74705SXin Li 
checkBind(SVal loc,SVal val,const Stmt * S,CheckerContext & C) const3607*67e74705SXin Li void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
3608*67e74705SXin Li                                    CheckerContext &C) const {
3609*67e74705SXin Li   // Are we storing to something that causes the value to "escape"?
3610*67e74705SXin Li   bool escapes = true;
3611*67e74705SXin Li 
3612*67e74705SXin Li   // A value escapes in three possible cases (this may change):
3613*67e74705SXin Li   //
3614*67e74705SXin Li   // (1) we are binding to something that is not a memory region.
3615*67e74705SXin Li   // (2) we are binding to a memregion that does not have stack storage
3616*67e74705SXin Li   // (3) we are binding to a memregion with stack storage that the store
3617*67e74705SXin Li   //     does not understand.
3618*67e74705SXin Li   ProgramStateRef state = C.getState();
3619*67e74705SXin Li 
3620*67e74705SXin Li   if (Optional<loc::MemRegionVal> regionLoc = loc.getAs<loc::MemRegionVal>()) {
3621*67e74705SXin Li     escapes = !regionLoc->getRegion()->hasStackStorage();
3622*67e74705SXin Li 
3623*67e74705SXin Li     if (!escapes) {
3624*67e74705SXin Li       // To test (3), generate a new state with the binding added.  If it is
3625*67e74705SXin Li       // the same state, then it escapes (since the store cannot represent
3626*67e74705SXin Li       // the binding).
3627*67e74705SXin Li       // Do this only if we know that the store is not supposed to generate the
3628*67e74705SXin Li       // same state.
3629*67e74705SXin Li       SVal StoredVal = state->getSVal(regionLoc->getRegion());
3630*67e74705SXin Li       if (StoredVal != val)
3631*67e74705SXin Li         escapes = (state == (state->bindLoc(*regionLoc, val)));
3632*67e74705SXin Li     }
3633*67e74705SXin Li     if (!escapes) {
3634*67e74705SXin Li       // Case 4: We do not currently model what happens when a symbol is
3635*67e74705SXin Li       // assigned to a struct field, so be conservative here and let the symbol
3636*67e74705SXin Li       // go. TODO: This could definitely be improved upon.
3637*67e74705SXin Li       escapes = !isa<VarRegion>(regionLoc->getRegion());
3638*67e74705SXin Li     }
3639*67e74705SXin Li   }
3640*67e74705SXin Li 
3641*67e74705SXin Li   // If we are storing the value into an auto function scope variable annotated
3642*67e74705SXin Li   // with (__attribute__((cleanup))), stop tracking the value to avoid leak
3643*67e74705SXin Li   // false positives.
3644*67e74705SXin Li   if (const VarRegion *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
3645*67e74705SXin Li     const VarDecl *VD = LVR->getDecl();
3646*67e74705SXin Li     if (VD->hasAttr<CleanupAttr>()) {
3647*67e74705SXin Li       escapes = true;
3648*67e74705SXin Li     }
3649*67e74705SXin Li   }
3650*67e74705SXin Li 
3651*67e74705SXin Li   // If our store can represent the binding and we aren't storing to something
3652*67e74705SXin Li   // that doesn't have local storage then just return and have the simulation
3653*67e74705SXin Li   // state continue as is.
3654*67e74705SXin Li   if (!escapes)
3655*67e74705SXin Li       return;
3656*67e74705SXin Li 
3657*67e74705SXin Li   // Otherwise, find all symbols referenced by 'val' that we are tracking
3658*67e74705SXin Li   // and stop tracking them.
3659*67e74705SXin Li   state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3660*67e74705SXin Li   C.addTransition(state);
3661*67e74705SXin Li }
3662*67e74705SXin Li 
evalAssume(ProgramStateRef state,SVal Cond,bool Assumption) const3663*67e74705SXin Li ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
3664*67e74705SXin Li                                                    SVal Cond,
3665*67e74705SXin Li                                                    bool Assumption) const {
3666*67e74705SXin Li   // FIXME: We may add to the interface of evalAssume the list of symbols
3667*67e74705SXin Li   //  whose assumptions have changed.  For now we just iterate through the
3668*67e74705SXin Li   //  bindings and check if any of the tracked symbols are NULL.  This isn't
3669*67e74705SXin Li   //  too bad since the number of symbols we will track in practice are
3670*67e74705SXin Li   //  probably small and evalAssume is only called at branches and a few
3671*67e74705SXin Li   //  other places.
3672*67e74705SXin Li   RefBindingsTy B = state->get<RefBindings>();
3673*67e74705SXin Li 
3674*67e74705SXin Li   if (B.isEmpty())
3675*67e74705SXin Li     return state;
3676*67e74705SXin Li 
3677*67e74705SXin Li   bool changed = false;
3678*67e74705SXin Li   RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
3679*67e74705SXin Li 
3680*67e74705SXin Li   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3681*67e74705SXin Li     // Check if the symbol is null stop tracking the symbol.
3682*67e74705SXin Li     ConstraintManager &CMgr = state->getConstraintManager();
3683*67e74705SXin Li     ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
3684*67e74705SXin Li     if (AllocFailed.isConstrainedTrue()) {
3685*67e74705SXin Li       changed = true;
3686*67e74705SXin Li       B = RefBFactory.remove(B, I.getKey());
3687*67e74705SXin Li     }
3688*67e74705SXin Li   }
3689*67e74705SXin Li 
3690*67e74705SXin Li   if (changed)
3691*67e74705SXin Li     state = state->set<RefBindings>(B);
3692*67e74705SXin Li 
3693*67e74705SXin Li   return state;
3694*67e74705SXin Li }
3695*67e74705SXin Li 
3696*67e74705SXin Li ProgramStateRef
checkRegionChanges(ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > ExplicitRegions,ArrayRef<const MemRegion * > Regions,const CallEvent * Call) const3697*67e74705SXin Li RetainCountChecker::checkRegionChanges(ProgramStateRef state,
3698*67e74705SXin Li                                     const InvalidatedSymbols *invalidated,
3699*67e74705SXin Li                                     ArrayRef<const MemRegion *> ExplicitRegions,
3700*67e74705SXin Li                                     ArrayRef<const MemRegion *> Regions,
3701*67e74705SXin Li                                     const CallEvent *Call) const {
3702*67e74705SXin Li   if (!invalidated)
3703*67e74705SXin Li     return state;
3704*67e74705SXin Li 
3705*67e74705SXin Li   llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
3706*67e74705SXin Li   for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
3707*67e74705SXin Li        E = ExplicitRegions.end(); I != E; ++I) {
3708*67e74705SXin Li     if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
3709*67e74705SXin Li       WhitelistedSymbols.insert(SR->getSymbol());
3710*67e74705SXin Li   }
3711*67e74705SXin Li 
3712*67e74705SXin Li   for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
3713*67e74705SXin Li        E = invalidated->end(); I!=E; ++I) {
3714*67e74705SXin Li     SymbolRef sym = *I;
3715*67e74705SXin Li     if (WhitelistedSymbols.count(sym))
3716*67e74705SXin Li       continue;
3717*67e74705SXin Li     // Remove any existing reference-count binding.
3718*67e74705SXin Li     state = removeRefBinding(state, sym);
3719*67e74705SXin Li   }
3720*67e74705SXin Li   return state;
3721*67e74705SXin Li }
3722*67e74705SXin Li 
3723*67e74705SXin Li //===----------------------------------------------------------------------===//
3724*67e74705SXin Li // Handle dead symbols and end-of-path.
3725*67e74705SXin Li //===----------------------------------------------------------------------===//
3726*67e74705SXin Li 
3727*67e74705SXin Li ProgramStateRef
handleAutoreleaseCounts(ProgramStateRef state,ExplodedNode * Pred,const ProgramPointTag * Tag,CheckerContext & Ctx,SymbolRef Sym,RefVal V) const3728*67e74705SXin Li RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
3729*67e74705SXin Li                                             ExplodedNode *Pred,
3730*67e74705SXin Li                                             const ProgramPointTag *Tag,
3731*67e74705SXin Li                                             CheckerContext &Ctx,
3732*67e74705SXin Li                                             SymbolRef Sym, RefVal V) const {
3733*67e74705SXin Li   unsigned ACnt = V.getAutoreleaseCount();
3734*67e74705SXin Li 
3735*67e74705SXin Li   // No autorelease counts?  Nothing to be done.
3736*67e74705SXin Li   if (!ACnt)
3737*67e74705SXin Li     return state;
3738*67e74705SXin Li 
3739*67e74705SXin Li   assert(!Ctx.isObjCGCEnabled() && "Autorelease counts in GC mode?");
3740*67e74705SXin Li   unsigned Cnt = V.getCount();
3741*67e74705SXin Li 
3742*67e74705SXin Li   // FIXME: Handle sending 'autorelease' to already released object.
3743*67e74705SXin Li 
3744*67e74705SXin Li   if (V.getKind() == RefVal::ReturnedOwned)
3745*67e74705SXin Li     ++Cnt;
3746*67e74705SXin Li 
3747*67e74705SXin Li   // If we would over-release here, but we know the value came from an ivar,
3748*67e74705SXin Li   // assume it was a strong ivar that's just been relinquished.
3749*67e74705SXin Li   if (ACnt > Cnt &&
3750*67e74705SXin Li       V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
3751*67e74705SXin Li     V = V.releaseViaIvar();
3752*67e74705SXin Li     --ACnt;
3753*67e74705SXin Li   }
3754*67e74705SXin Li 
3755*67e74705SXin Li   if (ACnt <= Cnt) {
3756*67e74705SXin Li     if (ACnt == Cnt) {
3757*67e74705SXin Li       V.clearCounts();
3758*67e74705SXin Li       if (V.getKind() == RefVal::ReturnedOwned)
3759*67e74705SXin Li         V = V ^ RefVal::ReturnedNotOwned;
3760*67e74705SXin Li       else
3761*67e74705SXin Li         V = V ^ RefVal::NotOwned;
3762*67e74705SXin Li     } else {
3763*67e74705SXin Li       V.setCount(V.getCount() - ACnt);
3764*67e74705SXin Li       V.setAutoreleaseCount(0);
3765*67e74705SXin Li     }
3766*67e74705SXin Li     return setRefBinding(state, Sym, V);
3767*67e74705SXin Li   }
3768*67e74705SXin Li 
3769*67e74705SXin Li   // HACK: Ignore retain-count issues on values accessed through ivars,
3770*67e74705SXin Li   // because of cases like this:
3771*67e74705SXin Li   //   [_contentView retain];
3772*67e74705SXin Li   //   [_contentView removeFromSuperview];
3773*67e74705SXin Li   //   [self addSubview:_contentView]; // invalidates 'self'
3774*67e74705SXin Li   //   [_contentView release];
3775*67e74705SXin Li   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3776*67e74705SXin Li     return state;
3777*67e74705SXin Li 
3778*67e74705SXin Li   // Woah!  More autorelease counts then retain counts left.
3779*67e74705SXin Li   // Emit hard error.
3780*67e74705SXin Li   V = V ^ RefVal::ErrorOverAutorelease;
3781*67e74705SXin Li   state = setRefBinding(state, Sym, V);
3782*67e74705SXin Li 
3783*67e74705SXin Li   ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
3784*67e74705SXin Li   if (N) {
3785*67e74705SXin Li     SmallString<128> sbuf;
3786*67e74705SXin Li     llvm::raw_svector_ostream os(sbuf);
3787*67e74705SXin Li     os << "Object was autoreleased ";
3788*67e74705SXin Li     if (V.getAutoreleaseCount() > 1)
3789*67e74705SXin Li       os << V.getAutoreleaseCount() << " times but the object ";
3790*67e74705SXin Li     else
3791*67e74705SXin Li       os << "but ";
3792*67e74705SXin Li     os << "has a +" << V.getCount() << " retain count";
3793*67e74705SXin Li 
3794*67e74705SXin Li     if (!overAutorelease)
3795*67e74705SXin Li       overAutorelease.reset(new OverAutorelease(this));
3796*67e74705SXin Li 
3797*67e74705SXin Li     const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
3798*67e74705SXin Li     Ctx.emitReport(std::unique_ptr<BugReport>(
3799*67e74705SXin Li         new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
3800*67e74705SXin Li                         SummaryLog, N, Sym, os.str())));
3801*67e74705SXin Li   }
3802*67e74705SXin Li 
3803*67e74705SXin Li   return nullptr;
3804*67e74705SXin Li }
3805*67e74705SXin Li 
3806*67e74705SXin Li ProgramStateRef
handleSymbolDeath(ProgramStateRef state,SymbolRef sid,RefVal V,SmallVectorImpl<SymbolRef> & Leaked) const3807*67e74705SXin Li RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
3808*67e74705SXin Li                                       SymbolRef sid, RefVal V,
3809*67e74705SXin Li                                     SmallVectorImpl<SymbolRef> &Leaked) const {
3810*67e74705SXin Li   bool hasLeak;
3811*67e74705SXin Li 
3812*67e74705SXin Li   // HACK: Ignore retain-count issues on values accessed through ivars,
3813*67e74705SXin Li   // because of cases like this:
3814*67e74705SXin Li   //   [_contentView retain];
3815*67e74705SXin Li   //   [_contentView removeFromSuperview];
3816*67e74705SXin Li   //   [self addSubview:_contentView]; // invalidates 'self'
3817*67e74705SXin Li   //   [_contentView release];
3818*67e74705SXin Li   if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3819*67e74705SXin Li     hasLeak = false;
3820*67e74705SXin Li   else if (V.isOwned())
3821*67e74705SXin Li     hasLeak = true;
3822*67e74705SXin Li   else if (V.isNotOwned() || V.isReturnedOwned())
3823*67e74705SXin Li     hasLeak = (V.getCount() > 0);
3824*67e74705SXin Li   else
3825*67e74705SXin Li     hasLeak = false;
3826*67e74705SXin Li 
3827*67e74705SXin Li   if (!hasLeak)
3828*67e74705SXin Li     return removeRefBinding(state, sid);
3829*67e74705SXin Li 
3830*67e74705SXin Li   Leaked.push_back(sid);
3831*67e74705SXin Li   return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
3832*67e74705SXin Li }
3833*67e74705SXin Li 
3834*67e74705SXin Li ExplodedNode *
processLeaks(ProgramStateRef state,SmallVectorImpl<SymbolRef> & Leaked,CheckerContext & Ctx,ExplodedNode * Pred) const3835*67e74705SXin Li RetainCountChecker::processLeaks(ProgramStateRef state,
3836*67e74705SXin Li                                  SmallVectorImpl<SymbolRef> &Leaked,
3837*67e74705SXin Li                                  CheckerContext &Ctx,
3838*67e74705SXin Li                                  ExplodedNode *Pred) const {
3839*67e74705SXin Li   // Generate an intermediate node representing the leak point.
3840*67e74705SXin Li   ExplodedNode *N = Ctx.addTransition(state, Pred);
3841*67e74705SXin Li 
3842*67e74705SXin Li   if (N) {
3843*67e74705SXin Li     for (SmallVectorImpl<SymbolRef>::iterator
3844*67e74705SXin Li          I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
3845*67e74705SXin Li 
3846*67e74705SXin Li       const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
3847*67e74705SXin Li       bool GCEnabled = Ctx.isObjCGCEnabled();
3848*67e74705SXin Li       CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
3849*67e74705SXin Li                           : getLeakAtReturnBug(LOpts, GCEnabled);
3850*67e74705SXin Li       assert(BT && "BugType not initialized.");
3851*67e74705SXin Li 
3852*67e74705SXin Li       Ctx.emitReport(std::unique_ptr<BugReport>(
3853*67e74705SXin Li           new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
3854*67e74705SXin Li                               IncludeAllocationLine)));
3855*67e74705SXin Li     }
3856*67e74705SXin Li   }
3857*67e74705SXin Li 
3858*67e74705SXin Li   return N;
3859*67e74705SXin Li }
3860*67e74705SXin Li 
checkEndFunction(CheckerContext & Ctx) const3861*67e74705SXin Li void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
3862*67e74705SXin Li   ProgramStateRef state = Ctx.getState();
3863*67e74705SXin Li   RefBindingsTy B = state->get<RefBindings>();
3864*67e74705SXin Li   ExplodedNode *Pred = Ctx.getPredecessor();
3865*67e74705SXin Li 
3866*67e74705SXin Li   // Don't process anything within synthesized bodies.
3867*67e74705SXin Li   const LocationContext *LCtx = Pred->getLocationContext();
3868*67e74705SXin Li   if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
3869*67e74705SXin Li     assert(LCtx->getParent());
3870*67e74705SXin Li     return;
3871*67e74705SXin Li   }
3872*67e74705SXin Li 
3873*67e74705SXin Li   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3874*67e74705SXin Li     state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
3875*67e74705SXin Li                                     I->first, I->second);
3876*67e74705SXin Li     if (!state)
3877*67e74705SXin Li       return;
3878*67e74705SXin Li   }
3879*67e74705SXin Li 
3880*67e74705SXin Li   // If the current LocationContext has a parent, don't check for leaks.
3881*67e74705SXin Li   // We will do that later.
3882*67e74705SXin Li   // FIXME: we should instead check for imbalances of the retain/releases,
3883*67e74705SXin Li   // and suggest annotations.
3884*67e74705SXin Li   if (LCtx->getParent())
3885*67e74705SXin Li     return;
3886*67e74705SXin Li 
3887*67e74705SXin Li   B = state->get<RefBindings>();
3888*67e74705SXin Li   SmallVector<SymbolRef, 10> Leaked;
3889*67e74705SXin Li 
3890*67e74705SXin Li   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
3891*67e74705SXin Li     state = handleSymbolDeath(state, I->first, I->second, Leaked);
3892*67e74705SXin Li 
3893*67e74705SXin Li   processLeaks(state, Leaked, Ctx, Pred);
3894*67e74705SXin Li }
3895*67e74705SXin Li 
3896*67e74705SXin Li const ProgramPointTag *
getDeadSymbolTag(SymbolRef sym) const3897*67e74705SXin Li RetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
3898*67e74705SXin Li   const CheckerProgramPointTag *&tag = DeadSymbolTags[sym];
3899*67e74705SXin Li   if (!tag) {
3900*67e74705SXin Li     SmallString<64> buf;
3901*67e74705SXin Li     llvm::raw_svector_ostream out(buf);
3902*67e74705SXin Li     out << "Dead Symbol : ";
3903*67e74705SXin Li     sym->dumpToStream(out);
3904*67e74705SXin Li     tag = new CheckerProgramPointTag(this, out.str());
3905*67e74705SXin Li   }
3906*67e74705SXin Li   return tag;
3907*67e74705SXin Li }
3908*67e74705SXin Li 
checkDeadSymbols(SymbolReaper & SymReaper,CheckerContext & C) const3909*67e74705SXin Li void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
3910*67e74705SXin Li                                           CheckerContext &C) const {
3911*67e74705SXin Li   ExplodedNode *Pred = C.getPredecessor();
3912*67e74705SXin Li 
3913*67e74705SXin Li   ProgramStateRef state = C.getState();
3914*67e74705SXin Li   RefBindingsTy B = state->get<RefBindings>();
3915*67e74705SXin Li   SmallVector<SymbolRef, 10> Leaked;
3916*67e74705SXin Li 
3917*67e74705SXin Li   // Update counts from autorelease pools
3918*67e74705SXin Li   for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3919*67e74705SXin Li        E = SymReaper.dead_end(); I != E; ++I) {
3920*67e74705SXin Li     SymbolRef Sym = *I;
3921*67e74705SXin Li     if (const RefVal *T = B.lookup(Sym)){
3922*67e74705SXin Li       // Use the symbol as the tag.
3923*67e74705SXin Li       // FIXME: This might not be as unique as we would like.
3924*67e74705SXin Li       const ProgramPointTag *Tag = getDeadSymbolTag(Sym);
3925*67e74705SXin Li       state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
3926*67e74705SXin Li       if (!state)
3927*67e74705SXin Li         return;
3928*67e74705SXin Li 
3929*67e74705SXin Li       // Fetch the new reference count from the state, and use it to handle
3930*67e74705SXin Li       // this symbol.
3931*67e74705SXin Li       state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked);
3932*67e74705SXin Li     }
3933*67e74705SXin Li   }
3934*67e74705SXin Li 
3935*67e74705SXin Li   if (Leaked.empty()) {
3936*67e74705SXin Li     C.addTransition(state);
3937*67e74705SXin Li     return;
3938*67e74705SXin Li   }
3939*67e74705SXin Li 
3940*67e74705SXin Li   Pred = processLeaks(state, Leaked, C, Pred);
3941*67e74705SXin Li 
3942*67e74705SXin Li   // Did we cache out?
3943*67e74705SXin Li   if (!Pred)
3944*67e74705SXin Li     return;
3945*67e74705SXin Li 
3946*67e74705SXin Li   // Now generate a new node that nukes the old bindings.
3947*67e74705SXin Li   // The only bindings left at this point are the leaked symbols.
3948*67e74705SXin Li   RefBindingsTy::Factory &F = state->get_context<RefBindings>();
3949*67e74705SXin Li   B = state->get<RefBindings>();
3950*67e74705SXin Li 
3951*67e74705SXin Li   for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
3952*67e74705SXin Li                                             E = Leaked.end();
3953*67e74705SXin Li        I != E; ++I)
3954*67e74705SXin Li     B = F.remove(B, *I);
3955*67e74705SXin Li 
3956*67e74705SXin Li   state = state->set<RefBindings>(B);
3957*67e74705SXin Li   C.addTransition(state, Pred);
3958*67e74705SXin Li }
3959*67e74705SXin Li 
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep) const3960*67e74705SXin Li void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
3961*67e74705SXin Li                                     const char *NL, const char *Sep) const {
3962*67e74705SXin Li 
3963*67e74705SXin Li   RefBindingsTy B = State->get<RefBindings>();
3964*67e74705SXin Li 
3965*67e74705SXin Li   if (B.isEmpty())
3966*67e74705SXin Li     return;
3967*67e74705SXin Li 
3968*67e74705SXin Li   Out << Sep << NL;
3969*67e74705SXin Li 
3970*67e74705SXin Li   for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3971*67e74705SXin Li     Out << I->first << " : ";
3972*67e74705SXin Li     I->second.print(Out);
3973*67e74705SXin Li     Out << NL;
3974*67e74705SXin Li   }
3975*67e74705SXin Li }
3976*67e74705SXin Li 
3977*67e74705SXin Li //===----------------------------------------------------------------------===//
3978*67e74705SXin Li // Checker registration.
3979*67e74705SXin Li //===----------------------------------------------------------------------===//
3980*67e74705SXin Li 
registerRetainCountChecker(CheckerManager & Mgr)3981*67e74705SXin Li void ento::registerRetainCountChecker(CheckerManager &Mgr) {
3982*67e74705SXin Li   Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions());
3983*67e74705SXin Li }
3984*67e74705SXin Li 
3985*67e74705SXin Li //===----------------------------------------------------------------------===//
3986*67e74705SXin Li // Implementation of the CallEffects API.
3987*67e74705SXin Li //===----------------------------------------------------------------------===//
3988*67e74705SXin Li 
3989*67e74705SXin Li namespace clang {
3990*67e74705SXin Li namespace ento {
3991*67e74705SXin Li namespace objc_retain {
3992*67e74705SXin Li 
3993*67e74705SXin Li // This is a bit gross, but it allows us to populate CallEffects without
3994*67e74705SXin Li // creating a bunch of accessors.  This kind is very localized, so the
3995*67e74705SXin Li // damage of this macro is limited.
3996*67e74705SXin Li #define createCallEffect(D, KIND)\
3997*67e74705SXin Li   ASTContext &Ctx = D->getASTContext();\
3998*67e74705SXin Li   LangOptions L = Ctx.getLangOpts();\
3999*67e74705SXin Li   RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\
4000*67e74705SXin Li   const RetainSummary *S = M.get ## KIND ## Summary(D);\
4001*67e74705SXin Li   CallEffects CE(S->getRetEffect());\
4002*67e74705SXin Li   CE.Receiver = S->getReceiverEffect();\
4003*67e74705SXin Li   unsigned N = D->param_size();\
4004*67e74705SXin Li   for (unsigned i = 0; i < N; ++i) {\
4005*67e74705SXin Li     CE.Args.push_back(S->getArg(i));\
4006*67e74705SXin Li   }
4007*67e74705SXin Li 
getEffect(const ObjCMethodDecl * MD)4008*67e74705SXin Li CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
4009*67e74705SXin Li   createCallEffect(MD, Method);
4010*67e74705SXin Li   return CE;
4011*67e74705SXin Li }
4012*67e74705SXin Li 
getEffect(const FunctionDecl * FD)4013*67e74705SXin Li CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
4014*67e74705SXin Li   createCallEffect(FD, Function);
4015*67e74705SXin Li   return CE;
4016*67e74705SXin Li }
4017*67e74705SXin Li 
4018*67e74705SXin Li #undef createCallEffect
4019*67e74705SXin Li 
4020*67e74705SXin Li } // end namespace objc_retain
4021*67e74705SXin Li } // end namespace ento
4022*67e74705SXin Li } // end namespace clang
4023