1 // CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the methods for CFRefCount, which implements
11 // a reference count checker for Core Foundation (Mac OS X).
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Core/Checker.h"
16 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/StmtVisitor.h"
21 #include "clang/Basic/LangOptions.h"
22 #include "clang/Basic/SourceManager.h"
23 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
24 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
25 #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
26 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
27 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
28 #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
29 #include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
30 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
31 #include "llvm/ADT/DenseMap.h"
32 #include "llvm/ADT/FoldingSet.h"
33 #include "llvm/ADT/ImmutableList.h"
34 #include "llvm/ADT/ImmutableMap.h"
35 #include "llvm/ADT/STLExtras.h"
36 #include "llvm/ADT/StringExtras.h"
39 using namespace clang;
41 using llvm::StringRef;
42 using llvm::StrInStrNoCase;
45 class InstanceReceiver {
47 const LocationContext *LC;
49 InstanceReceiver() : LC(0) { }
50 InstanceReceiver(const ObjCMessage &msg,
51 const LocationContext *lc = 0) : Msg(msg), LC(lc) {}
53 bool isValid() const {
54 return Msg.isValid() && Msg.isInstanceMessage();
56 operator bool() const {
60 SVal getSValAsScalarOrLoc(const GRState *state) {
62 // We have an expression for the receiver? Fetch the value
63 // of that expression.
64 if (const Expr *Ex = Msg.getInstanceReceiver())
65 return state->getSValAsScalarOrLoc(Ex);
67 // Otherwise we are sending a message to super. In this case the
68 // object reference is the same as 'self'.
69 if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl())
70 return state->getSVal(state->getRegion(SelfDecl, LC));
75 SourceRange getSourceRange() const {
77 if (const Expr *Ex = Msg.getInstanceReceiver())
78 return Ex->getSourceRange();
80 // Otherwise we are sending a message to super.
81 SourceLocation L = Msg.getSuperLoc();
83 return SourceRange(L, L);
88 static const ObjCMethodDecl*
89 ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
90 const ObjCInterfaceDecl *ID = MD->getClassInterface();
92 return MD->isInstanceMethod()
93 ? ID->lookupInstanceMethod(MD->getSelector())
94 : ID->lookupClassMethod(MD->getSelector());
98 class GenericNodeBuilderRefCount {
102 EndOfFunctionNodeBuilder *ENB;
104 GenericNodeBuilderRefCount(StmtNodeBuilder &snb, const Stmt *s,
106 : SNB(&snb), S(s), tag(t), ENB(0) {}
108 GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb)
109 : SNB(0), S(0), tag(0), ENB(&enb) {}
111 ExplodedNode *MakeNode(const GRState *state, ExplodedNode *Pred) {
113 return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
117 return ENB->generateNode(state, Pred);
120 } // end anonymous namespace
122 //===----------------------------------------------------------------------===//
123 // Primitives used for constructing summaries for function/method calls.
124 //===----------------------------------------------------------------------===//
126 /// ArgEffect is used to summarize a function/method call's effect on a
127 /// particular argument.
128 enum ArgEffect { Autorelease, Dealloc, DecRef, DecRefMsg, DoNothing,
129 DecRefBridgedTransfered,
130 DoNothingByRef, IncRefMsg, IncRef, MakeCollectable, MayEscape,
131 NewAutoreleasePool, SelfOwn, StopTracking };
134 template <> struct FoldingSetTrait<ArgEffect> {
135 static inline void Profile(const ArgEffect X, FoldingSetNodeID& ID) {
136 ID.AddInteger((unsigned) X);
139 } // end llvm namespace
141 /// ArgEffects summarizes the effects of a function/method call on all of
143 typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
147 /// RetEffect is used to summarize a function/method call's behavior with
148 /// respect to its return value.
151 enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
152 NotOwnedSymbol, GCNotOwnedSymbol, ARCNotOwnedSymbol,
154 OwnedWhenTrackedReceiver };
156 enum ObjKind { CF, ObjC, AnyObj };
163 RetEffect(Kind k, unsigned idx = 0) : K(k), O(AnyObj), index(idx) {}
164 RetEffect(Kind k, ObjKind o) : K(k), O(o), index(0) {}
167 Kind getKind() const { return K; }
169 ObjKind getObjKind() const { return O; }
171 unsigned getIndex() const {
172 assert(getKind() == Alias);
176 bool isOwned() const {
177 return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
178 K == OwnedWhenTrackedReceiver;
181 static RetEffect MakeOwnedWhenTrackedReceiver() {
182 return RetEffect(OwnedWhenTrackedReceiver, ObjC);
185 static RetEffect MakeAlias(unsigned Idx) {
186 return RetEffect(Alias, Idx);
188 static RetEffect MakeReceiverAlias() {
189 return RetEffect(ReceiverAlias);
191 static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
192 return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
194 static RetEffect MakeNotOwned(ObjKind o) {
195 return RetEffect(NotOwnedSymbol, o);
197 static RetEffect MakeGCNotOwned() {
198 return RetEffect(GCNotOwnedSymbol, ObjC);
200 static RetEffect MakeARCNotOwned() {
201 return RetEffect(ARCNotOwnedSymbol, ObjC);
203 static RetEffect MakeNoRet() {
204 return RetEffect(NoRet);
208 //===----------------------------------------------------------------------===//
209 // Reference-counting logic (typestate + counts).
210 //===----------------------------------------------------------------------===//
215 Owned = 0, // Owning reference.
216 NotOwned, // Reference is not owned by still valid (not freed).
217 Released, // Object has been released.
218 ReturnedOwned, // Returned object passes ownership to caller.
219 ReturnedNotOwned, // Return object does not pass ownership to caller.
221 ErrorDeallocNotOwned, // -dealloc called on non-owned object.
222 ErrorDeallocGC, // Calling -dealloc with GC enabled.
223 ErrorUseAfterRelease, // Object used after released.
224 ErrorReleaseNotOwned, // Release of an object that was not owned.
226 ErrorLeak, // A memory leak due to excessive reference counts.
227 ErrorLeakReturned, // A memory leak due to the returning method not having
228 // the correct naming conventions.
230 ErrorOverAutorelease,
231 ErrorReturnedNotOwned
236 RetEffect::ObjKind okind;
241 RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
242 : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
245 Kind getKind() const { return kind; }
247 RetEffect::ObjKind getObjKind() const { return okind; }
249 unsigned getCount() const { return Cnt; }
250 unsigned getAutoreleaseCount() const { return ACnt; }
251 unsigned getCombinedCounts() const { return Cnt + ACnt; }
252 void clearCounts() { Cnt = 0; ACnt = 0; }
253 void setCount(unsigned i) { Cnt = i; }
254 void setAutoreleaseCount(unsigned i) { ACnt = i; }
256 QualType getType() const { return T; }
258 bool isOwned() const {
259 return getKind() == Owned;
262 bool isNotOwned() const {
263 return getKind() == NotOwned;
266 bool isReturnedOwned() const {
267 return getKind() == ReturnedOwned;
270 bool isReturnedNotOwned() const {
271 return getKind() == ReturnedNotOwned;
274 static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
275 unsigned Count = 1) {
276 return RefVal(Owned, o, Count, 0, t);
279 static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
280 unsigned Count = 0) {
281 return RefVal(NotOwned, o, Count, 0, t);
284 // Comparison, profiling, and pretty-printing.
286 bool operator==(const RefVal& X) const {
287 return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
290 RefVal operator-(size_t i) const {
291 return RefVal(getKind(), getObjKind(), getCount() - i,
292 getAutoreleaseCount(), getType());
295 RefVal operator+(size_t i) const {
296 return RefVal(getKind(), getObjKind(), getCount() + i,
297 getAutoreleaseCount(), getType());
300 RefVal operator^(Kind k) const {
301 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
305 RefVal autorelease() const {
306 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
310 void Profile(llvm::FoldingSetNodeID& ID) const {
311 ID.AddInteger((unsigned) kind);
317 void print(llvm::raw_ostream& Out) const;
320 void RefVal::print(llvm::raw_ostream& Out) const {
322 Out << "Tracked Type:" << T.getAsString() << '\n';
325 default: assert(false);
328 unsigned cnt = getCount();
329 if (cnt) Out << " (+ " << cnt << ")";
335 unsigned cnt = getCount();
336 if (cnt) Out << " (+ " << cnt << ")";
340 case ReturnedOwned: {
341 Out << "ReturnedOwned";
342 unsigned cnt = getCount();
343 if (cnt) Out << " (+ " << cnt << ")";
347 case ReturnedNotOwned: {
348 Out << "ReturnedNotOwned";
349 unsigned cnt = getCount();
350 if (cnt) Out << " (+ " << cnt << ")";
359 Out << "-dealloc (GC)";
362 case ErrorDeallocNotOwned:
363 Out << "-dealloc (not-owned)";
370 case ErrorLeakReturned:
371 Out << "Leaked (Bad naming)";
374 case ErrorGCLeakReturned:
375 Out << "Leaked (GC-ed at return)";
378 case ErrorUseAfterRelease:
379 Out << "Use-After-Release [ERROR]";
382 case ErrorReleaseNotOwned:
383 Out << "Release of Not-Owned [ERROR]";
386 case RefVal::ErrorOverAutorelease:
387 Out << "Over autoreleased";
390 case RefVal::ErrorReturnedNotOwned:
391 Out << "Non-owned object returned instead of owned";
396 Out << " [ARC +" << ACnt << ']';
399 } //end anonymous namespace
401 //===----------------------------------------------------------------------===//
402 // RefBindings - State used to track object reference counts.
403 //===----------------------------------------------------------------------===//
405 typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
410 struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
411 static void* GDMIndex() {
412 static int RefBIndex = 0;
419 //===----------------------------------------------------------------------===//
421 //===----------------------------------------------------------------------===//
424 class RetainSummary {
425 /// Args - an ordered vector of (index, ArgEffect) pairs, where index
426 /// specifies the argument (starting from 0). This can be sparsely
427 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
430 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
431 /// do not have an entry in Args.
432 ArgEffect DefaultArgEffect;
434 /// Receiver - If this summary applies to an Objective-C message expression,
435 /// this is the effect applied to the state of the receiver.
438 /// Ret - The effect on the return value. Used to indicate if the
439 /// function/method call returns a new tracked symbol, returns an
440 /// alias of one of the arguments in the call, and so on.
443 /// EndPath - Indicates that execution of this method/function should
444 /// terminate the simulation of a path.
448 RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
449 ArgEffect ReceiverEff, bool endpath = false)
450 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R),
453 /// getArg - Return the argument effect on the argument specified by
454 /// idx (starting from 0).
455 ArgEffect getArg(unsigned idx) const {
456 if (const ArgEffect *AE = Args.lookup(idx))
459 return DefaultArgEffect;
462 void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
463 Args = af.add(Args, idx, e);
466 /// setDefaultArgEffect - Set the default argument effect.
467 void setDefaultArgEffect(ArgEffect E) {
468 DefaultArgEffect = E;
471 /// getRetEffect - Returns the effect on the return value of the call.
472 RetEffect getRetEffect() const { return Ret; }
474 /// setRetEffect - Set the effect of the return value of the call.
475 void setRetEffect(RetEffect E) { Ret = E; }
477 /// isEndPath - Returns true if executing the given method/function should
478 /// terminate the path.
479 bool isEndPath() const { return EndPath; }
482 /// Sets the effect on the receiver of the message.
483 void setReceiverEffect(ArgEffect e) { Receiver = e; }
485 /// getReceiverEffect - Returns the effect on the receiver of the call.
486 /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
487 ArgEffect getReceiverEffect() const { return Receiver; }
489 } // end anonymous namespace
491 //===----------------------------------------------------------------------===//
492 // Data structures for constructing summaries.
493 //===----------------------------------------------------------------------===//
496 class ObjCSummaryKey {
500 ObjCSummaryKey(IdentifierInfo* ii, Selector s)
503 ObjCSummaryKey(const ObjCInterfaceDecl* d, Selector s)
504 : II(d ? d->getIdentifier() : 0), S(s) {}
506 ObjCSummaryKey(const ObjCInterfaceDecl* d, IdentifierInfo *ii, Selector s)
507 : II(d ? d->getIdentifier() : ii), S(s) {}
509 ObjCSummaryKey(Selector s)
512 IdentifierInfo* getIdentifier() const { return II; }
513 Selector getSelector() const { return S; }
518 template <> struct DenseMapInfo<ObjCSummaryKey> {
519 static inline ObjCSummaryKey getEmptyKey() {
520 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
521 DenseMapInfo<Selector>::getEmptyKey());
524 static inline ObjCSummaryKey getTombstoneKey() {
525 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
526 DenseMapInfo<Selector>::getTombstoneKey());
529 static unsigned getHashValue(const ObjCSummaryKey &V) {
530 return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
532 | (DenseMapInfo<Selector>::getHashValue(V.getSelector())
536 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
537 return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
538 RHS.getIdentifier()) &&
539 DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
545 struct isPodLike<ObjCSummaryKey> { static const bool value = true; };
546 } // end llvm namespace
549 class ObjCSummaryCache {
550 typedef llvm::DenseMap<ObjCSummaryKey, RetainSummary*> MapTy;
553 ObjCSummaryCache() {}
555 RetainSummary* find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
557 // Lookup the method using the decl for the class @interface. If we
558 // have no decl, lookup using the class name.
559 return D ? find(D, S) : find(ClsName, S);
562 RetainSummary* find(const ObjCInterfaceDecl* D, Selector S) {
563 // Do a lookup with the (D,S) pair. If we find a match return
565 ObjCSummaryKey K(D, S);
566 MapTy::iterator I = M.find(K);
568 if (I != M.end() || !D)
571 // Walk the super chain. If we find a hit with a parent, we'll end
572 // up returning that summary. We actually allow that key (null,S), as
573 // we cache summaries for the null ObjCInterfaceDecl* to allow us to
574 // generate initial summaries without having to worry about NSObject
576 // FIXME: We may change this at some point.
577 for (ObjCInterfaceDecl* C=D->getSuperClass() ;; C=C->getSuperClass()) {
578 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
585 // Cache the summary with original key to make the next lookup faster
586 // and return the iterator.
587 RetainSummary *Summ = I->second;
592 RetainSummary* find(IdentifierInfo* II, Selector S) {
593 // FIXME: Class method lookup. Right now we dont' have a good way
594 // of going between IdentifierInfo* and the class hierarchy.
595 MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
598 I = M.find(ObjCSummaryKey(S));
600 return I == M.end() ? NULL : I->second;
603 RetainSummary*& operator[](ObjCSummaryKey K) {
607 RetainSummary*& operator[](Selector S) {
608 return M[ ObjCSummaryKey(S) ];
611 } // end anonymous namespace
613 //===----------------------------------------------------------------------===//
614 // Data structures for managing collections of summaries.
615 //===----------------------------------------------------------------------===//
618 class RetainSummaryManager {
620 //==-----------------------------------------------------------------==//
622 //==-----------------------------------------------------------------==//
624 typedef llvm::DenseMap<const FunctionDecl*, RetainSummary*>
627 typedef ObjCSummaryCache ObjCMethodSummariesTy;
629 //==-----------------------------------------------------------------==//
631 //==-----------------------------------------------------------------==//
633 /// Ctx - The ASTContext object for the analyzed ASTs.
636 /// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
637 /// "CFDictionaryCreate".
638 IdentifierInfo* CFDictionaryCreateII;
640 /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
641 const bool GCEnabled;
643 /// Records whether or not the analyzed code runs in ARC mode.
644 const bool ARCEnabled;
646 /// FuncSummaries - A map from FunctionDecls to summaries.
647 FuncSummariesTy FuncSummaries;
649 /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
651 ObjCMethodSummariesTy ObjCClassMethodSummaries;
653 /// ObjCMethodSummaries - A map from selectors to summaries.
654 ObjCMethodSummariesTy ObjCMethodSummaries;
656 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
657 /// and all other data used by the checker.
658 llvm::BumpPtrAllocator BPAlloc;
660 /// AF - A factory for ArgEffects objects.
661 ArgEffects::Factory AF;
663 /// ScratchArgs - A holding buffer for construct ArgEffects.
664 ArgEffects ScratchArgs;
666 /// ObjCAllocRetE - Default return effect for methods returning Objective-C
668 RetEffect ObjCAllocRetE;
670 /// ObjCInitRetE - Default return effect for init methods returning
671 /// Objective-C objects.
672 RetEffect ObjCInitRetE;
674 RetainSummary DefaultSummary;
675 RetainSummary* StopSummary;
677 //==-----------------------------------------------------------------==//
679 //==-----------------------------------------------------------------==//
681 /// getArgEffects - Returns a persistent ArgEffects object based on the
682 /// data in ScratchArgs.
683 ArgEffects getArgEffects();
685 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
688 RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
690 RetainSummary *getDefaultSummary() {
691 RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
692 return new (Summ) RetainSummary(DefaultSummary);
695 RetainSummary* getUnarySummary(const FunctionType* FT, UnaryFuncKind func);
697 RetainSummary* getCFSummaryCreateRule(const FunctionDecl* FD);
698 RetainSummary* getCFSummaryGetRule(const FunctionDecl* FD);
699 RetainSummary* getCFCreateGetRuleSummary(const FunctionDecl* FD,
702 RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
703 ArgEffect ReceiverEff = DoNothing,
704 ArgEffect DefaultEff = MayEscape,
705 bool isEndPath = false);
707 RetainSummary* getPersistentSummary(RetEffect RE,
708 ArgEffect ReceiverEff = DoNothing,
709 ArgEffect DefaultEff = MayEscape) {
710 return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
713 RetainSummary *getPersistentStopSummary() {
717 StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
718 StopTracking, StopTracking);
723 RetainSummary *getInitMethodSummary(QualType RetTy);
725 void InitializeClassMethodSummaries();
726 void InitializeMethodSummaries();
728 void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
729 ObjCClassMethodSummaries[S] = Summ;
732 void addNSObjectMethSummary(Selector S, RetainSummary *Summ) {
733 ObjCMethodSummaries[S] = Summ;
736 void addClassMethSummary(const char* Cls, const char* nullaryName,
737 RetainSummary *Summ) {
738 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
739 Selector S = GetNullarySelector(nullaryName, Ctx);
740 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
743 void addInstMethSummary(const char* Cls, const char* nullaryName,
744 RetainSummary *Summ) {
745 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
746 Selector S = GetNullarySelector(nullaryName, Ctx);
747 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
750 Selector generateSelector(va_list argp) {
751 llvm::SmallVector<IdentifierInfo*, 10> II;
753 while (const char* s = va_arg(argp, const char*))
754 II.push_back(&Ctx.Idents.get(s));
756 return Ctx.Selectors.getSelector(II.size(), &II[0]);
759 void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
760 RetainSummary* Summ, va_list argp) {
761 Selector S = generateSelector(argp);
762 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
765 void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) {
767 va_start(argp, Summ);
768 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
772 void addClsMethSummary(const char* Cls, RetainSummary* Summ, ...) {
774 va_start(argp, Summ);
775 addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
779 void addClsMethSummary(IdentifierInfo *II, RetainSummary* Summ, ...) {
781 va_start(argp, Summ);
782 addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
786 void addPanicSummary(const char* Cls, ...) {
787 RetainSummary* Summ = getPersistentSummary(AF.getEmptyMap(),
788 RetEffect::MakeNoRet(),
789 DoNothing, DoNothing, true);
791 va_start (argp, Cls);
792 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
798 RetainSummaryManager(ASTContext& ctx, bool gcenabled, bool usesARC)
800 CFDictionaryCreateII(&ctx.Idents.get("CFDictionaryCreate")),
801 GCEnabled(gcenabled),
803 AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
804 ObjCAllocRetE(gcenabled
805 ? RetEffect::MakeGCNotOwned()
806 : (usesARC ? RetEffect::MakeARCNotOwned()
807 : RetEffect::MakeOwned(RetEffect::ObjC, true))),
808 ObjCInitRetE(gcenabled
809 ? RetEffect::MakeGCNotOwned()
810 : (usesARC ? RetEffect::MakeARCNotOwned()
811 : RetEffect::MakeOwnedWhenTrackedReceiver())),
812 DefaultSummary(AF.getEmptyMap() /* per-argument effects (none) */,
813 RetEffect::MakeNoRet() /* return effect */,
814 MayEscape, /* default argument effect */
815 DoNothing /* receiver effect */),
818 InitializeClassMethodSummaries();
819 InitializeMethodSummaries();
822 ~RetainSummaryManager();
824 RetainSummary* getSummary(const FunctionDecl* FD);
826 RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
827 const GRState *state,
828 const LocationContext *LC);
830 RetainSummary* getInstanceMethodSummary(const ObjCMessage &msg,
831 const ObjCInterfaceDecl* ID) {
832 return getInstanceMethodSummary(msg.getSelector(), 0,
833 ID, msg.getMethodDecl(), msg.getType(Ctx));
836 RetainSummary* getInstanceMethodSummary(Selector S, IdentifierInfo *ClsName,
837 const ObjCInterfaceDecl* ID,
838 const ObjCMethodDecl *MD,
841 RetainSummary *getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
842 const ObjCInterfaceDecl *ID,
843 const ObjCMethodDecl *MD,
846 RetainSummary *getClassMethodSummary(const ObjCMessage &msg) {
847 const ObjCInterfaceDecl *Class = 0;
848 if (!msg.isInstanceMessage())
849 Class = msg.getReceiverInterface();
851 return getClassMethodSummary(msg.getSelector(),
852 Class? Class->getIdentifier() : 0,
854 msg.getMethodDecl(), msg.getType(Ctx));
857 /// getMethodSummary - This version of getMethodSummary is used to query
858 /// the summary for the current method being analyzed.
859 RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
860 // FIXME: Eventually this should be unneeded.
861 const ObjCInterfaceDecl *ID = MD->getClassInterface();
862 Selector S = MD->getSelector();
863 IdentifierInfo *ClsName = ID->getIdentifier();
864 QualType ResultTy = MD->getResultType();
866 // Resolve the method decl last.
867 if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD))
870 if (MD->isInstanceMethod())
871 return getInstanceMethodSummary(S, ClsName, ID, MD, ResultTy);
873 return getClassMethodSummary(S, ClsName, ID, MD, ResultTy);
876 RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD,
877 Selector S, QualType RetTy);
879 void updateSummaryFromAnnotations(RetainSummary &Summ,
880 const ObjCMethodDecl *MD);
882 void updateSummaryFromAnnotations(RetainSummary &Summ,
883 const FunctionDecl *FD);
885 bool isGCEnabled() const { return GCEnabled; }
887 bool isARCEnabled() const { return ARCEnabled; }
889 bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; }
891 RetainSummary *copySummary(RetainSummary *OldSumm) {
892 RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
893 new (Summ) RetainSummary(*OldSumm);
898 } // end anonymous namespace
900 //===----------------------------------------------------------------------===//
901 // Implementation of checker data structures.
902 //===----------------------------------------------------------------------===//
904 RetainSummaryManager::~RetainSummaryManager() {}
906 ArgEffects RetainSummaryManager::getArgEffects() {
907 ArgEffects AE = ScratchArgs;
908 ScratchArgs = AF.getEmptyMap();
913 RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
914 ArgEffect ReceiverEff,
915 ArgEffect DefaultEff,
917 // Create the summary and return it.
918 RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
919 new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff, isEndPath);
923 //===----------------------------------------------------------------------===//
924 // Summary creation for functions (largely uses of Core Foundation).
925 //===----------------------------------------------------------------------===//
927 static bool isRetain(const FunctionDecl* FD, StringRef FName) {
928 return FName.endswith("Retain");
931 static bool isRelease(const FunctionDecl* FD, StringRef FName) {
932 return FName.endswith("Release");
935 RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl* FD) {
936 // Look up a summary in our cache of FunctionDecls -> Summaries.
937 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
938 if (I != FuncSummaries.end())
941 // No summary? Generate one.
942 RetainSummary *S = 0;
945 // We generate "stop" summaries for implicitly defined functions.
946 if (FD->isImplicit()) {
947 S = getPersistentStopSummary();
950 // For C++ methods, generate an implicit "stop" summary as well. We
951 // can relax this once we have a clear policy for C++ methods and
952 // ownership attributes.
953 if (isa<CXXMethodDecl>(FD)) {
954 S = getPersistentStopSummary();
958 // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
960 const FunctionType* FT = FD->getType()->getAs<FunctionType>();
961 const IdentifierInfo *II = FD->getIdentifier();
965 StringRef FName = II->getName();
967 // Strip away preceding '_'. Doing this here will effect all the checks
969 FName = FName.substr(FName.find_first_not_of('_'));
971 // Inspect the result type.
972 QualType RetTy = FT->getResultType();
974 // FIXME: This should all be refactored into a chain of "summary lookup"
976 assert(ScratchArgs.isEmpty());
978 if (FName == "pthread_create") {
979 // Part of: <rdar://problem/7299394>. This will be addressed
981 S = getPersistentStopSummary();
982 } else if (FName == "NSMakeCollectable") {
983 // Handle: id NSMakeCollectable(CFTypeRef)
984 S = (RetTy->isObjCIdType())
985 ? getUnarySummary(FT, cfmakecollectable)
986 : getPersistentStopSummary();
987 } else if (FName == "IOBSDNameMatching" ||
988 FName == "IOServiceMatching" ||
989 FName == "IOServiceNameMatching" ||
990 FName == "IORegistryEntryIDMatching" ||
991 FName == "IOOpenFirmwarePathMatching") {
992 // Part of <rdar://problem/6961230>. (IOKit)
993 // This should be addressed using a API table.
994 S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
995 DoNothing, DoNothing);
996 } else if (FName == "IOServiceGetMatchingService" ||
997 FName == "IOServiceGetMatchingServices") {
998 // FIXES: <rdar://problem/6326900>
999 // This should be addressed using a API table. This strcmp is also
1000 // a little gross, but there is no need to super optimize here.
1001 ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
1002 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1003 } else if (FName == "IOServiceAddNotification" ||
1004 FName == "IOServiceAddMatchingNotification") {
1005 // Part of <rdar://problem/6961230>. (IOKit)
1006 // This should be addressed using a API table.
1007 ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
1008 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1009 } else if (FName == "CVPixelBufferCreateWithBytes") {
1010 // FIXES: <rdar://problem/7283567>
1011 // Eventually this can be improved by recognizing that the pixel
1012 // buffer passed to CVPixelBufferCreateWithBytes is released via
1013 // a callback and doing full IPA to make sure this is done correctly.
1014 // FIXME: This function has an out parameter that returns an
1015 // allocated object.
1016 ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
1017 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1018 } else if (FName == "CGBitmapContextCreateWithData") {
1019 // FIXES: <rdar://problem/7358899>
1020 // Eventually this can be improved by recognizing that 'releaseInfo'
1021 // passed to CGBitmapContextCreateWithData is released via
1022 // a callback and doing full IPA to make sure this is done correctly.
1023 ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
1024 S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
1025 DoNothing, DoNothing);
1026 } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
1027 // FIXES: <rdar://problem/7283567>
1028 // Eventually this can be improved by recognizing that the pixel
1029 // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
1030 // via a callback and doing full IPA to make sure this is done
1032 ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
1033 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1036 // Did we get a summary?
1040 // Enable this code once the semantics of NSDeallocateObject are resolved
1041 // for GC. <rdar://problem/6619988>
1043 // Handle: NSDeallocateObject(id anObject);
1044 // This method does allow 'nil' (although we don't check it now).
1045 if (strcmp(FName, "NSDeallocateObject") == 0) {
1046 return RetTy == Ctx.VoidTy
1047 ? getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, Dealloc)
1048 : getPersistentStopSummary();
1052 if (RetTy->isPointerType()) {
1053 // For CoreFoundation ('CF') types.
1054 if (cocoa::isRefType(RetTy, "CF", FName)) {
1055 if (isRetain(FD, FName))
1056 S = getUnarySummary(FT, cfretain);
1057 else if (FName.find("MakeCollectable") != StringRef::npos)
1058 S = getUnarySummary(FT, cfmakecollectable);
1060 S = getCFCreateGetRuleSummary(FD, FName);
1065 // For CoreGraphics ('CG') types.
1066 if (cocoa::isRefType(RetTy, "CG", FName)) {
1067 if (isRetain(FD, FName))
1068 S = getUnarySummary(FT, cfretain);
1070 S = getCFCreateGetRuleSummary(FD, FName);
1075 // For the Disk Arbitration API (DiskArbitration/DADisk.h)
1076 if (cocoa::isRefType(RetTy, "DADisk") ||
1077 cocoa::isRefType(RetTy, "DADissenter") ||
1078 cocoa::isRefType(RetTy, "DASessionRef")) {
1079 S = getCFCreateGetRuleSummary(FD, FName);
1086 // Check for release functions, the only kind of functions that we care
1087 // about that don't return a pointer type.
1088 if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
1090 FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
1092 if (isRelease(FD, FName))
1093 S = getUnarySummary(FT, cfrelease);
1095 assert (ScratchArgs.isEmpty());
1096 // Remaining CoreFoundation and CoreGraphics functions.
1097 // We use to assume that they all strictly followed the ownership idiom
1098 // and that ownership cannot be transferred. While this is technically
1099 // correct, many methods allow a tracked object to escape. For example:
1101 // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
1102 // CFDictionaryAddValue(y, key, x);
1104 // ... it is okay to use 'x' since 'y' has a reference to it
1106 // We handle this and similar cases with the follow heuristic. If the
1107 // function name contains "InsertValue", "SetValue", "AddValue",
1108 // "AppendValue", or "SetAttribute", then we assume that arguments may
1109 // "escape." This means that something else holds on to the object,
1110 // allowing it be used even after its local retain count drops to 0.
1111 ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
1112 StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
1113 StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
1114 StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
1115 StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
1116 ? MayEscape : DoNothing;
1118 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
1125 S = getDefaultSummary();
1127 // Annotations override defaults.
1129 updateSummaryFromAnnotations(*S, FD);
1131 FuncSummaries[FD] = S;
1136 RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl* FD,
1138 if (coreFoundation::followsCreateRule(FName))
1139 return getCFSummaryCreateRule(FD);
1141 return getCFSummaryGetRule(FD);
1145 RetainSummaryManager::getUnarySummary(const FunctionType* FT,
1146 UnaryFuncKind func) {
1148 // Sanity check that this is *really* a unary function. This can
1149 // happen if people do weird things.
1150 const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
1151 if (!FTP || FTP->getNumArgs() != 1)
1152 return getPersistentStopSummary();
1154 assert (ScratchArgs.isEmpty());
1158 ScratchArgs = AF.add(ScratchArgs, 0, IncRef);
1159 return getPersistentSummary(RetEffect::MakeAlias(0),
1160 DoNothing, DoNothing);
1164 ScratchArgs = AF.add(ScratchArgs, 0, DecRef);
1165 return getPersistentSummary(RetEffect::MakeNoRet(),
1166 DoNothing, DoNothing);
1169 case cfmakecollectable: {
1170 ScratchArgs = AF.add(ScratchArgs, 0, MakeCollectable);
1171 return getPersistentSummary(RetEffect::MakeAlias(0),DoNothing, DoNothing);
1175 assert (false && "Not a supported unary function.");
1176 return getDefaultSummary();
1181 RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl* FD) {
1182 assert (ScratchArgs.isEmpty());
1184 if (FD->getIdentifier() == CFDictionaryCreateII) {
1185 ScratchArgs = AF.add(ScratchArgs, 1, DoNothingByRef);
1186 ScratchArgs = AF.add(ScratchArgs, 2, DoNothingByRef);
1189 return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1193 RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl* FD) {
1194 assert (ScratchArgs.isEmpty());
1195 return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1196 DoNothing, DoNothing);
1199 //===----------------------------------------------------------------------===//
1200 // Summary creation for Selectors.
1201 //===----------------------------------------------------------------------===//
1204 RetainSummaryManager::getInitMethodSummary(QualType RetTy) {
1205 assert(ScratchArgs.isEmpty());
1206 // 'init' methods conceptually return a newly allocated object and claim
1208 if (cocoa::isCocoaObjectRef(RetTy) ||
1209 coreFoundation::isCFObjectRef(RetTy))
1210 return getPersistentSummary(ObjCInitRetE, DecRefMsg);
1212 return getDefaultSummary();
1216 RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
1217 const FunctionDecl *FD) {
1221 // Effects on the parameters.
1222 unsigned parm_idx = 0;
1223 for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
1224 pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
1225 const ParmVarDecl *pd = *pi;
1226 if (pd->getAttr<NSConsumedAttr>()) {
1228 Summ.addArg(AF, parm_idx, DecRef);
1230 else if(pd->getAttr<CFConsumedAttr>()) {
1231 Summ.addArg(AF, parm_idx, DecRef);
1235 QualType RetTy = FD->getResultType();
1237 // Determine if there is a special return effect for this method.
1238 if (cocoa::isCocoaObjectRef(RetTy)) {
1239 if (FD->getAttr<NSReturnsRetainedAttr>()) {
1240 Summ.setRetEffect(ObjCAllocRetE);
1242 else if (FD->getAttr<CFReturnsRetainedAttr>()) {
1243 Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
1245 else if (FD->getAttr<NSReturnsNotRetainedAttr>()) {
1246 Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
1248 else if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
1249 Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
1252 else if (RetTy->getAs<PointerType>()) {
1253 if (FD->getAttr<CFReturnsRetainedAttr>()) {
1254 Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
1256 else if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
1257 Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
1263 RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
1264 const ObjCMethodDecl *MD) {
1268 bool isTrackedLoc = false;
1270 // Effects on the receiver.
1271 if (MD->getAttr<NSConsumesSelfAttr>()) {
1273 Summ.setReceiverEffect(DecRefMsg);
1276 // Effects on the parameters.
1277 unsigned parm_idx = 0;
1278 for (ObjCMethodDecl::param_iterator pi=MD->param_begin(), pe=MD->param_end();
1279 pi != pe; ++pi, ++parm_idx) {
1280 const ParmVarDecl *pd = *pi;
1281 if (pd->getAttr<NSConsumedAttr>()) {
1283 Summ.addArg(AF, parm_idx, DecRef);
1285 else if(pd->getAttr<CFConsumedAttr>()) {
1286 Summ.addArg(AF, parm_idx, DecRef);
1290 // Determine if there is a special return effect for this method.
1291 if (cocoa::isCocoaObjectRef(MD->getResultType())) {
1292 if (MD->getAttr<NSReturnsRetainedAttr>()) {
1293 Summ.setRetEffect(ObjCAllocRetE);
1296 if (MD->getAttr<NSReturnsNotRetainedAttr>()) {
1297 Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
1301 isTrackedLoc = true;
1305 isTrackedLoc = MD->getResultType()->getAs<PointerType>() != NULL;
1308 if (MD->getAttr<CFReturnsRetainedAttr>())
1309 Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
1310 else if (MD->getAttr<CFReturnsNotRetainedAttr>())
1311 Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
1316 RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
1317 Selector S, QualType RetTy) {
1320 // Scan the method decl for 'void*' arguments. These should be treated
1321 // as 'StopTracking' because they are often used with delegates.
1322 // Delegates are a frequent form of false positives with the retain
1325 for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
1326 E = MD->param_end(); I != E; ++I, ++i)
1327 if (ParmVarDecl *PD = *I) {
1328 QualType Ty = Ctx.getCanonicalType(PD->getType());
1329 if (Ty.getLocalUnqualifiedType() == Ctx.VoidPtrTy)
1330 ScratchArgs = AF.add(ScratchArgs, i, StopTracking);
1334 // Any special effect for the receiver?
1335 ArgEffect ReceiverEff = DoNothing;
1337 // If one of the arguments in the selector has the keyword 'delegate' we
1338 // should stop tracking the reference count for the receiver. This is
1339 // because the reference count is quite possibly handled by a delegate
1341 if (S.isKeywordSelector()) {
1342 const std::string &str = S.getAsString();
1343 assert(!str.empty());
1344 if (StrInStrNoCase(str, "delegate:") != StringRef::npos)
1345 ReceiverEff = StopTracking;
1348 // Look for methods that return an owned object.
1349 if (cocoa::isCocoaObjectRef(RetTy)) {
1350 // EXPERIMENTAL: assume the Cocoa conventions for all objects returned
1351 // by instance methods.
1352 RetEffect E = cocoa::followsFundamentalRule(S, MD)
1353 ? ObjCAllocRetE : RetEffect::MakeNotOwned(RetEffect::ObjC);
1355 return getPersistentSummary(E, ReceiverEff, MayEscape);
1358 // Look for methods that return an owned core foundation object.
1359 if (coreFoundation::isCFObjectRef(RetTy)) {
1360 RetEffect E = cocoa::followsFundamentalRule(S, MD)
1361 ? RetEffect::MakeOwned(RetEffect::CF, true)
1362 : RetEffect::MakeNotOwned(RetEffect::CF);
1364 return getPersistentSummary(E, ReceiverEff, MayEscape);
1367 if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing)
1368 return getDefaultSummary();
1370 return getPersistentSummary(RetEffect::MakeNoRet(), ReceiverEff, MayEscape);
1374 RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
1375 const GRState *state,
1376 const LocationContext *LC) {
1378 // We need the type-information of the tracked receiver object
1379 // Retrieve it from the state.
1380 const Expr *Receiver = msg.getInstanceReceiver();
1381 const ObjCInterfaceDecl* ID = 0;
1383 // FIXME: Is this really working as expected? There are cases where
1384 // we just use the 'ID' from the message expression.
1388 receiverV = state->getSValAsScalarOrLoc(Receiver);
1390 // FIXME: Eventually replace the use of state->get<RefBindings> with
1391 // a generic API for reasoning about the Objective-C types of symbolic
1393 if (SymbolRef Sym = receiverV.getAsLocSymbol())
1394 if (const RefVal *T = state->get<RefBindings>(Sym))
1395 if (const ObjCObjectPointerType* PT =
1396 T->getType()->getAs<ObjCObjectPointerType>())
1397 ID = PT->getInterfaceDecl();
1399 // FIXME: this is a hack. This may or may not be the actual method
1402 if (const ObjCObjectPointerType *PT =
1403 Receiver->getType()->getAs<ObjCObjectPointerType>())
1404 ID = PT->getInterfaceDecl();
1407 // FIXME: Hack for 'super'.
1408 ID = msg.getReceiverInterface();
1411 // FIXME: The receiver could be a reference to a class, meaning that
1412 // we should use the class method.
1413 RetainSummary *Summ = getInstanceMethodSummary(msg, ID);
1414 return Summ ? Summ : getDefaultSummary();
1418 RetainSummaryManager::getInstanceMethodSummary(Selector S,
1419 IdentifierInfo *ClsName,
1420 const ObjCInterfaceDecl* ID,
1421 const ObjCMethodDecl *MD,
1424 // Look up a summary in our summary cache.
1425 RetainSummary *Summ = ObjCMethodSummaries.find(ID, ClsName, S);
1428 assert(ScratchArgs.isEmpty());
1430 // "initXXX": pass-through for receiver.
1431 if (cocoa::deriveNamingConvention(S, MD) == cocoa::InitRule)
1432 Summ = getInitMethodSummary(RetTy);
1434 Summ = getCommonMethodSummary(MD, S, RetTy);
1436 // Annotations override defaults.
1437 updateSummaryFromAnnotations(*Summ, MD);
1439 // Memoize the summary.
1440 ObjCMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
1447 RetainSummaryManager::getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
1448 const ObjCInterfaceDecl *ID,
1449 const ObjCMethodDecl *MD,
1452 assert(ClsName && "Class name must be specified.");
1453 RetainSummary *Summ = ObjCClassMethodSummaries.find(ID, ClsName, S);
1456 Summ = getCommonMethodSummary(MD, S, RetTy);
1457 // Annotations override defaults.
1458 updateSummaryFromAnnotations(*Summ, MD);
1459 // Memoize the summary.
1460 ObjCClassMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
1466 void RetainSummaryManager::InitializeClassMethodSummaries() {
1467 assert(ScratchArgs.isEmpty());
1468 RetainSummary* Summ = getPersistentSummary(ObjCAllocRetE);
1470 // Create the [NSAssertionHandler currentHander] summary.
1471 addClassMethSummary("NSAssertionHandler", "currentHandler",
1472 getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
1474 // Create the [NSAutoreleasePool addObject:] summary.
1475 ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
1476 addClassMethSummary("NSAutoreleasePool", "addObject",
1477 getPersistentSummary(RetEffect::MakeNoRet(),
1478 DoNothing, Autorelease));
1480 // Create the summaries for [NSObject performSelector...]. We treat
1481 // these as 'stop tracking' for the arguments because they are often
1482 // used for delegates that can release the object. When we have better
1483 // inter-procedural analysis we can potentially do something better. This
1484 // workaround is to remove false positives.
1485 Summ = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking);
1486 IdentifierInfo *NSObjectII = &Ctx.Idents.get("NSObject");
1487 addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
1488 "afterDelay", NULL);
1489 addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
1490 "afterDelay", "inModes", NULL);
1491 addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
1492 "withObject", "waitUntilDone", NULL);
1493 addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
1494 "withObject", "waitUntilDone", "modes", NULL);
1495 addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
1496 "withObject", "waitUntilDone", NULL);
1497 addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
1498 "withObject", "waitUntilDone", "modes", NULL);
1499 addClsMethSummary(NSObjectII, Summ, "performSelectorInBackground",
1500 "withObject", NULL);
1503 void RetainSummaryManager::InitializeMethodSummaries() {
1505 assert (ScratchArgs.isEmpty());
1507 // Create the "init" selector. It just acts as a pass-through for the
1509 RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
1510 addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
1512 // awakeAfterUsingCoder: behaves basically like an 'init' method. It
1513 // claims the receiver and returns a retained object.
1514 addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
1517 // The next methods are allocators.
1518 RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1519 RetainSummary *CFAllocSumm =
1520 getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1522 // Create the "retain" selector.
1523 RetEffect E = RetEffect::MakeReceiverAlias();
1524 RetainSummary *Summ = getPersistentSummary(E, IncRefMsg);
1525 addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
1527 // Create the "release" selector.
1528 Summ = getPersistentSummary(E, DecRefMsg);
1529 addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
1531 // Create the "drain" selector.
1532 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
1533 addNSObjectMethSummary(GetNullarySelector("drain", Ctx), Summ);
1535 // Create the -dealloc summary.
1536 Summ = getPersistentSummary(RetEffect::MakeNoRet(), Dealloc);
1537 addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
1539 // Create the "autorelease" selector.
1540 Summ = getPersistentSummary(E, Autorelease);
1541 addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
1543 // Specially handle NSAutoreleasePool.
1544 addInstMethSummary("NSAutoreleasePool", "init",
1545 getPersistentSummary(RetEffect::MakeReceiverAlias(),
1546 NewAutoreleasePool));
1548 // For NSWindow, allocated objects are (initially) self-owned.
1549 // FIXME: For now we opt for false negatives with NSWindow, as these objects
1550 // self-own themselves. However, they only do this once they are displayed.
1551 // Thus, we need to track an NSWindow's display status.
1552 // This is tracked in <rdar://problem/6062711>.
1553 // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1554 RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1558 addClassMethSummary("NSWindow", "alloc", NoTrackYet);
1561 addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
1562 "styleMask", "backing", "defer", NULL);
1564 addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
1565 "styleMask", "backing", "defer", "screen", NULL);
1568 // For NSPanel (which subclasses NSWindow), allocated objects are not
1570 // FIXME: For now we don't track NSPanels. object for the same reason
1571 // as for NSWindow objects.
1572 addClassMethSummary("NSPanel", "alloc", NoTrackYet);
1575 addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
1576 "styleMask", "backing", "defer", NULL);
1578 addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
1579 "styleMask", "backing", "defer", "screen", NULL);
1582 // Don't track allocated autorelease pools yet, as it is okay to prematurely
1584 addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
1586 // Create NSAssertionHandler summaries.
1587 addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
1588 "lineNumber", "description", NULL);
1590 addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
1591 "file", "lineNumber", "description", NULL);
1593 // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
1594 addInstMethSummary("QCRenderer", AllocSumm,
1595 "createSnapshotImageOfType", NULL);
1596 addInstMethSummary("QCView", AllocSumm,
1597 "createSnapshotImageOfType", NULL);
1599 // Create summaries for CIContext, 'createCGImage' and
1600 // 'createCGLayerWithSize'. These objects are CF objects, and are not
1601 // automatically garbage collected.
1602 addInstMethSummary("CIContext", CFAllocSumm,
1603 "createCGImage", "fromRect", NULL);
1604 addInstMethSummary("CIContext", CFAllocSumm,
1605 "createCGImage", "fromRect", "format", "colorSpace", NULL);
1606 addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize",
1610 //===----------------------------------------------------------------------===//
1611 // AutoreleaseBindings - State used to track objects in autorelease pools.
1612 //===----------------------------------------------------------------------===//
1614 typedef llvm::ImmutableMap<SymbolRef, unsigned> ARCounts;
1615 typedef llvm::ImmutableMap<SymbolRef, ARCounts> ARPoolContents;
1616 typedef llvm::ImmutableList<SymbolRef> ARStack;
1618 static int AutoRCIndex = 0;
1619 static int AutoRBIndex = 0;
1621 namespace { class AutoreleasePoolContents {}; }
1622 namespace { class AutoreleaseStack {}; }
1626 template<> struct GRStateTrait<AutoreleaseStack>
1627 : public GRStatePartialTrait<ARStack> {
1628 static inline void* GDMIndex() { return &AutoRBIndex; }
1631 template<> struct GRStateTrait<AutoreleasePoolContents>
1632 : public GRStatePartialTrait<ARPoolContents> {
1633 static inline void* GDMIndex() { return &AutoRCIndex; }
1635 } // end GR namespace
1636 } // end clang namespace
1638 static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
1639 ARStack stack = state->get<AutoreleaseStack>();
1640 return stack.isEmpty() ? SymbolRef() : stack.getHead();
1643 static const GRState * SendAutorelease(const GRState *state,
1644 ARCounts::Factory &F, SymbolRef sym) {
1646 SymbolRef pool = GetCurrentAutoreleasePool(state);
1647 const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
1648 ARCounts newCnts(0);
1651 const unsigned *cnt = (*cnts).lookup(sym);
1652 newCnts = F.add(*cnts, sym, cnt ? *cnt + 1 : 1);
1655 newCnts = F.add(F.getEmptyMap(), sym, 1);
1657 return state->set<AutoreleasePoolContents>(pool, newCnts);
1660 //===----------------------------------------------------------------------===//
1661 // Transfer functions.
1662 //===----------------------------------------------------------------------===//
1666 class CFRefCount : public TransferFuncs {
1668 class BindingsPrinter : public GRState::Printer {
1670 virtual void Print(llvm::raw_ostream& Out, const GRState* state,
1671 const char* nl, const char* sep);
1674 typedef llvm::DenseMap<const ExplodedNode*, const RetainSummary*>
1677 RetainSummaryManager Summaries;
1678 SummaryLogTy SummaryLog;
1679 const LangOptions& LOpts;
1680 ARCounts::Factory ARCountFactory;
1682 BugType *useAfterRelease, *releaseNotOwned;
1683 BugType *deallocGC, *deallocNotOwned;
1684 BugType *leakWithinFunction, *leakAtReturn;
1685 BugType *overAutorelease;
1686 BugType *returnNotOwnedForOwned;
1689 const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
1690 RefVal::Kind& hasErr);
1692 void ProcessNonLeakError(ExplodedNodeSet& Dst,
1693 StmtNodeBuilder& Builder,
1694 const Expr* NodeExpr, SourceRange ErrorRange,
1697 RefVal::Kind hasErr, SymbolRef Sym);
1699 const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
1700 llvm::SmallVectorImpl<SymbolRef> &Leaked);
1702 ExplodedNode* ProcessLeaks(const GRState * state,
1703 llvm::SmallVectorImpl<SymbolRef> &Leaked,
1704 GenericNodeBuilderRefCount &Builder,
1706 ExplodedNode *Pred = 0);
1709 CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
1710 : Summaries(Ctx, gcenabled, (bool)lopts.ObjCAutoRefCount),
1711 LOpts(lopts), useAfterRelease(0), releaseNotOwned(0),
1712 deallocGC(0), deallocNotOwned(0),
1713 leakWithinFunction(0), leakAtReturn(0), overAutorelease(0),
1714 returnNotOwnedForOwned(0), BR(0) {}
1716 virtual ~CFRefCount() {}
1718 void RegisterChecks(ExprEngine &Eng);
1720 virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
1721 Printers.push_back(new BindingsPrinter());
1724 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
1725 bool isARCorGCEnabled() const { return Summaries.isARCorGCEnabled(); }
1727 const LangOptions& getLangOptions() const { return LOpts; }
1729 const RetainSummary *getSummaryOfNode(const ExplodedNode *N) const {
1730 SummaryLogTy::const_iterator I = SummaryLog.find(N);
1731 return I == SummaryLog.end() ? 0 : I->second;
1736 void evalSummary(ExplodedNodeSet& Dst,
1738 StmtNodeBuilder& Builder,
1740 const CallOrObjCMessage &callOrMsg,
1741 InstanceReceiver Receiver,
1742 const RetainSummary& Summ,
1743 const MemRegion *Callee,
1744 ExplodedNode* Pred, const GRState *state);
1746 virtual void evalCall(ExplodedNodeSet& Dst,
1748 StmtNodeBuilder& Builder,
1749 const CallExpr* CE, SVal L,
1750 ExplodedNode* Pred);
1753 virtual void evalObjCMessage(ExplodedNodeSet& Dst,
1755 StmtNodeBuilder& Builder,
1758 const GRState *state);
1760 virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val);
1764 virtual void evalEndPath(ExprEngine& Engine,
1765 EndOfFunctionNodeBuilder& Builder);
1767 virtual void evalDeadSymbols(ExplodedNodeSet& Dst,
1769 StmtNodeBuilder& Builder,
1771 const GRState* state,
1772 SymbolReaper& SymReaper);
1774 std::pair<ExplodedNode*, const GRState *>
1775 HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilderRefCount Bd,
1776 ExplodedNode* Pred, ExprEngine &Eng,
1777 SymbolRef Sym, RefVal V, bool &stop);
1778 // Return statements.
1780 virtual void evalReturn(ExplodedNodeSet& Dst,
1782 StmtNodeBuilder& Builder,
1783 const ReturnStmt* S,
1784 ExplodedNode* Pred);
1786 void evalReturnWithRetEffect(ExplodedNodeSet& Dst,
1788 StmtNodeBuilder& Builder,
1789 const ReturnStmt* S,
1791 RetEffect RE, RefVal X,
1792 SymbolRef Sym, const GRState *state);
1797 virtual const GRState *evalAssume(const GRState* state, SVal condition,
1801 } // end anonymous namespace
1803 static void PrintPool(llvm::raw_ostream &Out, SymbolRef Sym,
1804 const GRState *state) {
1807 Out << Sym->getSymbolID();
1812 // Get the contents of the pool.
1813 if (const ARCounts *cnts = state->get<AutoreleasePoolContents>(Sym))
1814 for (ARCounts::iterator J=cnts->begin(), EJ=cnts->end(); J != EJ; ++J)
1815 Out << '(' << J.getKey() << ',' << J.getData() << ')';
1820 void CFRefCount::BindingsPrinter::Print(llvm::raw_ostream& Out,
1821 const GRState* state,
1822 const char* nl, const char* sep) {
1824 RefBindings B = state->get<RefBindings>();
1829 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1830 Out << (*I).first << " : ";
1831 (*I).second.print(Out);
1835 // Print the autorelease stack.
1836 Out << sep << nl << "AR pool stack:";
1837 ARStack stack = state->get<AutoreleaseStack>();
1839 PrintPool(Out, SymbolRef(), state); // Print the caller's pool.
1840 for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
1841 PrintPool(Out, *I, state);
1846 //===----------------------------------------------------------------------===//
1848 //===----------------------------------------------------------------------===//
1852 //===-------------===//
1853 // Bug Descriptions. //
1854 //===-------------===//
1856 class CFRefBug : public BugType {
1860 CFRefBug(CFRefCount* tf, llvm::StringRef name)
1861 : BugType(name, "Memory (Core Foundation/Objective-C)"), TF(*tf) {}
1864 CFRefCount& getTF() { return TF; }
1866 // FIXME: Eventually remove.
1867 virtual const char* getDescription() const = 0;
1869 virtual bool isLeak() const { return false; }
1872 class UseAfterRelease : public CFRefBug {
1874 UseAfterRelease(CFRefCount* tf)
1875 : CFRefBug(tf, "Use-after-release") {}
1877 const char* getDescription() const {
1878 return "Reference-counted object is used after it is released";
1882 class BadRelease : public CFRefBug {
1884 BadRelease(CFRefCount* tf) : CFRefBug(tf, "Bad release") {}
1886 const char* getDescription() const {
1887 return "Incorrect decrement of the reference count of an object that is "
1888 "not owned at this point by the caller";
1892 class DeallocGC : public CFRefBug {
1894 DeallocGC(CFRefCount *tf)
1895 : CFRefBug(tf, "-dealloc called while using garbage collection") {}
1897 const char *getDescription() const {
1898 return "-dealloc called while using garbage collection";
1902 class DeallocNotOwned : public CFRefBug {
1904 DeallocNotOwned(CFRefCount *tf)
1905 : CFRefBug(tf, "-dealloc sent to non-exclusively owned object") {}
1907 const char *getDescription() const {
1908 return "-dealloc sent to object that may be referenced elsewhere";
1912 class OverAutorelease : public CFRefBug {
1914 OverAutorelease(CFRefCount *tf) :
1915 CFRefBug(tf, "Object sent -autorelease too many times") {}
1917 const char *getDescription() const {
1918 return "Object sent -autorelease too many times";
1922 class ReturnedNotOwnedForOwned : public CFRefBug {
1924 ReturnedNotOwnedForOwned(CFRefCount *tf) :
1925 CFRefBug(tf, "Method should return an owned object") {}
1927 const char *getDescription() const {
1928 return "Object with a +0 retain count returned to caller where a +1 "
1929 "(owning) retain count is expected";
1933 class Leak : public CFRefBug {
1934 const bool isReturn;
1936 Leak(CFRefCount* tf, llvm::StringRef name, bool isRet)
1937 : CFRefBug(tf, name), isReturn(isRet) {}
1940 const char* getDescription() const { return ""; }
1942 bool isLeak() const { return true; }
1945 class LeakAtReturn : public Leak {
1947 LeakAtReturn(CFRefCount* tf, llvm::StringRef name)
1948 : Leak(tf, name, true) {}
1951 class LeakWithinFunction : public Leak {
1953 LeakWithinFunction(CFRefCount* tf, llvm::StringRef name)
1954 : Leak(tf, name, false) {}
1961 class CFRefReport : public RangedBugReport {
1964 const CFRefCount &TF;
1966 CFRefReport(CFRefBug& D, const CFRefCount &tf,
1967 ExplodedNode *n, SymbolRef sym)
1968 : RangedBugReport(D, D.getDescription(), n), Sym(sym), TF(tf) {}
1970 CFRefReport(CFRefBug& D, const CFRefCount &tf,
1971 ExplodedNode *n, SymbolRef sym, llvm::StringRef endText)
1972 : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
1974 virtual ~CFRefReport() {}
1976 CFRefBug& getBugType() const {
1977 return (CFRefBug&) RangedBugReport::getBugType();
1980 virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const {
1981 if (!getBugType().isLeak())
1982 return RangedBugReport::getRanges();
1984 return std::make_pair(ranges_iterator(), ranges_iterator());
1987 SymbolRef getSymbol() const { return Sym; }
1989 PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
1990 const ExplodedNode* N);
1992 std::pair<const char**,const char**> getExtraDescriptiveText();
1994 PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
1995 const ExplodedNode* PrevN,
1996 BugReporterContext& BRC);
1999 class CFRefLeakReport : public CFRefReport {
2000 SourceLocation AllocSite;
2001 const MemRegion* AllocBinding;
2003 CFRefLeakReport(CFRefBug& D, const CFRefCount &tf,
2004 ExplodedNode *n, SymbolRef sym,
2007 PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
2008 const ExplodedNode* N);
2010 SourceLocation getLocation() const { return AllocSite; }
2012 } // end anonymous namespace
2016 static const char* Msgs[] = {
2018 "Code is compiled to only use garbage collection",
2020 "Code is compiled to use reference counts",
2022 "Code is compiled to use either garbage collection (GC) or reference counts"
2023 " (non-GC). The bug occurs with GC enabled",
2024 // Hybrid, without GC
2025 "Code is compiled to use either garbage collection (GC) or reference counts"
2026 " (non-GC). The bug occurs in non-GC mode"
2029 std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
2030 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
2032 switch (TF.getLangOptions().getGCMode()) {
2036 case LangOptions::GCOnly:
2037 assert (TF.isGCEnabled());
2038 return std::make_pair(&Msgs[0], &Msgs[0]+1);
2040 case LangOptions::NonGC:
2041 assert (!TF.isGCEnabled());
2042 return std::make_pair(&Msgs[1], &Msgs[1]+1);
2044 case LangOptions::HybridGC:
2045 if (TF.isGCEnabled())
2046 return std::make_pair(&Msgs[2], &Msgs[2]+1);
2048 return std::make_pair(&Msgs[3], &Msgs[3]+1);
2052 static inline bool contains(const llvm::SmallVectorImpl<ArgEffect>& V,
2054 for (llvm::SmallVectorImpl<ArgEffect>::const_iterator I=V.begin(), E=V.end();
2056 if (*I == X) return true;
2061 PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N,
2062 const ExplodedNode* PrevN,
2063 BugReporterContext& BRC) {
2065 if (!isa<PostStmt>(N->getLocation()))
2068 // Check if the type state has changed.
2069 const GRState *PrevSt = PrevN->getState();
2070 const GRState *CurrSt = N->getState();
2072 const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
2073 if (!CurrT) return NULL;
2075 const RefVal &CurrV = *CurrT;
2076 const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
2078 // Create a string buffer to constain all the useful things we want
2079 // to tell the user.
2081 llvm::raw_string_ostream os(sbuf);
2083 // This is the allocation site since the previous node had no bindings
2086 const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2088 if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2089 // Get the name of the callee (if it is available).
2090 SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
2091 if (const FunctionDecl* FD = X.getAsFunctionDecl())
2092 os << "Call to function '" << FD << '\'';
2094 os << "function call";
2096 else if (isa<ObjCMessageExpr>(S)) {
2102 if (CurrV.getObjKind() == RetEffect::CF) {
2103 os << " returns a Core Foundation object with a ";
2106 assert (CurrV.getObjKind() == RetEffect::ObjC);
2107 os << " returns an Objective-C object with a ";
2110 if (CurrV.isOwned()) {
2111 os << "+1 retain count";
2113 if (static_cast<CFRefBug&>(getBugType()).getTF().isGCEnabled()) {
2114 assert(CurrV.getObjKind() == RetEffect::CF);
2116 "Core Foundation objects are not automatically garbage collected.";
2120 assert (CurrV.isNotOwned());
2121 os << "+0 retain count";
2124 PathDiagnosticLocation Pos(S, BRC.getSourceManager());
2125 return new PathDiagnosticEventPiece(Pos, os.str());
2128 // Gather up the effects that were performed on the object at this
2130 llvm::SmallVector<ArgEffect, 2> AEffects;
2132 if (const RetainSummary *Summ =
2133 TF.getSummaryOfNode(BRC.getNodeResolver().getOriginalNode(N))) {
2134 // We only have summaries attached to nodes after evaluating CallExpr and
2135 // ObjCMessageExprs.
2136 const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2138 if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2139 // Iterate through the parameter expressions and see if the symbol
2140 // was ever passed as an argument.
2143 for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
2144 AI!=AE; ++AI, ++i) {
2146 // Retrieve the value of the argument. Is it the symbol
2147 // we are interested in?
2148 if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
2151 // We have an argument. Get the effect!
2152 AEffects.push_back(Summ->getArg(i));
2155 else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
2156 if (const Expr *receiver = ME->getInstanceReceiver())
2157 if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
2158 // The symbol we are tracking is the receiver.
2159 AEffects.push_back(Summ->getReceiverEffect());
2165 // Get the previous type state.
2166 RefVal PrevV = *PrevT;
2168 // Specially handle -dealloc.
2169 if (!TF.isGCEnabled() && contains(AEffects, Dealloc)) {
2170 // Determine if the object's reference count was pushed to zero.
2171 assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
2172 // We may not have transitioned to 'release' if we hit an error.
2173 // This case is handled elsewhere.
2174 if (CurrV.getKind() == RefVal::Released) {
2175 assert(CurrV.getCombinedCounts() == 0);
2176 os << "Object released by directly sending the '-dealloc' message";
2181 // Specially handle CFMakeCollectable and friends.
2182 if (contains(AEffects, MakeCollectable)) {
2183 // Get the name of the function.
2184 const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2185 SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
2186 const FunctionDecl* FD = X.getAsFunctionDecl();
2187 const std::string& FName = FD->getNameAsString();
2189 if (TF.isGCEnabled()) {
2190 // Determine if the object's reference count was pushed to zero.
2191 assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
2193 os << "In GC mode a call to '" << FName
2194 << "' decrements an object's retain count and registers the "
2195 "object with the garbage collector. ";
2197 if (CurrV.getKind() == RefVal::Released) {
2198 assert(CurrV.getCount() == 0);
2199 os << "Since it now has a 0 retain count the object can be "
2200 "automatically collected by the garbage collector.";
2203 os << "An object must have a 0 retain count to be garbage collected. "
2204 "After this call its retain count is +" << CurrV.getCount()
2208 os << "When GC is not enabled a call to '" << FName
2209 << "' has no effect on its argument.";
2211 // Nothing more to say.
2215 // Determine if the typestate has changed.
2216 if (!(PrevV == CurrV))
2217 switch (CurrV.getKind()) {
2219 case RefVal::NotOwned:
2221 if (PrevV.getCount() == CurrV.getCount()) {
2222 // Did an autorelease message get sent?
2223 if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2226 assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2227 os << "Object sent -autorelease message";
2231 if (PrevV.getCount() > CurrV.getCount())
2232 os << "Reference count decremented.";
2234 os << "Reference count incremented.";
2236 if (unsigned Count = CurrV.getCount())
2237 os << " The object now has a +" << Count << " retain count.";
2239 if (PrevV.getKind() == RefVal::Released) {
2240 assert(TF.isGCEnabled() && CurrV.getCount() > 0);
2241 os << " The object is not eligible for garbage collection until the "
2242 "retain count reaches 0 again.";
2247 case RefVal::Released:
2248 os << "Object released.";
2251 case RefVal::ReturnedOwned:
2252 os << "Object returned to caller as an owning reference (single retain "
2253 "count transferred to caller)";
2256 case RefVal::ReturnedNotOwned:
2257 os << "Object returned to caller with a +0 retain count";
2264 // Emit any remaining diagnostics for the argument effects (if any).
2265 for (llvm::SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
2266 E=AEffects.end(); I != E; ++I) {
2268 // A bunch of things have alternate behavior under GC.
2269 if (TF.isGCEnabled())
2273 os << "In GC mode an 'autorelease' has no effect.";
2276 os << "In GC mode the 'retain' message has no effect.";
2279 os << "In GC mode the 'release' message has no effect.";
2285 if (os.str().empty())
2286 return 0; // We have nothing to say!
2288 const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2289 PathDiagnosticLocation Pos(S, BRC.getSourceManager());
2290 PathDiagnosticPiece* P = new PathDiagnosticEventPiece(Pos, os.str());
2292 // Add the range by scanning the children of the statement for any bindings
2294 for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
2296 if (const Expr* Exp = dyn_cast_or_null<Expr>(*I))
2297 if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
2298 P->addRange(Exp->getSourceRange());
2306 class FindUniqueBinding :
2307 public StoreManager::BindingsHandler {
2309 const MemRegion* Binding;
2313 FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {}
2315 bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
2318 SymbolRef SymV = val.getAsSymbol();
2319 if (!SymV || SymV != Sym)
2332 operator bool() { return First && Binding; }
2333 const MemRegion* getRegion() { return Binding; }
2337 static std::pair<const ExplodedNode*,const MemRegion*>
2338 GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode* N,
2341 // Find both first node that referred to the tracked symbol and the
2342 // memory location that value was store to.
2343 const ExplodedNode* Last = N;
2344 const MemRegion* FirstBinding = 0;
2347 const GRState* St = N->getState();
2348 RefBindings B = St->get<RefBindings>();
2353 FindUniqueBinding FB(Sym);
2354 StateMgr.iterBindings(St, FB);
2355 if (FB) FirstBinding = FB.getRegion();
2358 N = N->pred_empty() ? NULL : *(N->pred_begin());
2361 return std::make_pair(Last, FirstBinding);
2364 PathDiagnosticPiece*
2365 CFRefReport::getEndPath(BugReporterContext& BRC,
2366 const ExplodedNode* EndN) {
2367 // Tell the BugReporterContext to report cases when the tracked symbol is
2368 // assigned to different variables, etc.
2369 BRC.addNotableSymbol(Sym);
2370 return RangedBugReport::getEndPath(BRC, EndN);
2373 PathDiagnosticPiece*
2374 CFRefLeakReport::getEndPath(BugReporterContext& BRC,
2375 const ExplodedNode* EndN){
2377 // Tell the BugReporterContext to report cases when the tracked symbol is
2378 // assigned to different variables, etc.
2379 BRC.addNotableSymbol(Sym);
2381 // We are reporting a leak. Walk up the graph to get to the first node where
2382 // the symbol appeared, and also get the first VarDecl that tracked object
2384 const ExplodedNode* AllocNode = 0;
2385 const MemRegion* FirstBinding = 0;
2387 llvm::tie(AllocNode, FirstBinding) =
2388 GetAllocationSite(BRC.getStateManager(), EndN, Sym);
2390 SourceManager& SMgr = BRC.getSourceManager();
2392 // Compute an actual location for the leak. Sometimes a leak doesn't
2393 // occur at an actual statement (e.g., transition between blocks; end
2394 // of function) so we need to walk the graph and compute a real location.
2395 const ExplodedNode* LeakN = EndN;
2396 PathDiagnosticLocation L;
2399 ProgramPoint P = LeakN->getLocation();
2401 if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
2402 L = PathDiagnosticLocation(PS->getStmt()->getLocStart(), SMgr);
2405 else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
2406 if (const Stmt* Term = BE->getSrc()->getTerminator()) {
2407 L = PathDiagnosticLocation(Term->getLocStart(), SMgr);
2412 LeakN = LeakN->succ_empty() ? 0 : *(LeakN->succ_begin());
2416 const Decl &D = EndN->getCodeDecl();
2417 L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr);
2421 llvm::raw_string_ostream os(sbuf);
2423 os << "Object leaked: ";
2426 os << "object allocated and stored into '"
2427 << FirstBinding->getString() << '\'';
2430 os << "allocated object";
2432 // Get the retain count.
2433 const RefVal* RV = EndN->getState()->get<RefBindings>(Sym);
2435 if (RV->getKind() == RefVal::ErrorLeakReturned) {
2436 // FIXME: Per comments in rdar://6320065, "create" only applies to CF
2437 // objects. Only "copy", "alloc", "retain" and "new" transfer ownership
2438 // to the caller for NS objects.
2439 const Decl *D = &EndN->getCodeDecl();
2440 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
2441 os << " is returned from a method whose name ('"
2442 << MD->getSelector().getAsString()
2443 << "') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
2444 " This violates the naming convention rules"
2445 " given in the Memory Management Guide for Cocoa";
2448 const FunctionDecl *FD = cast<FunctionDecl>(D);
2449 os << " is return from a function whose name ('"
2450 << FD->getNameAsString()
2451 << "') does not contain 'Copy' or 'Create'. This violates the naming"
2452 " convention rules given the Memory Management Guide for Core"
2456 else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2457 ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
2458 os << " and returned from method '" << MD.getSelector().getAsString()
2459 << "' is potentially leaked when using garbage collection. Callers "
2460 "of this method do not expect a returned object with a +1 retain "
2461 "count since they expect the object to be managed by the garbage "
2465 os << " is not referenced later in this execution path and has a retain "
2466 "count of +" << RV->getCount();
2468 return new PathDiagnosticEventPiece(L, os.str());
2471 CFRefLeakReport::CFRefLeakReport(CFRefBug& D, const CFRefCount &tf,
2473 SymbolRef sym, ExprEngine& Eng)
2474 : CFRefReport(D, tf, n, sym) {
2476 // Most bug reports are cached at the location where they occurred.
2477 // With leaks, we want to unique them by the location where they were
2478 // allocated, and only report a single path. To do this, we need to find
2479 // the allocation site of a piece of tracked memory, which we do via a
2480 // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
2481 // Note that this is *not* the trimmed graph; we are guaranteed, however,
2482 // that all ancestor nodes that represent the allocation site have the
2483 // same SourceLocation.
2484 const ExplodedNode* AllocNode = 0;
2486 llvm::tie(AllocNode, AllocBinding) = // Set AllocBinding.
2487 GetAllocationSite(Eng.getStateManager(), getErrorNode(), getSymbol());
2489 // Get the SourceLocation for the allocation site.
2490 ProgramPoint P = AllocNode->getLocation();
2491 AllocSite = cast<PostStmt>(P).getStmt()->getLocStart();
2493 // Fill in the description of the bug.
2494 Description.clear();
2495 llvm::raw_string_ostream os(Description);
2496 SourceManager& SMgr = Eng.getContext().getSourceManager();
2497 unsigned AllocLine = SMgr.getInstantiationLineNumber(AllocSite);
2498 os << "Potential leak ";
2499 if (tf.isGCEnabled()) {
2500 os << "(when using garbage collection) ";
2502 os << "of an object allocated on line " << AllocLine;
2504 // FIXME: AllocBinding doesn't get populated for RegionStore yet.
2506 os << " and stored into '" << AllocBinding->getString() << '\'';
2509 //===----------------------------------------------------------------------===//
2510 // Main checker logic.
2511 //===----------------------------------------------------------------------===//
2513 /// GetReturnType - Used to get the return type of a message expression or
2514 /// function call with the intention of affixing that type to a tracked symbol.
2515 /// While the the return type can be queried directly from RetEx, when
2516 /// invoking class methods we augment to the return type to be that of
2517 /// a pointer to the class (as opposed it just being id).
2518 static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
2519 QualType RetTy = RetE->getType();
2520 // If RetE is not a message expression just return its type.
2521 // If RetE is a message expression, return its types if it is something
2522 /// more specific than id.
2523 if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
2524 if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
2525 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2526 PT->isObjCClassType()) {
2527 // At this point we know the return type of the message expression is
2528 // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
2529 // is a call to a class method whose type we can resolve. In such
2530 // cases, promote the return type to XXX* (where XXX is the class).
2531 const ObjCInterfaceDecl *D = ME->getReceiverInterface();
2533 Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
2540 // HACK: Symbols that have ref-count state that are referenced directly
2541 // (not as structure or array elements, or via bindings) by an argument
2542 // should not have their ref-count state stripped after we have
2543 // done an invalidation pass.
2545 // FIXME: This is a global to currently share between CFRefCount and
2546 // RetainReleaseChecker. Eventually all functionality in CFRefCount should
2547 // be migrated to RetainReleaseChecker, and we can make this a non-global.
2548 llvm::DenseSet<SymbolRef> WhitelistedSymbols;
2550 struct ResetWhiteList {
2552 ~ResetWhiteList() { WhitelistedSymbols.clear(); }
2556 void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
2558 StmtNodeBuilder& Builder,
2560 const CallOrObjCMessage &callOrMsg,
2561 InstanceReceiver Receiver,
2562 const RetainSummary& Summ,
2563 const MemRegion *Callee,
2564 ExplodedNode* Pred, const GRState *state) {
2566 // Evaluate the effect of the arguments.
2567 RefVal::Kind hasErr = (RefVal::Kind) 0;
2568 SourceRange ErrorRange;
2569 SymbolRef ErrorSym = 0;
2571 llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
2573 // Use RAII to make sure the whitelist is properly cleared.
2574 ResetWhiteList resetWhiteList;
2576 // Invalidate all instance variables of the receiver of a message.
2577 // FIXME: We should be able to do better with inter-procedural analysis.
2579 SVal V = Receiver.getSValAsScalarOrLoc(state);
2580 if (SymbolRef Sym = V.getAsLocSymbol()) {
2581 if (state->get<RefBindings>(Sym))
2582 WhitelistedSymbols.insert(Sym);
2584 if (const MemRegion *region = V.getAsRegion())
2585 RegionsToInvalidate.push_back(region);
2588 // Invalidate all instance variables for the callee of a C++ method call.
2589 // FIXME: We should be able to do better with inter-procedural analysis.
2590 // FIXME: we can probably do better for const versus non-const methods.
2591 if (callOrMsg.isCXXCall()) {
2592 if (const MemRegion *callee = callOrMsg.getCXXCallee().getAsRegion())
2593 RegionsToInvalidate.push_back(callee);
2596 for (unsigned idx = 0, e = callOrMsg.getNumArgs(); idx != e; ++idx) {
2597 SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
2598 SymbolRef Sym = V.getAsLocSymbol();
2601 if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
2602 WhitelistedSymbols.insert(Sym);
2603 state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
2605 ErrorRange = callOrMsg.getArgSourceRange(idx);
2613 if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(&V)) {
2614 if (Summ.getArg(idx) == DoNothingByRef)
2617 // Invalidate the value of the variable passed by reference.
2618 const MemRegion *R = MR->getRegion();
2620 // Are we dealing with an ElementRegion? If the element type is
2621 // a basic integer type (e.g., char, int) and the underying region
2622 // is a variable region then strip off the ElementRegion.
2623 // FIXME: We really need to think about this for the general case
2624 // as sometimes we are reasoning about arrays and other times
2625 // about (char*), etc., is just a form of passing raw bytes.
2626 // e.g., void *p = alloca(); foo((char*)p);
2627 if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
2628 // Checking for 'integral type' is probably too promiscuous, but
2629 // we'll leave it in for now until we have a systematic way of
2630 // handling all of these cases. Eventually we need to come up
2631 // with an interface to StoreManager so that this logic can be
2632 // approriately delegated to the respective StoreManagers while
2633 // still allowing us to do checker-specific logic (e.g.,
2634 // invalidating reference counts), probably via callbacks.
2635 if (ER->getElementType()->isIntegralOrEnumerationType()) {
2636 const MemRegion *superReg = ER->getSuperRegion();
2637 if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
2638 isa<ObjCIvarRegion>(superReg))
2639 R = cast<TypedRegion>(superReg);
2641 // FIXME: What about layers of ElementRegions?
2644 // Mark this region for invalidation. We batch invalidate regions
2645 // below for efficiency.
2646 RegionsToInvalidate.push_back(R);
2650 // Nuke all other arguments passed by reference.
2651 // FIXME: is this necessary or correct? This handles the non-Region
2652 // cases. Is it ever valid to store to these?
2653 state = state->unbindLoc(cast<Loc>(V));
2656 else if (isa<nonloc::LocAsInteger>(V)) {
2657 // If we are passing a location wrapped as an integer, unwrap it and
2658 // invalidate the values referred by the location.
2659 V = cast<nonloc::LocAsInteger>(V).getLoc();
2664 // Block calls result in all captured values passed-via-reference to be
2666 if (const BlockDataRegion *BR = dyn_cast_or_null<BlockDataRegion>(Callee)) {
2667 RegionsToInvalidate.push_back(BR);
2670 // Invalidate regions we designed for invalidation use the batch invalidation
2673 // FIXME: We can have collisions on the conjured symbol if the
2674 // expression *I also creates conjured symbols. We probably want
2675 // to identify conjured symbols by an expression pair: the enclosing
2676 // expression (the context) and the expression itself. This should
2677 // disambiguate conjured symbols.
2678 unsigned Count = Builder.getCurrentBlockCount();
2679 StoreManager::InvalidatedSymbols IS;
2681 // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
2682 // global variables.
2683 // NOTE: RetainReleaseChecker handles the actual invalidation of symbols.
2685 state->invalidateRegions(RegionsToInvalidate.data(),
2686 RegionsToInvalidate.data() +
2687 RegionsToInvalidate.size(),
2689 /* invalidateGlobals = */
2690 Eng.doesInvalidateGlobals(callOrMsg));
2692 // Evaluate the effect on the message receiver.
2693 if (!ErrorRange.isValid() && Receiver) {
2694 SymbolRef Sym = Receiver.getSValAsScalarOrLoc(state).getAsLocSymbol();
2696 if (const RefVal* T = state->get<RefBindings>(Sym)) {
2697 state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
2699 ErrorRange = Receiver.getSourceRange();
2706 // Process any errors.
2708 ProcessNonLeakError(Dst, Builder, Ex, ErrorRange, Pred, state,
2713 // Consult the summary for the return value.
2714 RetEffect RE = Summ.getRetEffect();
2716 if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
2719 SVal V = Receiver.getSValAsScalarOrLoc(state);
2720 if (SymbolRef Sym = V.getAsLocSymbol())
2721 if (state->get<RefBindings>(Sym)) {
2723 RE = Summaries.getObjAllocRetEffect();
2725 } // FIXME: Otherwise, this is a send-to-super instance message.
2727 RE = RetEffect::MakeNoRet();
2730 switch (RE.getKind()) {
2732 assert (false && "Unhandled RetEffect."); break;
2734 case RetEffect::NoRet: {
2735 // Make up a symbol for the return value (not reference counted).
2736 // FIXME: Most of this logic is not specific to the retain/release
2739 // FIXME: We eventually should handle structs and other compound types
2740 // that are returned by value.
2742 // Use the result type from callOrMsg as it automatically adjusts
2743 // for methods/functions that return references.
2744 QualType resultTy = callOrMsg.getResultType(Eng.getContext());
2745 if (Loc::isLocType(resultTy) ||
2746 (resultTy->isIntegerType() && resultTy->isScalarType())) {
2747 unsigned Count = Builder.getCurrentBlockCount();
2748 SValBuilder &svalBuilder = Eng.getSValBuilder();
2749 SVal X = svalBuilder.getConjuredSymbolVal(NULL, Ex, resultTy, Count);
2750 state = state->BindExpr(Ex, X, false);
2756 case RetEffect::Alias: {
2757 unsigned idx = RE.getIndex();
2758 assert (idx < callOrMsg.getNumArgs());
2759 SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
2760 state = state->BindExpr(Ex, V, false);
2764 case RetEffect::ReceiverAlias: {
2766 SVal V = Receiver.getSValAsScalarOrLoc(state);
2767 state = state->BindExpr(Ex, V, false);
2771 case RetEffect::OwnedAllocatedSymbol:
2772 case RetEffect::OwnedSymbol: {
2773 unsigned Count = Builder.getCurrentBlockCount();
2774 SValBuilder &svalBuilder = Eng.getSValBuilder();
2775 SymbolRef Sym = svalBuilder.getConjuredSymbol(Ex, Count);
2777 // Use the result type from callOrMsg as it automatically adjusts
2778 // for methods/functions that return references.
2779 QualType resultTy = callOrMsg.getResultType(Eng.getContext());
2780 state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
2782 state = state->BindExpr(Ex, svalBuilder.makeLoc(Sym), false);
2784 // FIXME: Add a flag to the checker where allocations are assumed to
2787 if (RE.getKind() == RetEffect::OwnedAllocatedSymbol) {
2789 state = state.assume(loc::SymbolVal(Sym), true, isFeasible);
2790 assert(isFeasible && "Cannot assume fresh symbol is non-null.");
2797 case RetEffect::GCNotOwnedSymbol:
2798 case RetEffect::ARCNotOwnedSymbol:
2799 case RetEffect::NotOwnedSymbol: {
2800 unsigned Count = Builder.getCurrentBlockCount();
2801 SValBuilder &svalBuilder = Eng.getSValBuilder();
2802 SymbolRef Sym = svalBuilder.getConjuredSymbol(Ex, Count);
2803 QualType RetT = GetReturnType(Ex, svalBuilder.getContext());
2804 state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
2806 state = state->BindExpr(Ex, svalBuilder.makeLoc(Sym), false);
2811 // Generate a sink node if we are at the end of a path.
2812 ExplodedNode *NewNode =
2813 Summ.isEndPath() ? Builder.MakeSinkNode(Dst, Ex, Pred, state)
2814 : Builder.MakeNode(Dst, Ex, Pred, state);
2816 // Annotate the edge with summary we used.
2817 if (NewNode) SummaryLog[NewNode] = &Summ;
2821 void CFRefCount::evalCall(ExplodedNodeSet& Dst,
2823 StmtNodeBuilder& Builder,
2824 const CallExpr* CE, SVal L,
2825 ExplodedNode* Pred) {
2827 RetainSummary *Summ = 0;
2829 // FIXME: Better support for blocks. For now we stop tracking anything
2830 // that is passed to blocks.
2831 // FIXME: Need to handle variables that are "captured" by the block.
2832 if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
2833 Summ = Summaries.getPersistentStopSummary();
2835 else if (const FunctionDecl* FD = L.getAsFunctionDecl()) {
2836 Summ = Summaries.getSummary(FD);
2838 else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
2839 if (const CXXMethodDecl *MD = me->getMethodDecl())
2840 Summ = Summaries.getSummary(MD);
2842 Summ = Summaries.getDefaultSummary();
2845 Summ = Summaries.getDefaultSummary();
2848 evalSummary(Dst, Eng, Builder, CE,
2849 CallOrObjCMessage(CE, Builder.GetState(Pred)),
2850 InstanceReceiver(), *Summ,L.getAsRegion(),
2851 Pred, Builder.GetState(Pred));
2854 void CFRefCount::evalObjCMessage(ExplodedNodeSet& Dst,
2856 StmtNodeBuilder& Builder,
2859 const GRState *state) {
2860 RetainSummary *Summ =
2861 msg.isInstanceMessage()
2862 ? Summaries.getInstanceMethodSummary(msg, state,Pred->getLocationContext())
2863 : Summaries.getClassMethodSummary(msg);
2865 assert(Summ && "RetainSummary is null");
2866 evalSummary(Dst, Eng, Builder, msg.getOriginExpr(),
2867 CallOrObjCMessage(msg, Builder.GetState(Pred)),
2868 InstanceReceiver(msg, Pred->getLocationContext()), *Summ, NULL,
2873 class StopTrackingCallback : public SymbolVisitor {
2874 const GRState *state;
2876 StopTrackingCallback(const GRState *st) : state(st) {}
2877 const GRState *getState() const { return state; }
2879 bool VisitSymbol(SymbolRef sym) {
2880 state = state->remove<RefBindings>(sym);
2884 } // end anonymous namespace
2887 void CFRefCount::evalBind(StmtNodeBuilderRef& B, SVal location, SVal val) {
2888 // Are we storing to something that causes the value to "escape"?
2889 bool escapes = false;
2891 // A value escapes in three possible cases (this may change):
2893 // (1) we are binding to something that is not a memory region.
2894 // (2) we are binding to a memregion that does not have stack storage
2895 // (3) we are binding to a memregion with stack storage that the store
2896 // does not understand.
2897 const GRState *state = B.getState();
2899 if (!isa<loc::MemRegionVal>(location))
2902 const MemRegion* R = cast<loc::MemRegionVal>(location).getRegion();
2903 escapes = !R->hasStackStorage();
2906 // To test (3), generate a new state with the binding removed. If it is
2907 // the same state, then it escapes (since the store cannot represent
2909 escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal())));
2913 // If our store can represent the binding and we aren't storing to something
2914 // that doesn't have local storage then just return and have the simulation
2915 // state continue as is.
2919 // Otherwise, find all symbols referenced by 'val' that we are tracking
2920 // and stop tracking them.
2921 B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState());
2924 // Return statements.
2926 void CFRefCount::evalReturn(ExplodedNodeSet& Dst,
2928 StmtNodeBuilder& Builder,
2929 const ReturnStmt* S,
2930 ExplodedNode* Pred) {
2932 const Expr* RetE = S->getRetValue();
2936 const GRState *state = Builder.GetState(Pred);
2937 SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
2942 // Get the reference count binding (if any).
2943 const RefVal* T = state->get<RefBindings>(Sym);
2948 // Change the reference count.
2951 switch (X.getKind()) {
2952 case RefVal::Owned: {
2953 unsigned cnt = X.getCount();
2955 X.setCount(cnt - 1);
2956 X = X ^ RefVal::ReturnedOwned;
2960 case RefVal::NotOwned: {
2961 unsigned cnt = X.getCount();
2963 X.setCount(cnt - 1);
2964 X = X ^ RefVal::ReturnedOwned;
2967 X = X ^ RefVal::ReturnedNotOwned;
2976 // Update the binding.
2977 state = state->set<RefBindings>(Sym, X);
2978 Pred = Builder.MakeNode(Dst, S, Pred, state);
2980 // Did we cache out?
2984 // Update the autorelease counts.
2985 static unsigned autoreleasetag = 0;
2986 GenericNodeBuilderRefCount Bd(Builder, S, &autoreleasetag);
2988 llvm::tie(Pred, state) = HandleAutoreleaseCounts(state , Bd, Pred, Eng, Sym,
2991 // Did we cache out?
2995 // Get the updated binding.
2996 T = state->get<RefBindings>(Sym);
3000 // Consult the summary of the enclosing method.
3001 Decl const *CD = &Pred->getCodeDecl();
3003 if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
3004 const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
3005 return evalReturnWithRetEffect(Dst, Eng, Builder, S,
3006 Pred, Summ.getRetEffect(), X,
3010 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3011 if (!isa<CXXMethodDecl>(FD))
3012 if (const RetainSummary *Summ = Summaries.getSummary(FD))
3013 return evalReturnWithRetEffect(Dst, Eng, Builder, S,
3014 Pred, Summ->getRetEffect(), X,
3019 void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
3021 StmtNodeBuilder &Builder,
3022 const ReturnStmt *S,
3024 RetEffect RE, RefVal X,
3025 SymbolRef Sym, const GRState *state) {
3026 // Any leaks or other errors?
3027 if (X.isReturnedOwned() && X.getCount() == 0) {
3028 if (RE.getKind() != RetEffect::NoRet) {
3029 bool hasError = false;
3030 if (isGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
3031 // Things are more complicated with garbage collection. If the
3032 // returned object is suppose to be an Objective-C object, we have
3033 // a leak (as the caller expects a GC'ed object) because no
3034 // method should return ownership unless it returns a CF object.
3036 X = X ^ RefVal::ErrorGCLeakReturned;
3038 else if (!RE.isOwned()) {
3039 // Either we are using GC and the returned object is a CF type
3040 // or we aren't using GC. In either case, we expect that the
3041 // enclosing method is expected to return ownership.
3043 X = X ^ RefVal::ErrorLeakReturned;
3047 // Generate an error node.
3048 static int ReturnOwnLeakTag = 0;
3049 state = state->set<RefBindings>(Sym, X);
3051 Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
3052 &ReturnOwnLeakTag), state, Pred);
3054 CFRefReport *report =
3055 new CFRefLeakReport(*static_cast<CFRefBug*>(leakAtReturn), *this,
3057 BR->EmitReport(report);
3064 if (X.isReturnedNotOwned()) {
3066 // Trying to return a not owned object to a caller expecting an
3069 static int ReturnNotOwnedForOwnedTag = 0;
3070 state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
3071 if (ExplodedNode *N =
3072 Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
3073 &ReturnNotOwnedForOwnedTag),
3075 CFRefReport *report =
3076 new CFRefReport(*static_cast<CFRefBug*>(returnNotOwnedForOwned),
3078 BR->EmitReport(report);
3086 const GRState* CFRefCount::evalAssume(const GRState *state,
3087 SVal Cond, bool Assumption) {
3089 // FIXME: We may add to the interface of evalAssume the list of symbols
3090 // whose assumptions have changed. For now we just iterate through the
3091 // bindings and check if any of the tracked symbols are NULL. This isn't
3092 // too bad since the number of symbols we will track in practice are
3093 // probably small and evalAssume is only called at branches and a few
3095 RefBindings B = state->get<RefBindings>();
3100 bool changed = false;
3101 RefBindings::Factory& RefBFactory = state->get_context<RefBindings>();
3103 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
3104 // Check if the symbol is null (or equal to any constant).
3105 // If this is the case, stop tracking the symbol.
3106 if (state->getSymVal(I.getKey())) {
3108 B = RefBFactory.remove(B, I.getKey());
3113 state = state->set<RefBindings>(B);
3118 const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
3119 RefVal V, ArgEffect E,
3120 RefVal::Kind& hasErr) {
3122 // In GC mode [... release] and [... retain] do nothing.
3125 case IncRefMsg: E = isARCorGCEnabled() ? DoNothing : IncRef; break;
3126 case DecRefMsg: E = isARCorGCEnabled() ? DoNothing : DecRef; break;
3127 case MakeCollectable: E = isGCEnabled() ? DecRef : DoNothing; break;
3128 case NewAutoreleasePool: E = isGCEnabled() ? DoNothing :
3129 NewAutoreleasePool; break;
3132 // Handle all use-after-releases.
3133 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
3134 V = V ^ RefVal::ErrorUseAfterRelease;
3135 hasErr = V.getKind();
3136 return state->set<RefBindings>(sym, V);
3142 case MakeCollectable:
3144 "DecRefMsg/IncRefMsg/MakeCollectable already transformed");
3148 // Any use of -dealloc in GC is *bad*.
3149 if (isGCEnabled()) {
3150 V = V ^ RefVal::ErrorDeallocGC;
3151 hasErr = V.getKind();
3155 switch (V.getKind()) {
3157 assert(false && "Invalid case.");
3159 // The object immediately transitions to the released state.
3160 V = V ^ RefVal::Released;
3162 return state->set<RefBindings>(sym, V);
3163 case RefVal::NotOwned:
3164 V = V ^ RefVal::ErrorDeallocNotOwned;
3165 hasErr = V.getKind();
3170 case NewAutoreleasePool:
3171 assert(!isGCEnabled());
3172 return state->add<AutoreleaseStack>(sym);
3175 if (V.getKind() == RefVal::Owned) {
3176 V = V ^ RefVal::NotOwned;
3182 case DoNothingByRef:
3190 // Update the autorelease counts.
3191 state = SendAutorelease(state, ARCountFactory, sym);
3192 V = V.autorelease();
3196 return state->remove<RefBindings>(sym);
3199 switch (V.getKind()) {
3204 case RefVal::NotOwned:
3207 case RefVal::Released:
3208 // Non-GC cases are handled above.
3209 assert(isGCEnabled());
3210 V = (V ^ RefVal::Owned) + 1;
3216 V = V ^ RefVal::NotOwned;
3219 case DecRefBridgedTransfered:
3220 switch (V.getKind()) {
3222 // case 'RefVal::Released' handled above.
3226 assert(V.getCount() > 0);
3227 if (V.getCount() == 1)
3228 V = V ^ (E == DecRefBridgedTransfered ?
3229 RefVal::NotOwned : RefVal::Released);
3233 case RefVal::NotOwned:
3234 if (V.getCount() > 0)
3237 V = V ^ RefVal::ErrorReleaseNotOwned;
3238 hasErr = V.getKind();
3242 case RefVal::Released:
3243 // Non-GC cases are handled above.
3244 assert(isGCEnabled());
3245 V = V ^ RefVal::ErrorUseAfterRelease;
3246 hasErr = V.getKind();
3251 return state->set<RefBindings>(sym, V);
3254 //===----------------------------------------------------------------------===//
3255 // Handle dead symbols and end-of-path.
3256 //===----------------------------------------------------------------------===//
3258 std::pair<ExplodedNode*, const GRState *>
3259 CFRefCount::HandleAutoreleaseCounts(const GRState * state,
3260 GenericNodeBuilderRefCount Bd,
3263 SymbolRef Sym, RefVal V, bool &stop) {
3265 unsigned ACnt = V.getAutoreleaseCount();
3268 // No autorelease counts? Nothing to be done.
3270 return std::make_pair(Pred, state);
3272 assert(!isGCEnabled() && "Autorelease counts in GC mode?");
3273 unsigned Cnt = V.getCount();
3275 // FIXME: Handle sending 'autorelease' to already released object.
3277 if (V.getKind() == RefVal::ReturnedOwned)
3283 if (V.getKind() == RefVal::ReturnedOwned)
3284 V = V ^ RefVal::ReturnedNotOwned;
3286 V = V ^ RefVal::NotOwned;
3289 V.setCount(Cnt - ACnt);
3290 V.setAutoreleaseCount(0);
3292 state = state->set<RefBindings>(Sym, V);
3293 ExplodedNode *N = Bd.MakeNode(state, Pred);
3295 return std::make_pair(N, state);
3298 // Woah! More autorelease counts then retain counts left.
3301 V = V ^ RefVal::ErrorOverAutorelease;
3302 state = state->set<RefBindings>(Sym, V);
3304 if (ExplodedNode *N = Bd.MakeNode(state, Pred)) {
3308 llvm::raw_string_ostream os(sbuf);
3309 os << "Object over-autoreleased: object was sent -autorelease ";
3310 if (V.getAutoreleaseCount() > 1)
3311 os << V.getAutoreleaseCount() << " times ";
3312 os << "but the object has a +" << V.getCount() << " retain count";
3314 CFRefReport *report =
3315 new CFRefReport(*static_cast<CFRefBug*>(overAutorelease),
3316 *this, N, Sym, os.str());
3317 BR->EmitReport(report);
3320 return std::make_pair((ExplodedNode*)0, state);
3324 CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
3325 llvm::SmallVectorImpl<SymbolRef> &Leaked) {
3327 bool hasLeak = V.isOwned() ||
3328 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
3331 return state->remove<RefBindings>(sid);
3333 Leaked.push_back(sid);
3334 return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
3338 CFRefCount::ProcessLeaks(const GRState * state,
3339 llvm::SmallVectorImpl<SymbolRef> &Leaked,
3340 GenericNodeBuilderRefCount &Builder,
3342 ExplodedNode *Pred) {
3347 // Generate an intermediate node representing the leak point.
3348 ExplodedNode *N = Builder.MakeNode(state, Pred);
3351 for (llvm::SmallVectorImpl<SymbolRef>::iterator
3352 I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
3354 CFRefBug *BT = static_cast<CFRefBug*>(Pred ? leakWithinFunction
3356 assert(BT && "BugType not initialized.");
3357 CFRefLeakReport* report = new CFRefLeakReport(*BT, *this, N, *I, Eng);
3358 BR->EmitReport(report);
3365 void CFRefCount::evalEndPath(ExprEngine& Eng,
3366 EndOfFunctionNodeBuilder& Builder) {
3368 const GRState *state = Builder.getState();
3369 GenericNodeBuilderRefCount Bd(Builder);
3370 RefBindings B = state->get<RefBindings>();
3371 ExplodedNode *Pred = 0;
3373 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3375 llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
3383 B = state->get<RefBindings>();
3384 llvm::SmallVector<SymbolRef, 10> Leaked;
3386 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
3387 state = HandleSymbolDeath(state, (*I).first, (*I).second, Leaked);
3389 ProcessLeaks(state, Leaked, Bd, Eng, Pred);
3392 void CFRefCount::evalDeadSymbols(ExplodedNodeSet& Dst,
3394 StmtNodeBuilder& Builder,
3396 const GRState* state,
3397 SymbolReaper& SymReaper) {
3398 const Stmt *S = Builder.getStmt();
3399 RefBindings B = state->get<RefBindings>();
3401 // Update counts from autorelease pools
3402 for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3403 E = SymReaper.dead_end(); I != E; ++I) {
3405 if (const RefVal* T = B.lookup(Sym)){
3406 // Use the symbol as the tag.
3407 // FIXME: This might not be as unique as we would like.
3408 GenericNodeBuilderRefCount Bd(Builder, S, Sym);
3410 llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
3417 B = state->get<RefBindings>();
3418 llvm::SmallVector<SymbolRef, 10> Leaked;
3420 for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3421 E = SymReaper.dead_end(); I != E; ++I) {
3422 if (const RefVal* T = B.lookup(*I))
3423 state = HandleSymbolDeath(state, *I, *T, Leaked);
3426 static unsigned LeakPPTag = 0;
3428 GenericNodeBuilderRefCount Bd(Builder, S, &LeakPPTag);
3429 Pred = ProcessLeaks(state, Leaked, Bd, Eng, Pred);
3432 // Did we cache out?
3436 // Now generate a new node that nukes the old bindings.
3437 RefBindings::Factory& F = state->get_context<RefBindings>();
3439 for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3440 E = SymReaper.dead_end(); I!=E; ++I) B = F.remove(B, *I);
3442 state = state->set<RefBindings>(B);
3443 Builder.MakeNode(Dst, S, Pred, state);
3446 void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst,
3447 StmtNodeBuilder& Builder,
3448 const Expr* NodeExpr,
3449 SourceRange ErrorRange,
3452 RefVal::Kind hasErr, SymbolRef Sym) {
3453 Builder.BuildSinks = true;
3454 ExplodedNode *N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
3463 assert(false && "Unhandled error.");
3465 case RefVal::ErrorUseAfterRelease:
3466 BT = static_cast<CFRefBug*>(useAfterRelease);
3468 case RefVal::ErrorReleaseNotOwned:
3469 BT = static_cast<CFRefBug*>(releaseNotOwned);
3471 case RefVal::ErrorDeallocGC:
3472 BT = static_cast<CFRefBug*>(deallocGC);
3474 case RefVal::ErrorDeallocNotOwned:
3475 BT = static_cast<CFRefBug*>(deallocNotOwned);
3479 CFRefReport *report = new CFRefReport(*BT, *this, N, Sym);
3480 report->addRange(ErrorRange);
3481 BR->EmitReport(report);
3484 //===----------------------------------------------------------------------===//
3485 // Pieces of the retain/release checker implemented using a CheckerVisitor.
3486 // More pieces of the retain/release checker will be migrated to this interface
3487 // (ideally, all of it some day).
3488 //===----------------------------------------------------------------------===//
3491 class RetainReleaseChecker
3492 : public Checker< check::PostStmt<BlockExpr>,
3493 check::PostStmt<CastExpr>,
3494 check::RegionChanges > {
3496 bool wantsRegionUpdate;
3498 RetainReleaseChecker() : wantsRegionUpdate(true) {}
3501 void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
3503 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
3505 const GRState *checkRegionChanges(const GRState *state,
3506 const StoreManager::InvalidatedSymbols *invalidated,
3507 const MemRegion * const *begin,
3508 const MemRegion * const *end) const;
3510 bool wantsRegionChangeUpdate(const GRState *state) const {
3511 return wantsRegionUpdate;
3514 } // end anonymous namespace
3517 RetainReleaseChecker::checkRegionChanges(const GRState *state,
3518 const StoreManager::InvalidatedSymbols *invalidated,
3519 const MemRegion * const *begin,
3520 const MemRegion * const *end) const {
3524 for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
3525 E = invalidated->end(); I!=E; ++I) {
3527 if (WhitelistedSymbols.count(sym))
3529 // Remove any existing reference-count binding.
3530 state = state->remove<RefBindings>(sym);
3535 void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
3536 CheckerContext &C) const {
3538 // Scan the BlockDecRefExprs for any object the retain/release checker
3540 if (!BE->getBlockDecl()->hasCaptures())
3543 const GRState *state = C.getState();
3544 const BlockDataRegion *R =
3545 cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
3547 BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
3548 E = R->referenced_vars_end();
3553 // FIXME: For now we invalidate the tracking of all symbols passed to blocks
3554 // via captured variables, even though captured variables result in a copy
3555 // and in implicit increment/decrement of a retain count.
3556 llvm::SmallVector<const MemRegion*, 10> Regions;
3557 const LocationContext *LC = C.getPredecessor()->getLocationContext();
3558 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
3560 for ( ; I != E; ++I) {
3561 const VarRegion *VR = *I;
3562 if (VR->getSuperRegion() == R) {
3563 VR = MemMgr.getVarRegion(VR->getDecl(), LC);
3565 Regions.push_back(VR);
3569 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
3570 Regions.data() + Regions.size()).getState();
3571 C.addTransition(state);
3574 void RetainReleaseChecker::checkPostStmt(const CastExpr *CE,
3575 CheckerContext &C) const {
3576 const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
3580 ArgEffect AE = IncRef;
3582 switch (BE->getBridgeKind()) {
3583 case clang::OBC_Bridge:
3586 case clang::OBC_BridgeRetained:
3589 case clang::OBC_BridgeTransfer:
3590 AE = DecRefBridgedTransfered;
3594 const GRState *state = C.getState();
3595 SymbolRef Sym = state->getSVal(CE).getAsLocSymbol();
3598 const RefVal* T = state->get<RefBindings>(Sym);
3602 // This is gross. Once the checker and CFRefCount are unified,
3603 // this will go away.
3604 CFRefCount &cf = static_cast<CFRefCount&>(C.getEngine().getTF());
3605 RefVal::Kind hasErr = (RefVal::Kind) 0;
3606 state = cf.Update(state, Sym, *T, AE, hasErr);
3613 C.generateNode(state);
3616 //===----------------------------------------------------------------------===//
3617 // Transfer function creation for external clients.
3618 //===----------------------------------------------------------------------===//
3620 void CFRefCount::RegisterChecks(ExprEngine& Eng) {
3621 BugReporter &BR = Eng.getBugReporter();
3623 useAfterRelease = new UseAfterRelease(this);
3624 BR.Register(useAfterRelease);
3626 releaseNotOwned = new BadRelease(this);
3627 BR.Register(releaseNotOwned);
3629 deallocGC = new DeallocGC(this);
3630 BR.Register(deallocGC);
3632 deallocNotOwned = new DeallocNotOwned(this);
3633 BR.Register(deallocNotOwned);
3635 overAutorelease = new OverAutorelease(this);
3636 BR.Register(overAutorelease);
3638 returnNotOwnedForOwned = new ReturnedNotOwnedForOwned(this);
3639 BR.Register(returnNotOwnedForOwned);
3641 // First register "return" leaks.
3642 const char* name = 0;
3645 name = "Leak of returned object when using garbage collection";
3646 else if (getLangOptions().getGCMode() == LangOptions::HybridGC)
3647 name = "Leak of returned object when not using garbage collection (GC) in "
3648 "dual GC/non-GC code";
3650 assert(getLangOptions().getGCMode() == LangOptions::NonGC);
3651 name = "Leak of returned object";
3654 // Leaks should not be reported if they are post-dominated by a sink.
3655 leakAtReturn = new LeakAtReturn(this, name);
3656 leakAtReturn->setSuppressOnSink(true);
3657 BR.Register(leakAtReturn);
3659 // Second, register leaks within a function/method.
3661 name = "Leak of object when using garbage collection";
3662 else if (getLangOptions().getGCMode() == LangOptions::HybridGC)
3663 name = "Leak of object when not using garbage collection (GC) in "
3664 "dual GC/non-GC code";
3666 assert(getLangOptions().getGCMode() == LangOptions::NonGC);
3670 // Leaks should not be reported if they are post-dominated by sinks.
3671 leakWithinFunction = new LeakWithinFunction(this, name);
3672 leakWithinFunction->setSuppressOnSink(true);
3673 BR.Register(leakWithinFunction);
3675 // Save the reference to the BugReporter.
3678 // Register the RetainReleaseChecker with the ExprEngine object.
3679 // Functionality in CFRefCount will be migrated to RetainReleaseChecker
3681 // FIXME: HACK! Remove TransferFuncs and turn all of CFRefCount into fully
3682 // using the checker mechanism.
3683 Eng.getCheckerManager().registerChecker<RetainReleaseChecker>();
3686 TransferFuncs* ento::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
3687 const LangOptions& lopts) {
3688 return new CFRefCount(Ctx, GCEnabled, lopts);