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