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/AST/DeclObjC.h"
16 #include "clang/AST/StmtVisitor.h"
17 #include "clang/Basic/LangOptions.h"
18 #include "clang/Basic/SourceManager.h"
19 #include "clang/StaticAnalyzer/BugReporter/BugType.h"
20 #include "clang/StaticAnalyzer/BugReporter/PathDiagnostic.h"
21 #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
22 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
23 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
24 #include "clang/StaticAnalyzer/PathSensitive/ExprEngineBuilders.h"
25 #include "clang/StaticAnalyzer/PathSensitive/GRStateTrait.h"
26 #include "clang/StaticAnalyzer/PathSensitive/TransferFuncs.h"
27 #include "clang/StaticAnalyzer/PathSensitive/SymbolManager.h"
28 #include "llvm/ADT/DenseMap.h"
29 #include "llvm/ADT/FoldingSet.h"
30 #include "llvm/ADT/ImmutableList.h"
31 #include "llvm/ADT/ImmutableMap.h"
32 #include "llvm/ADT/STLExtras.h"
33 #include "llvm/ADT/StringExtras.h"
36 using namespace clang
;
38 using llvm::StringRef
;
39 using llvm::StrInStrNoCase
;
42 class InstanceReceiver
{
44 const LocationContext
*LC
;
46 InstanceReceiver() : LC(0) { }
47 InstanceReceiver(const ObjCMessage
&msg
,
48 const LocationContext
*lc
= 0) : Msg(msg
), LC(lc
) {}
50 bool isValid() const {
51 return Msg
.isValid() && Msg
.isInstanceMessage();
53 operator bool() const {
57 SVal
getSValAsScalarOrLoc(const GRState
*state
) {
59 // We have an expression for the receiver? Fetch the value
60 // of that expression.
61 if (const Expr
*Ex
= Msg
.getInstanceReceiver())
62 return state
->getSValAsScalarOrLoc(Ex
);
64 // Otherwise we are sending a message to super. In this case the
65 // object reference is the same as 'self'.
66 if (const ImplicitParamDecl
*SelfDecl
= LC
->getSelfDecl())
67 return state
->getSVal(state
->getRegion(SelfDecl
, LC
));
72 SourceRange
getSourceRange() const {
74 if (const Expr
*Ex
= Msg
.getInstanceReceiver())
75 return Ex
->getSourceRange();
77 // Otherwise we are sending a message to super.
78 SourceLocation L
= Msg
.getSuperLoc();
80 return SourceRange(L
, L
);
85 static const ObjCMethodDecl
*
86 ResolveToInterfaceMethodDecl(const ObjCMethodDecl
*MD
) {
87 const ObjCInterfaceDecl
*ID
= MD
->getClassInterface();
89 return MD
->isInstanceMethod()
90 ? ID
->lookupInstanceMethod(MD
->getSelector())
91 : ID
->lookupClassMethod(MD
->getSelector());
95 class GenericNodeBuilderRefCount
{
99 EndOfFunctionNodeBuilder
*ENB
;
101 GenericNodeBuilderRefCount(StmtNodeBuilder
&snb
, const Stmt
*s
,
103 : SNB(&snb
), S(s
), tag(t
), ENB(0) {}
105 GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder
&enb
)
106 : SNB(0), S(0), tag(0), ENB(&enb
) {}
108 ExplodedNode
*MakeNode(const GRState
*state
, ExplodedNode
*Pred
) {
110 return SNB
->generateNode(PostStmt(S
, Pred
->getLocationContext(), tag
),
114 return ENB
->generateNode(state
, Pred
);
117 } // end anonymous namespace
119 //===----------------------------------------------------------------------===//
120 // Primitives used for constructing summaries for function/method calls.
121 //===----------------------------------------------------------------------===//
123 /// ArgEffect is used to summarize a function/method call's effect on a
124 /// particular argument.
125 enum ArgEffect
{ Autorelease
, Dealloc
, DecRef
, DecRefMsg
, DoNothing
,
126 DoNothingByRef
, IncRefMsg
, IncRef
, MakeCollectable
, MayEscape
,
127 NewAutoreleasePool
, SelfOwn
, StopTracking
};
130 template <> struct FoldingSetTrait
<ArgEffect
> {
131 static inline void Profile(const ArgEffect X
, FoldingSetNodeID
& ID
) {
132 ID
.AddInteger((unsigned) X
);
135 } // end llvm namespace
137 /// ArgEffects summarizes the effects of a function/method call on all of
139 typedef llvm::ImmutableMap
<unsigned,ArgEffect
> ArgEffects
;
143 /// RetEffect is used to summarize a function/method call's behavior with
144 /// respect to its return value.
147 enum Kind
{ NoRet
, Alias
, OwnedSymbol
, OwnedAllocatedSymbol
,
148 NotOwnedSymbol
, GCNotOwnedSymbol
, ReceiverAlias
,
149 OwnedWhenTrackedReceiver
};
151 enum ObjKind
{ CF
, ObjC
, AnyObj
};
158 RetEffect(Kind k
, unsigned idx
= 0) : K(k
), O(AnyObj
), index(idx
) {}
159 RetEffect(Kind k
, ObjKind o
) : K(k
), O(o
), index(0) {}
162 Kind
getKind() const { return K
; }
164 ObjKind
getObjKind() const { return O
; }
166 unsigned getIndex() const {
167 assert(getKind() == Alias
);
171 bool isOwned() const {
172 return K
== OwnedSymbol
|| K
== OwnedAllocatedSymbol
||
173 K
== OwnedWhenTrackedReceiver
;
176 static RetEffect
MakeOwnedWhenTrackedReceiver() {
177 return RetEffect(OwnedWhenTrackedReceiver
, ObjC
);
180 static RetEffect
MakeAlias(unsigned Idx
) {
181 return RetEffect(Alias
, Idx
);
183 static RetEffect
MakeReceiverAlias() {
184 return RetEffect(ReceiverAlias
);
186 static RetEffect
MakeOwned(ObjKind o
, bool isAllocated
= false) {
187 return RetEffect(isAllocated
? OwnedAllocatedSymbol
: OwnedSymbol
, o
);
189 static RetEffect
MakeNotOwned(ObjKind o
) {
190 return RetEffect(NotOwnedSymbol
, o
);
192 static RetEffect
MakeGCNotOwned() {
193 return RetEffect(GCNotOwnedSymbol
, ObjC
);
196 static RetEffect
MakeNoRet() {
197 return RetEffect(NoRet
);
201 //===----------------------------------------------------------------------===//
202 // Reference-counting logic (typestate + counts).
203 //===----------------------------------------------------------------------===//
208 Owned
= 0, // Owning reference.
209 NotOwned
, // Reference is not owned by still valid (not freed).
210 Released
, // Object has been released.
211 ReturnedOwned
, // Returned object passes ownership to caller.
212 ReturnedNotOwned
, // Return object does not pass ownership to caller.
214 ErrorDeallocNotOwned
, // -dealloc called on non-owned object.
215 ErrorDeallocGC
, // Calling -dealloc with GC enabled.
216 ErrorUseAfterRelease
, // Object used after released.
217 ErrorReleaseNotOwned
, // Release of an object that was not owned.
219 ErrorLeak
, // A memory leak due to excessive reference counts.
220 ErrorLeakReturned
, // A memory leak due to the returning method not having
221 // the correct naming conventions.
223 ErrorOverAutorelease
,
224 ErrorReturnedNotOwned
229 RetEffect::ObjKind okind
;
234 RefVal(Kind k
, RetEffect::ObjKind o
, unsigned cnt
, unsigned acnt
, QualType t
)
235 : kind(k
), okind(o
), Cnt(cnt
), ACnt(acnt
), T(t
) {}
238 Kind
getKind() const { return kind
; }
240 RetEffect::ObjKind
getObjKind() const { return okind
; }
242 unsigned getCount() const { return Cnt
; }
243 unsigned getAutoreleaseCount() const { return ACnt
; }
244 unsigned getCombinedCounts() const { return Cnt
+ ACnt
; }
245 void clearCounts() { Cnt
= 0; ACnt
= 0; }
246 void setCount(unsigned i
) { Cnt
= i
; }
247 void setAutoreleaseCount(unsigned i
) { ACnt
= i
; }
249 QualType
getType() const { return T
; }
251 bool isOwned() const {
252 return getKind() == Owned
;
255 bool isNotOwned() const {
256 return getKind() == NotOwned
;
259 bool isReturnedOwned() const {
260 return getKind() == ReturnedOwned
;
263 bool isReturnedNotOwned() const {
264 return getKind() == ReturnedNotOwned
;
267 static RefVal
makeOwned(RetEffect::ObjKind o
, QualType t
,
268 unsigned Count
= 1) {
269 return RefVal(Owned
, o
, Count
, 0, t
);
272 static RefVal
makeNotOwned(RetEffect::ObjKind o
, QualType t
,
273 unsigned Count
= 0) {
274 return RefVal(NotOwned
, o
, Count
, 0, t
);
277 // Comparison, profiling, and pretty-printing.
279 bool operator==(const RefVal
& X
) const {
280 return kind
== X
.kind
&& Cnt
== X
.Cnt
&& T
== X
.T
&& ACnt
== X
.ACnt
;
283 RefVal
operator-(size_t i
) const {
284 return RefVal(getKind(), getObjKind(), getCount() - i
,
285 getAutoreleaseCount(), getType());
288 RefVal
operator+(size_t i
) const {
289 return RefVal(getKind(), getObjKind(), getCount() + i
,
290 getAutoreleaseCount(), getType());
293 RefVal
operator^(Kind k
) const {
294 return RefVal(k
, getObjKind(), getCount(), getAutoreleaseCount(),
298 RefVal
autorelease() const {
299 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
303 void Profile(llvm::FoldingSetNodeID
& ID
) const {
304 ID
.AddInteger((unsigned) kind
);
310 void print(llvm::raw_ostream
& Out
) const;
313 void RefVal::print(llvm::raw_ostream
& Out
) const {
315 Out
<< "Tracked Type:" << T
.getAsString() << '\n';
318 default: assert(false);
321 unsigned cnt
= getCount();
322 if (cnt
) Out
<< " (+ " << cnt
<< ")";
328 unsigned cnt
= getCount();
329 if (cnt
) Out
<< " (+ " << cnt
<< ")";
333 case ReturnedOwned
: {
334 Out
<< "ReturnedOwned";
335 unsigned cnt
= getCount();
336 if (cnt
) Out
<< " (+ " << cnt
<< ")";
340 case ReturnedNotOwned
: {
341 Out
<< "ReturnedNotOwned";
342 unsigned cnt
= getCount();
343 if (cnt
) Out
<< " (+ " << cnt
<< ")";
352 Out
<< "-dealloc (GC)";
355 case ErrorDeallocNotOwned
:
356 Out
<< "-dealloc (not-owned)";
363 case ErrorLeakReturned
:
364 Out
<< "Leaked (Bad naming)";
367 case ErrorGCLeakReturned
:
368 Out
<< "Leaked (GC-ed at return)";
371 case ErrorUseAfterRelease
:
372 Out
<< "Use-After-Release [ERROR]";
375 case ErrorReleaseNotOwned
:
376 Out
<< "Release of Not-Owned [ERROR]";
379 case RefVal::ErrorOverAutorelease
:
380 Out
<< "Over autoreleased";
383 case RefVal::ErrorReturnedNotOwned
:
384 Out
<< "Non-owned object returned instead of owned";
389 Out
<< " [ARC +" << ACnt
<< ']';
392 } //end anonymous namespace
394 //===----------------------------------------------------------------------===//
395 // RefBindings - State used to track object reference counts.
396 //===----------------------------------------------------------------------===//
398 typedef llvm::ImmutableMap
<SymbolRef
, RefVal
> RefBindings
;
403 struct GRStateTrait
<RefBindings
> : public GRStatePartialTrait
<RefBindings
> {
404 static void* GDMIndex() {
405 static int RefBIndex
= 0;
412 //===----------------------------------------------------------------------===//
414 //===----------------------------------------------------------------------===//
417 class RetainSummary
{
418 /// Args - an ordered vector of (index, ArgEffect) pairs, where index
419 /// specifies the argument (starting from 0). This can be sparsely
420 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
423 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
424 /// do not have an entry in Args.
425 ArgEffect DefaultArgEffect
;
427 /// Receiver - If this summary applies to an Objective-C message expression,
428 /// this is the effect applied to the state of the receiver.
431 /// Ret - The effect on the return value. Used to indicate if the
432 /// function/method call returns a new tracked symbol, returns an
433 /// alias of one of the arguments in the call, and so on.
436 /// EndPath - Indicates that execution of this method/function should
437 /// terminate the simulation of a path.
441 RetainSummary(ArgEffects A
, RetEffect R
, ArgEffect defaultEff
,
442 ArgEffect ReceiverEff
, bool endpath
= false)
443 : Args(A
), DefaultArgEffect(defaultEff
), Receiver(ReceiverEff
), Ret(R
),
446 /// getArg - Return the argument effect on the argument specified by
447 /// idx (starting from 0).
448 ArgEffect
getArg(unsigned idx
) const {
449 if (const ArgEffect
*AE
= Args
.lookup(idx
))
452 return DefaultArgEffect
;
455 void addArg(ArgEffects::Factory
&af
, unsigned idx
, ArgEffect e
) {
456 Args
= af
.add(Args
, idx
, e
);
459 /// setDefaultArgEffect - Set the default argument effect.
460 void setDefaultArgEffect(ArgEffect E
) {
461 DefaultArgEffect
= E
;
464 /// getRetEffect - Returns the effect on the return value of the call.
465 RetEffect
getRetEffect() const { return Ret
; }
467 /// setRetEffect - Set the effect of the return value of the call.
468 void setRetEffect(RetEffect E
) { Ret
= E
; }
470 /// isEndPath - Returns true if executing the given method/function should
471 /// terminate the path.
472 bool isEndPath() const { return EndPath
; }
475 /// Sets the effect on the receiver of the message.
476 void setReceiverEffect(ArgEffect e
) { Receiver
= e
; }
478 /// getReceiverEffect - Returns the effect on the receiver of the call.
479 /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
480 ArgEffect
getReceiverEffect() const { return Receiver
; }
482 } // end anonymous namespace
484 //===----------------------------------------------------------------------===//
485 // Data structures for constructing summaries.
486 //===----------------------------------------------------------------------===//
489 class ObjCSummaryKey
{
493 ObjCSummaryKey(IdentifierInfo
* ii
, Selector s
)
496 ObjCSummaryKey(const ObjCInterfaceDecl
* d
, Selector s
)
497 : II(d
? d
->getIdentifier() : 0), S(s
) {}
499 ObjCSummaryKey(const ObjCInterfaceDecl
* d
, IdentifierInfo
*ii
, Selector s
)
500 : II(d
? d
->getIdentifier() : ii
), S(s
) {}
502 ObjCSummaryKey(Selector s
)
505 IdentifierInfo
* getIdentifier() const { return II
; }
506 Selector
getSelector() const { return S
; }
511 template <> struct DenseMapInfo
<ObjCSummaryKey
> {
512 static inline ObjCSummaryKey
getEmptyKey() {
513 return ObjCSummaryKey(DenseMapInfo
<IdentifierInfo
*>::getEmptyKey(),
514 DenseMapInfo
<Selector
>::getEmptyKey());
517 static inline ObjCSummaryKey
getTombstoneKey() {
518 return ObjCSummaryKey(DenseMapInfo
<IdentifierInfo
*>::getTombstoneKey(),
519 DenseMapInfo
<Selector
>::getTombstoneKey());
522 static unsigned getHashValue(const ObjCSummaryKey
&V
) {
523 return (DenseMapInfo
<IdentifierInfo
*>::getHashValue(V
.getIdentifier())
525 | (DenseMapInfo
<Selector
>::getHashValue(V
.getSelector())
529 static bool isEqual(const ObjCSummaryKey
& LHS
, const ObjCSummaryKey
& RHS
) {
530 return DenseMapInfo
<IdentifierInfo
*>::isEqual(LHS
.getIdentifier(),
531 RHS
.getIdentifier()) &&
532 DenseMapInfo
<Selector
>::isEqual(LHS
.getSelector(),
538 struct isPodLike
<ObjCSummaryKey
> { static const bool value
= true; };
539 } // end llvm namespace
542 class ObjCSummaryCache
{
543 typedef llvm::DenseMap
<ObjCSummaryKey
, RetainSummary
*> MapTy
;
546 ObjCSummaryCache() {}
548 RetainSummary
* find(const ObjCInterfaceDecl
* D
, IdentifierInfo
*ClsName
,
550 // Lookup the method using the decl for the class @interface. If we
551 // have no decl, lookup using the class name.
552 return D
? find(D
, S
) : find(ClsName
, S
);
555 RetainSummary
* find(const ObjCInterfaceDecl
* D
, Selector S
) {
556 // Do a lookup with the (D,S) pair. If we find a match return
558 ObjCSummaryKey
K(D
, S
);
559 MapTy::iterator I
= M
.find(K
);
561 if (I
!= M
.end() || !D
)
564 // Walk the super chain. If we find a hit with a parent, we'll end
565 // up returning that summary. We actually allow that key (null,S), as
566 // we cache summaries for the null ObjCInterfaceDecl* to allow us to
567 // generate initial summaries without having to worry about NSObject
569 // FIXME: We may change this at some point.
570 for (ObjCInterfaceDecl
* C
=D
->getSuperClass() ;; C
=C
->getSuperClass()) {
571 if ((I
= M
.find(ObjCSummaryKey(C
, S
))) != M
.end())
578 // Cache the summary with original key to make the next lookup faster
579 // and return the iterator.
580 RetainSummary
*Summ
= I
->second
;
585 RetainSummary
* find(IdentifierInfo
* II
, Selector S
) {
586 // FIXME: Class method lookup. Right now we dont' have a good way
587 // of going between IdentifierInfo* and the class hierarchy.
588 MapTy::iterator I
= M
.find(ObjCSummaryKey(II
, S
));
591 I
= M
.find(ObjCSummaryKey(S
));
593 return I
== M
.end() ? NULL
: I
->second
;
596 RetainSummary
*& operator[](ObjCSummaryKey K
) {
600 RetainSummary
*& operator[](Selector S
) {
601 return M
[ ObjCSummaryKey(S
) ];
604 } // end anonymous namespace
606 //===----------------------------------------------------------------------===//
607 // Data structures for managing collections of summaries.
608 //===----------------------------------------------------------------------===//
611 class RetainSummaryManager
{
613 //==-----------------------------------------------------------------==//
615 //==-----------------------------------------------------------------==//
617 typedef llvm::DenseMap
<const FunctionDecl
*, RetainSummary
*>
620 typedef ObjCSummaryCache ObjCMethodSummariesTy
;
622 //==-----------------------------------------------------------------==//
624 //==-----------------------------------------------------------------==//
626 /// Ctx - The ASTContext object for the analyzed ASTs.
629 /// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
630 /// "CFDictionaryCreate".
631 IdentifierInfo
* CFDictionaryCreateII
;
633 /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
634 const bool GCEnabled
;
636 /// FuncSummaries - A map from FunctionDecls to summaries.
637 FuncSummariesTy FuncSummaries
;
639 /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
641 ObjCMethodSummariesTy ObjCClassMethodSummaries
;
643 /// ObjCMethodSummaries - A map from selectors to summaries.
644 ObjCMethodSummariesTy ObjCMethodSummaries
;
646 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
647 /// and all other data used by the checker.
648 llvm::BumpPtrAllocator BPAlloc
;
650 /// AF - A factory for ArgEffects objects.
651 ArgEffects::Factory AF
;
653 /// ScratchArgs - A holding buffer for construct ArgEffects.
654 ArgEffects ScratchArgs
;
656 /// ObjCAllocRetE - Default return effect for methods returning Objective-C
658 RetEffect ObjCAllocRetE
;
660 /// ObjCInitRetE - Default return effect for init methods returning
661 /// Objective-C objects.
662 RetEffect ObjCInitRetE
;
664 RetainSummary DefaultSummary
;
665 RetainSummary
* StopSummary
;
667 //==-----------------------------------------------------------------==//
669 //==-----------------------------------------------------------------==//
671 /// getArgEffects - Returns a persistent ArgEffects object based on the
672 /// data in ScratchArgs.
673 ArgEffects
getArgEffects();
675 enum UnaryFuncKind
{ cfretain
, cfrelease
, cfmakecollectable
};
678 RetEffect
getObjAllocRetEffect() const { return ObjCAllocRetE
; }
680 RetainSummary
*getDefaultSummary() {
681 RetainSummary
*Summ
= (RetainSummary
*) BPAlloc
.Allocate
<RetainSummary
>();
682 return new (Summ
) RetainSummary(DefaultSummary
);
685 RetainSummary
* getUnarySummary(const FunctionType
* FT
, UnaryFuncKind func
);
687 RetainSummary
* getCFSummaryCreateRule(const FunctionDecl
* FD
);
688 RetainSummary
* getCFSummaryGetRule(const FunctionDecl
* FD
);
689 RetainSummary
* getCFCreateGetRuleSummary(const FunctionDecl
* FD
,
692 RetainSummary
* getPersistentSummary(ArgEffects AE
, RetEffect RetEff
,
693 ArgEffect ReceiverEff
= DoNothing
,
694 ArgEffect DefaultEff
= MayEscape
,
695 bool isEndPath
= false);
697 RetainSummary
* getPersistentSummary(RetEffect RE
,
698 ArgEffect ReceiverEff
= DoNothing
,
699 ArgEffect DefaultEff
= MayEscape
) {
700 return getPersistentSummary(getArgEffects(), RE
, ReceiverEff
, DefaultEff
);
703 RetainSummary
*getPersistentStopSummary() {
707 StopSummary
= getPersistentSummary(RetEffect::MakeNoRet(),
708 StopTracking
, StopTracking
);
713 RetainSummary
*getInitMethodSummary(QualType RetTy
);
715 void InitializeClassMethodSummaries();
716 void InitializeMethodSummaries();
718 void addNSObjectClsMethSummary(Selector S
, RetainSummary
*Summ
) {
719 ObjCClassMethodSummaries
[S
] = Summ
;
722 void addNSObjectMethSummary(Selector S
, RetainSummary
*Summ
) {
723 ObjCMethodSummaries
[S
] = Summ
;
726 void addClassMethSummary(const char* Cls
, const char* nullaryName
,
727 RetainSummary
*Summ
) {
728 IdentifierInfo
* ClsII
= &Ctx
.Idents
.get(Cls
);
729 Selector S
= GetNullarySelector(nullaryName
, Ctx
);
730 ObjCClassMethodSummaries
[ObjCSummaryKey(ClsII
, S
)] = Summ
;
733 void addInstMethSummary(const char* Cls
, const char* nullaryName
,
734 RetainSummary
*Summ
) {
735 IdentifierInfo
* ClsII
= &Ctx
.Idents
.get(Cls
);
736 Selector S
= GetNullarySelector(nullaryName
, Ctx
);
737 ObjCMethodSummaries
[ObjCSummaryKey(ClsII
, S
)] = Summ
;
740 Selector
generateSelector(va_list argp
) {
741 llvm::SmallVector
<IdentifierInfo
*, 10> II
;
743 while (const char* s
= va_arg(argp
, const char*))
744 II
.push_back(&Ctx
.Idents
.get(s
));
746 return Ctx
.Selectors
.getSelector(II
.size(), &II
[0]);
749 void addMethodSummary(IdentifierInfo
*ClsII
, ObjCMethodSummariesTy
& Summaries
,
750 RetainSummary
* Summ
, va_list argp
) {
751 Selector S
= generateSelector(argp
);
752 Summaries
[ObjCSummaryKey(ClsII
, S
)] = Summ
;
755 void addInstMethSummary(const char* Cls
, RetainSummary
* Summ
, ...) {
757 va_start(argp
, Summ
);
758 addMethodSummary(&Ctx
.Idents
.get(Cls
), ObjCMethodSummaries
, Summ
, argp
);
762 void addClsMethSummary(const char* Cls
, RetainSummary
* Summ
, ...) {
764 va_start(argp
, Summ
);
765 addMethodSummary(&Ctx
.Idents
.get(Cls
),ObjCClassMethodSummaries
, Summ
, argp
);
769 void addClsMethSummary(IdentifierInfo
*II
, RetainSummary
* Summ
, ...) {
771 va_start(argp
, Summ
);
772 addMethodSummary(II
, ObjCClassMethodSummaries
, Summ
, argp
);
776 void addPanicSummary(const char* Cls
, ...) {
777 RetainSummary
* Summ
= getPersistentSummary(AF
.getEmptyMap(),
778 RetEffect::MakeNoRet(),
779 DoNothing
, DoNothing
, true);
781 va_start (argp
, Cls
);
782 addMethodSummary(&Ctx
.Idents
.get(Cls
), ObjCMethodSummaries
, Summ
, argp
);
788 RetainSummaryManager(ASTContext
& ctx
, bool gcenabled
)
790 CFDictionaryCreateII(&ctx
.Idents
.get("CFDictionaryCreate")),
791 GCEnabled(gcenabled
), AF(BPAlloc
), ScratchArgs(AF
.getEmptyMap()),
792 ObjCAllocRetE(gcenabled
? RetEffect::MakeGCNotOwned()
793 : RetEffect::MakeOwned(RetEffect::ObjC
, true)),
794 ObjCInitRetE(gcenabled
? RetEffect::MakeGCNotOwned()
795 : RetEffect::MakeOwnedWhenTrackedReceiver()),
796 DefaultSummary(AF
.getEmptyMap() /* per-argument effects (none) */,
797 RetEffect::MakeNoRet() /* return effect */,
798 MayEscape
, /* default argument effect */
799 DoNothing
/* receiver effect */),
802 InitializeClassMethodSummaries();
803 InitializeMethodSummaries();
806 ~RetainSummaryManager();
808 RetainSummary
* getSummary(const FunctionDecl
* FD
);
810 RetainSummary
*getInstanceMethodSummary(const ObjCMessage
&msg
,
811 const GRState
*state
,
812 const LocationContext
*LC
);
814 RetainSummary
* getInstanceMethodSummary(const ObjCMessage
&msg
,
815 const ObjCInterfaceDecl
* ID
) {
816 return getInstanceMethodSummary(msg
.getSelector(), 0,
817 ID
, msg
.getMethodDecl(), msg
.getType(Ctx
));
820 RetainSummary
* getInstanceMethodSummary(Selector S
, IdentifierInfo
*ClsName
,
821 const ObjCInterfaceDecl
* ID
,
822 const ObjCMethodDecl
*MD
,
825 RetainSummary
*getClassMethodSummary(Selector S
, IdentifierInfo
*ClsName
,
826 const ObjCInterfaceDecl
*ID
,
827 const ObjCMethodDecl
*MD
,
830 RetainSummary
*getClassMethodSummary(const ObjCMessage
&msg
) {
831 const ObjCInterfaceDecl
*Class
= 0;
832 if (!msg
.isInstanceMessage())
833 Class
= msg
.getReceiverInterface();
835 return getClassMethodSummary(msg
.getSelector(),
836 Class
? Class
->getIdentifier() : 0,
838 msg
.getMethodDecl(), msg
.getType(Ctx
));
841 /// getMethodSummary - This version of getMethodSummary is used to query
842 /// the summary for the current method being analyzed.
843 RetainSummary
*getMethodSummary(const ObjCMethodDecl
*MD
) {
844 // FIXME: Eventually this should be unneeded.
845 const ObjCInterfaceDecl
*ID
= MD
->getClassInterface();
846 Selector S
= MD
->getSelector();
847 IdentifierInfo
*ClsName
= ID
->getIdentifier();
848 QualType ResultTy
= MD
->getResultType();
850 // Resolve the method decl last.
851 if (const ObjCMethodDecl
*InterfaceMD
= ResolveToInterfaceMethodDecl(MD
))
854 if (MD
->isInstanceMethod())
855 return getInstanceMethodSummary(S
, ClsName
, ID
, MD
, ResultTy
);
857 return getClassMethodSummary(S
, ClsName
, ID
, MD
, ResultTy
);
860 RetainSummary
* getCommonMethodSummary(const ObjCMethodDecl
* MD
,
861 Selector S
, QualType RetTy
);
863 void updateSummaryFromAnnotations(RetainSummary
&Summ
,
864 const ObjCMethodDecl
*MD
);
866 void updateSummaryFromAnnotations(RetainSummary
&Summ
,
867 const FunctionDecl
*FD
);
869 bool isGCEnabled() const { return GCEnabled
; }
871 RetainSummary
*copySummary(RetainSummary
*OldSumm
) {
872 RetainSummary
*Summ
= (RetainSummary
*) BPAlloc
.Allocate
<RetainSummary
>();
873 new (Summ
) RetainSummary(*OldSumm
);
878 } // end anonymous namespace
880 //===----------------------------------------------------------------------===//
881 // Implementation of checker data structures.
882 //===----------------------------------------------------------------------===//
884 RetainSummaryManager::~RetainSummaryManager() {}
886 ArgEffects
RetainSummaryManager::getArgEffects() {
887 ArgEffects AE
= ScratchArgs
;
888 ScratchArgs
= AF
.getEmptyMap();
893 RetainSummaryManager::getPersistentSummary(ArgEffects AE
, RetEffect RetEff
,
894 ArgEffect ReceiverEff
,
895 ArgEffect DefaultEff
,
897 // Create the summary and return it.
898 RetainSummary
*Summ
= (RetainSummary
*) BPAlloc
.Allocate
<RetainSummary
>();
899 new (Summ
) RetainSummary(AE
, RetEff
, DefaultEff
, ReceiverEff
, isEndPath
);
903 //===----------------------------------------------------------------------===//
904 // Summary creation for functions (largely uses of Core Foundation).
905 //===----------------------------------------------------------------------===//
907 static bool isRetain(const FunctionDecl
* FD
, StringRef FName
) {
908 return FName
.endswith("Retain");
911 static bool isRelease(const FunctionDecl
* FD
, StringRef FName
) {
912 return FName
.endswith("Release");
915 RetainSummary
* RetainSummaryManager::getSummary(const FunctionDecl
* FD
) {
916 // Look up a summary in our cache of FunctionDecls -> Summaries.
917 FuncSummariesTy::iterator I
= FuncSummaries
.find(FD
);
918 if (I
!= FuncSummaries
.end())
921 // No summary? Generate one.
922 RetainSummary
*S
= 0;
925 // We generate "stop" summaries for implicitly defined functions.
926 if (FD
->isImplicit()) {
927 S
= getPersistentStopSummary();
931 // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
933 const FunctionType
* FT
= FD
->getType()->getAs
<FunctionType
>();
934 const IdentifierInfo
*II
= FD
->getIdentifier();
938 StringRef FName
= II
->getName();
940 // Strip away preceding '_'. Doing this here will effect all the checks
942 FName
= FName
.substr(FName
.find_first_not_of('_'));
944 // Inspect the result type.
945 QualType RetTy
= FT
->getResultType();
947 // FIXME: This should all be refactored into a chain of "summary lookup"
949 assert(ScratchArgs
.isEmpty());
951 if (FName
== "pthread_create") {
952 // Part of: <rdar://problem/7299394>. This will be addressed
954 S
= getPersistentStopSummary();
955 } else if (FName
== "NSMakeCollectable") {
956 // Handle: id NSMakeCollectable(CFTypeRef)
957 S
= (RetTy
->isObjCIdType())
958 ? getUnarySummary(FT
, cfmakecollectable
)
959 : getPersistentStopSummary();
960 } else if (FName
== "IOBSDNameMatching" ||
961 FName
== "IOServiceMatching" ||
962 FName
== "IOServiceNameMatching" ||
963 FName
== "IORegistryEntryIDMatching" ||
964 FName
== "IOOpenFirmwarePathMatching") {
965 // Part of <rdar://problem/6961230>. (IOKit)
966 // This should be addressed using a API table.
967 S
= getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF
, true),
968 DoNothing
, DoNothing
);
969 } else if (FName
== "IOServiceGetMatchingService" ||
970 FName
== "IOServiceGetMatchingServices") {
971 // FIXES: <rdar://problem/6326900>
972 // This should be addressed using a API table. This strcmp is also
973 // a little gross, but there is no need to super optimize here.
974 ScratchArgs
= AF
.add(ScratchArgs
, 1, DecRef
);
975 S
= getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, DoNothing
);
976 } else if (FName
== "IOServiceAddNotification" ||
977 FName
== "IOServiceAddMatchingNotification") {
978 // Part of <rdar://problem/6961230>. (IOKit)
979 // This should be addressed using a API table.
980 ScratchArgs
= AF
.add(ScratchArgs
, 2, DecRef
);
981 S
= getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, DoNothing
);
982 } else if (FName
== "CVPixelBufferCreateWithBytes") {
983 // FIXES: <rdar://problem/7283567>
984 // Eventually this can be improved by recognizing that the pixel
985 // buffer passed to CVPixelBufferCreateWithBytes is released via
986 // a callback and doing full IPA to make sure this is done correctly.
987 // FIXME: This function has an out parameter that returns an
989 ScratchArgs
= AF
.add(ScratchArgs
, 7, StopTracking
);
990 S
= getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, DoNothing
);
991 } else if (FName
== "CGBitmapContextCreateWithData") {
992 // FIXES: <rdar://problem/7358899>
993 // Eventually this can be improved by recognizing that 'releaseInfo'
994 // passed to CGBitmapContextCreateWithData is released via
995 // a callback and doing full IPA to make sure this is done correctly.
996 ScratchArgs
= AF
.add(ScratchArgs
, 8, StopTracking
);
997 S
= getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF
, true),
998 DoNothing
, DoNothing
);
999 } else if (FName
== "CVPixelBufferCreateWithPlanarBytes") {
1000 // FIXES: <rdar://problem/7283567>
1001 // Eventually this can be improved by recognizing that the pixel
1002 // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
1003 // via a callback and doing full IPA to make sure this is done
1005 ScratchArgs
= AF
.add(ScratchArgs
, 12, StopTracking
);
1006 S
= getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, DoNothing
);
1009 // Did we get a summary?
1013 // Enable this code once the semantics of NSDeallocateObject are resolved
1014 // for GC. <rdar://problem/6619988>
1016 // Handle: NSDeallocateObject(id anObject);
1017 // This method does allow 'nil' (although we don't check it now).
1018 if (strcmp(FName
, "NSDeallocateObject") == 0) {
1019 return RetTy
== Ctx
.VoidTy
1020 ? getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, Dealloc
)
1021 : getPersistentStopSummary();
1025 if (RetTy
->isPointerType()) {
1026 // For CoreFoundation ('CF') types.
1027 if (cocoa::isRefType(RetTy
, "CF", FName
)) {
1028 if (isRetain(FD
, FName
))
1029 S
= getUnarySummary(FT
, cfretain
);
1030 else if (FName
.find("MakeCollectable") != StringRef::npos
)
1031 S
= getUnarySummary(FT
, cfmakecollectable
);
1033 S
= getCFCreateGetRuleSummary(FD
, FName
);
1038 // For CoreGraphics ('CG') types.
1039 if (cocoa::isRefType(RetTy
, "CG", FName
)) {
1040 if (isRetain(FD
, FName
))
1041 S
= getUnarySummary(FT
, cfretain
);
1043 S
= getCFCreateGetRuleSummary(FD
, FName
);
1048 // For the Disk Arbitration API (DiskArbitration/DADisk.h)
1049 if (cocoa::isRefType(RetTy
, "DADisk") ||
1050 cocoa::isRefType(RetTy
, "DADissenter") ||
1051 cocoa::isRefType(RetTy
, "DASessionRef")) {
1052 S
= getCFCreateGetRuleSummary(FD
, FName
);
1059 // Check for release functions, the only kind of functions that we care
1060 // about that don't return a pointer type.
1061 if (FName
[0] == 'C' && (FName
[1] == 'F' || FName
[1] == 'G')) {
1063 FName
= FName
.substr(FName
.startswith("CGCF") ? 4 : 2);
1065 if (isRelease(FD
, FName
))
1066 S
= getUnarySummary(FT
, cfrelease
);
1068 assert (ScratchArgs
.isEmpty());
1069 // Remaining CoreFoundation and CoreGraphics functions.
1070 // We use to assume that they all strictly followed the ownership idiom
1071 // and that ownership cannot be transferred. While this is technically
1072 // correct, many methods allow a tracked object to escape. For example:
1074 // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
1075 // CFDictionaryAddValue(y, key, x);
1077 // ... it is okay to use 'x' since 'y' has a reference to it
1079 // We handle this and similar cases with the follow heuristic. If the
1080 // function name contains "InsertValue", "SetValue", "AddValue",
1081 // "AppendValue", or "SetAttribute", then we assume that arguments may
1082 // "escape." This means that something else holds on to the object,
1083 // allowing it be used even after its local retain count drops to 0.
1084 ArgEffect E
= (StrInStrNoCase(FName
, "InsertValue") != StringRef::npos
||
1085 StrInStrNoCase(FName
, "AddValue") != StringRef::npos
||
1086 StrInStrNoCase(FName
, "SetValue") != StringRef::npos
||
1087 StrInStrNoCase(FName
, "AppendValue") != StringRef::npos
||
1088 StrInStrNoCase(FName
, "SetAttribute") != StringRef::npos
)
1089 ? MayEscape
: DoNothing
;
1091 S
= getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, E
);
1098 S
= getDefaultSummary();
1100 // Annotations override defaults.
1102 updateSummaryFromAnnotations(*S
, FD
);
1104 FuncSummaries
[FD
] = S
;
1109 RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl
* FD
,
1112 if (FName
.find("Create") != StringRef::npos
||
1113 FName
.find("Copy") != StringRef::npos
)
1114 return getCFSummaryCreateRule(FD
);
1116 if (FName
.find("Get") != StringRef::npos
)
1117 return getCFSummaryGetRule(FD
);
1119 return getDefaultSummary();
1123 RetainSummaryManager::getUnarySummary(const FunctionType
* FT
,
1124 UnaryFuncKind func
) {
1126 // Sanity check that this is *really* a unary function. This can
1127 // happen if people do weird things.
1128 const FunctionProtoType
* FTP
= dyn_cast
<FunctionProtoType
>(FT
);
1129 if (!FTP
|| FTP
->getNumArgs() != 1)
1130 return getPersistentStopSummary();
1132 assert (ScratchArgs
.isEmpty());
1136 ScratchArgs
= AF
.add(ScratchArgs
, 0, IncRef
);
1137 return getPersistentSummary(RetEffect::MakeAlias(0),
1138 DoNothing
, DoNothing
);
1142 ScratchArgs
= AF
.add(ScratchArgs
, 0, DecRef
);
1143 return getPersistentSummary(RetEffect::MakeNoRet(),
1144 DoNothing
, DoNothing
);
1147 case cfmakecollectable
: {
1148 ScratchArgs
= AF
.add(ScratchArgs
, 0, MakeCollectable
);
1149 return getPersistentSummary(RetEffect::MakeAlias(0),DoNothing
, DoNothing
);
1153 assert (false && "Not a supported unary function.");
1154 return getDefaultSummary();
1159 RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl
* FD
) {
1160 assert (ScratchArgs
.isEmpty());
1162 if (FD
->getIdentifier() == CFDictionaryCreateII
) {
1163 ScratchArgs
= AF
.add(ScratchArgs
, 1, DoNothingByRef
);
1164 ScratchArgs
= AF
.add(ScratchArgs
, 2, DoNothingByRef
);
1167 return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF
, true));
1171 RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl
* FD
) {
1172 assert (ScratchArgs
.isEmpty());
1173 return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF
),
1174 DoNothing
, DoNothing
);
1177 //===----------------------------------------------------------------------===//
1178 // Summary creation for Selectors.
1179 //===----------------------------------------------------------------------===//
1182 RetainSummaryManager::getInitMethodSummary(QualType RetTy
) {
1183 assert(ScratchArgs
.isEmpty());
1184 // 'init' methods conceptually return a newly allocated object and claim
1186 if (cocoa::isCocoaObjectRef(RetTy
) || cocoa::isCFObjectRef(RetTy
))
1187 return getPersistentSummary(ObjCInitRetE
, DecRefMsg
);
1189 return getDefaultSummary();
1193 RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary
&Summ
,
1194 const FunctionDecl
*FD
) {
1198 // Effects on the parameters.
1199 unsigned parm_idx
= 0;
1200 for (FunctionDecl::param_const_iterator pi
= FD
->param_begin(),
1201 pe
= FD
->param_end(); pi
!= pe
; ++pi
) {
1202 const ParmVarDecl
*pd
= *pi
;
1203 if (pd
->getAttr
<NSConsumedAttr
>()) {
1205 Summ
.addArg(AF
, parm_idx
, DecRef
);
1207 else if(pd
->getAttr
<CFConsumedAttr
>()) {
1208 Summ
.addArg(AF
, parm_idx
, DecRef
);
1212 QualType RetTy
= FD
->getResultType();
1214 // Determine if there is a special return effect for this method.
1215 if (cocoa::isCocoaObjectRef(RetTy
)) {
1216 if (FD
->getAttr
<NSReturnsRetainedAttr
>()) {
1217 Summ
.setRetEffect(ObjCAllocRetE
);
1219 else if (FD
->getAttr
<CFReturnsRetainedAttr
>()) {
1220 Summ
.setRetEffect(RetEffect::MakeOwned(RetEffect::CF
, true));
1222 else if (FD
->getAttr
<NSReturnsNotRetainedAttr
>()) {
1223 Summ
.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC
));
1225 else if (FD
->getAttr
<CFReturnsNotRetainedAttr
>()) {
1226 Summ
.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF
));
1229 else if (RetTy
->getAs
<PointerType
>()) {
1230 if (FD
->getAttr
<CFReturnsRetainedAttr
>()) {
1231 Summ
.setRetEffect(RetEffect::MakeOwned(RetEffect::CF
, true));
1237 RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary
&Summ
,
1238 const ObjCMethodDecl
*MD
) {
1242 bool isTrackedLoc
= false;
1244 // Effects on the receiver.
1245 if (MD
->getAttr
<NSConsumesSelfAttr
>()) {
1247 Summ
.setReceiverEffect(DecRefMsg
);
1250 // Effects on the parameters.
1251 unsigned parm_idx
= 0;
1252 for (ObjCMethodDecl::param_iterator pi
=MD
->param_begin(), pe
=MD
->param_end();
1253 pi
!= pe
; ++pi
, ++parm_idx
) {
1254 const ParmVarDecl
*pd
= *pi
;
1255 if (pd
->getAttr
<NSConsumedAttr
>()) {
1257 Summ
.addArg(AF
, parm_idx
, DecRef
);
1259 else if(pd
->getAttr
<CFConsumedAttr
>()) {
1260 Summ
.addArg(AF
, parm_idx
, DecRef
);
1264 // Determine if there is a special return effect for this method.
1265 if (cocoa::isCocoaObjectRef(MD
->getResultType())) {
1266 if (MD
->getAttr
<NSReturnsRetainedAttr
>()) {
1267 Summ
.setRetEffect(ObjCAllocRetE
);
1270 if (MD
->getAttr
<NSReturnsNotRetainedAttr
>()) {
1271 Summ
.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC
));
1275 isTrackedLoc
= true;
1279 isTrackedLoc
= MD
->getResultType()->getAs
<PointerType
>() != NULL
;
1282 if (MD
->getAttr
<CFReturnsRetainedAttr
>())
1283 Summ
.setRetEffect(RetEffect::MakeOwned(RetEffect::CF
, true));
1284 else if (MD
->getAttr
<CFReturnsNotRetainedAttr
>())
1285 Summ
.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF
));
1290 RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl
* MD
,
1291 Selector S
, QualType RetTy
) {
1294 // Scan the method decl for 'void*' arguments. These should be treated
1295 // as 'StopTracking' because they are often used with delegates.
1296 // Delegates are a frequent form of false positives with the retain
1299 for (ObjCMethodDecl::param_iterator I
= MD
->param_begin(),
1300 E
= MD
->param_end(); I
!= E
; ++I
, ++i
)
1301 if (ParmVarDecl
*PD
= *I
) {
1302 QualType Ty
= Ctx
.getCanonicalType(PD
->getType());
1303 if (Ty
.getLocalUnqualifiedType() == Ctx
.VoidPtrTy
)
1304 ScratchArgs
= AF
.add(ScratchArgs
, i
, StopTracking
);
1308 // Any special effect for the receiver?
1309 ArgEffect ReceiverEff
= DoNothing
;
1311 // If one of the arguments in the selector has the keyword 'delegate' we
1312 // should stop tracking the reference count for the receiver. This is
1313 // because the reference count is quite possibly handled by a delegate
1315 if (S
.isKeywordSelector()) {
1316 const std::string
&str
= S
.getAsString();
1317 assert(!str
.empty());
1318 if (StrInStrNoCase(str
, "delegate:") != StringRef::npos
)
1319 ReceiverEff
= StopTracking
;
1322 // Look for methods that return an owned object.
1323 if (cocoa::isCocoaObjectRef(RetTy
)) {
1324 // EXPERIMENTAL: assume the Cocoa conventions for all objects returned
1325 // by instance methods.
1326 RetEffect E
= cocoa::followsFundamentalRule(S
)
1327 ? ObjCAllocRetE
: RetEffect::MakeNotOwned(RetEffect::ObjC
);
1329 return getPersistentSummary(E
, ReceiverEff
, MayEscape
);
1332 // Look for methods that return an owned core foundation object.
1333 if (cocoa::isCFObjectRef(RetTy
)) {
1334 RetEffect E
= cocoa::followsFundamentalRule(S
)
1335 ? RetEffect::MakeOwned(RetEffect::CF
, true)
1336 : RetEffect::MakeNotOwned(RetEffect::CF
);
1338 return getPersistentSummary(E
, ReceiverEff
, MayEscape
);
1341 if (ScratchArgs
.isEmpty() && ReceiverEff
== DoNothing
)
1342 return getDefaultSummary();
1344 return getPersistentSummary(RetEffect::MakeNoRet(), ReceiverEff
, MayEscape
);
1348 RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage
&msg
,
1349 const GRState
*state
,
1350 const LocationContext
*LC
) {
1352 // We need the type-information of the tracked receiver object
1353 // Retrieve it from the state.
1354 const Expr
*Receiver
= msg
.getInstanceReceiver();
1355 const ObjCInterfaceDecl
* ID
= 0;
1357 // FIXME: Is this really working as expected? There are cases where
1358 // we just use the 'ID' from the message expression.
1362 receiverV
= state
->getSValAsScalarOrLoc(Receiver
);
1364 // FIXME: Eventually replace the use of state->get<RefBindings> with
1365 // a generic API for reasoning about the Objective-C types of symbolic
1367 if (SymbolRef Sym
= receiverV
.getAsLocSymbol())
1368 if (const RefVal
*T
= state
->get
<RefBindings
>(Sym
))
1369 if (const ObjCObjectPointerType
* PT
=
1370 T
->getType()->getAs
<ObjCObjectPointerType
>())
1371 ID
= PT
->getInterfaceDecl();
1373 // FIXME: this is a hack. This may or may not be the actual method
1376 if (const ObjCObjectPointerType
*PT
=
1377 Receiver
->getType()->getAs
<ObjCObjectPointerType
>())
1378 ID
= PT
->getInterfaceDecl();
1381 // FIXME: Hack for 'super'.
1382 ID
= msg
.getReceiverInterface();
1385 // FIXME: The receiver could be a reference to a class, meaning that
1386 // we should use the class method.
1387 RetainSummary
*Summ
= getInstanceMethodSummary(msg
, ID
);
1389 // Special-case: are we sending a mesage to "self"?
1390 // This is a hack. When we have full-IP this should be removed.
1391 if (isa
<ObjCMethodDecl
>(LC
->getDecl()) && Receiver
) {
1392 if (const loc::MemRegionVal
*L
= dyn_cast
<loc::MemRegionVal
>(&receiverV
)) {
1393 // Get the region associated with 'self'.
1394 if (const ImplicitParamDecl
*SelfDecl
= LC
->getSelfDecl()) {
1395 SVal SelfVal
= state
->getSVal(state
->getRegion(SelfDecl
, LC
));
1396 if (L
->StripCasts() == SelfVal
.getAsRegion()) {
1397 // Update the summary to make the default argument effect
1399 Summ
= copySummary(Summ
);
1400 Summ
->setDefaultArgEffect(StopTracking
);
1406 return Summ
? Summ
: getDefaultSummary();
1410 RetainSummaryManager::getInstanceMethodSummary(Selector S
,
1411 IdentifierInfo
*ClsName
,
1412 const ObjCInterfaceDecl
* ID
,
1413 const ObjCMethodDecl
*MD
,
1416 // Look up a summary in our summary cache.
1417 RetainSummary
*Summ
= ObjCMethodSummaries
.find(ID
, ClsName
, S
);
1420 assert(ScratchArgs
.isEmpty());
1422 // "initXXX": pass-through for receiver.
1423 if (cocoa::deriveNamingConvention(S
) == cocoa::InitRule
)
1424 Summ
= getInitMethodSummary(RetTy
);
1426 Summ
= getCommonMethodSummary(MD
, S
, RetTy
);
1428 // Annotations override defaults.
1429 updateSummaryFromAnnotations(*Summ
, MD
);
1431 // Memoize the summary.
1432 ObjCMethodSummaries
[ObjCSummaryKey(ID
, ClsName
, S
)] = Summ
;
1439 RetainSummaryManager::getClassMethodSummary(Selector S
, IdentifierInfo
*ClsName
,
1440 const ObjCInterfaceDecl
*ID
,
1441 const ObjCMethodDecl
*MD
,
1444 assert(ClsName
&& "Class name must be specified.");
1445 RetainSummary
*Summ
= ObjCClassMethodSummaries
.find(ID
, ClsName
, S
);
1448 Summ
= getCommonMethodSummary(MD
, S
, RetTy
);
1449 // Annotations override defaults.
1450 updateSummaryFromAnnotations(*Summ
, MD
);
1451 // Memoize the summary.
1452 ObjCClassMethodSummaries
[ObjCSummaryKey(ID
, ClsName
, S
)] = Summ
;
1458 void RetainSummaryManager::InitializeClassMethodSummaries() {
1459 assert(ScratchArgs
.isEmpty());
1460 RetainSummary
* Summ
= getPersistentSummary(ObjCAllocRetE
);
1462 // Create the [NSAssertionHandler currentHander] summary.
1463 addClassMethSummary("NSAssertionHandler", "currentHandler",
1464 getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC
)));
1466 // Create the [NSAutoreleasePool addObject:] summary.
1467 ScratchArgs
= AF
.add(ScratchArgs
, 0, Autorelease
);
1468 addClassMethSummary("NSAutoreleasePool", "addObject",
1469 getPersistentSummary(RetEffect::MakeNoRet(),
1470 DoNothing
, Autorelease
));
1472 // Create the summaries for [NSObject performSelector...]. We treat
1473 // these as 'stop tracking' for the arguments because they are often
1474 // used for delegates that can release the object. When we have better
1475 // inter-procedural analysis we can potentially do something better. This
1476 // workaround is to remove false positives.
1477 Summ
= getPersistentSummary(RetEffect::MakeNoRet(), DoNothing
, StopTracking
);
1478 IdentifierInfo
*NSObjectII
= &Ctx
.Idents
.get("NSObject");
1479 addClsMethSummary(NSObjectII
, Summ
, "performSelector", "withObject",
1480 "afterDelay", NULL
);
1481 addClsMethSummary(NSObjectII
, Summ
, "performSelector", "withObject",
1482 "afterDelay", "inModes", NULL
);
1483 addClsMethSummary(NSObjectII
, Summ
, "performSelectorOnMainThread",
1484 "withObject", "waitUntilDone", NULL
);
1485 addClsMethSummary(NSObjectII
, Summ
, "performSelectorOnMainThread",
1486 "withObject", "waitUntilDone", "modes", NULL
);
1487 addClsMethSummary(NSObjectII
, Summ
, "performSelector", "onThread",
1488 "withObject", "waitUntilDone", NULL
);
1489 addClsMethSummary(NSObjectII
, Summ
, "performSelector", "onThread",
1490 "withObject", "waitUntilDone", "modes", NULL
);
1491 addClsMethSummary(NSObjectII
, Summ
, "performSelectorInBackground",
1492 "withObject", NULL
);
1495 void RetainSummaryManager::InitializeMethodSummaries() {
1497 assert (ScratchArgs
.isEmpty());
1499 // Create the "init" selector. It just acts as a pass-through for the
1501 RetainSummary
*InitSumm
= getPersistentSummary(ObjCInitRetE
, DecRefMsg
);
1502 addNSObjectMethSummary(GetNullarySelector("init", Ctx
), InitSumm
);
1504 // awakeAfterUsingCoder: behaves basically like an 'init' method. It
1505 // claims the receiver and returns a retained object.
1506 addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx
),
1509 // The next methods are allocators.
1510 RetainSummary
*AllocSumm
= getPersistentSummary(ObjCAllocRetE
);
1511 RetainSummary
*CFAllocSumm
=
1512 getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF
, true));
1514 // Create the "retain" selector.
1515 RetEffect E
= RetEffect::MakeReceiverAlias();
1516 RetainSummary
*Summ
= getPersistentSummary(E
, IncRefMsg
);
1517 addNSObjectMethSummary(GetNullarySelector("retain", Ctx
), Summ
);
1519 // Create the "release" selector.
1520 Summ
= getPersistentSummary(E
, DecRefMsg
);
1521 addNSObjectMethSummary(GetNullarySelector("release", Ctx
), Summ
);
1523 // Create the "drain" selector.
1524 Summ
= getPersistentSummary(E
, isGCEnabled() ? DoNothing
: DecRef
);
1525 addNSObjectMethSummary(GetNullarySelector("drain", Ctx
), Summ
);
1527 // Create the -dealloc summary.
1528 Summ
= getPersistentSummary(RetEffect::MakeNoRet(), Dealloc
);
1529 addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx
), Summ
);
1531 // Create the "autorelease" selector.
1532 Summ
= getPersistentSummary(E
, Autorelease
);
1533 addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx
), Summ
);
1535 // Specially handle NSAutoreleasePool.
1536 addInstMethSummary("NSAutoreleasePool", "init",
1537 getPersistentSummary(RetEffect::MakeReceiverAlias(),
1538 NewAutoreleasePool
));
1540 // For NSWindow, allocated objects are (initially) self-owned.
1541 // FIXME: For now we opt for false negatives with NSWindow, as these objects
1542 // self-own themselves. However, they only do this once they are displayed.
1543 // Thus, we need to track an NSWindow's display status.
1544 // This is tracked in <rdar://problem/6062711>.
1545 // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1546 RetainSummary
*NoTrackYet
= getPersistentSummary(RetEffect::MakeNoRet(),
1550 addClassMethSummary("NSWindow", "alloc", NoTrackYet
);
1553 addInstMethSummary("NSWindow", NoTrackYet
, "initWithContentRect",
1554 "styleMask", "backing", "defer", NULL
);
1556 addInstMethSummary("NSWindow", NoTrackYet
, "initWithContentRect",
1557 "styleMask", "backing", "defer", "screen", NULL
);
1560 // For NSPanel (which subclasses NSWindow), allocated objects are not
1562 // FIXME: For now we don't track NSPanels. object for the same reason
1563 // as for NSWindow objects.
1564 addClassMethSummary("NSPanel", "alloc", NoTrackYet
);
1567 addInstMethSummary("NSPanel", NoTrackYet
, "initWithContentRect",
1568 "styleMask", "backing", "defer", NULL
);
1570 addInstMethSummary("NSPanel", NoTrackYet
, "initWithContentRect",
1571 "styleMask", "backing", "defer", "screen", NULL
);
1574 // Don't track allocated autorelease pools yet, as it is okay to prematurely
1576 addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet
);
1578 // Create NSAssertionHandler summaries.
1579 addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
1580 "lineNumber", "description", NULL
);
1582 addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
1583 "file", "lineNumber", "description", NULL
);
1585 // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
1586 addInstMethSummary("QCRenderer", AllocSumm
,
1587 "createSnapshotImageOfType", NULL
);
1588 addInstMethSummary("QCView", AllocSumm
,
1589 "createSnapshotImageOfType", NULL
);
1591 // Create summaries for CIContext, 'createCGImage' and
1592 // 'createCGLayerWithSize'. These objects are CF objects, and are not
1593 // automatically garbage collected.
1594 addInstMethSummary("CIContext", CFAllocSumm
,
1595 "createCGImage", "fromRect", NULL
);
1596 addInstMethSummary("CIContext", CFAllocSumm
,
1597 "createCGImage", "fromRect", "format", "colorSpace", NULL
);
1598 addInstMethSummary("CIContext", CFAllocSumm
, "createCGLayerWithSize",
1602 //===----------------------------------------------------------------------===//
1603 // AutoreleaseBindings - State used to track objects in autorelease pools.
1604 //===----------------------------------------------------------------------===//
1606 typedef llvm::ImmutableMap
<SymbolRef
, unsigned> ARCounts
;
1607 typedef llvm::ImmutableMap
<SymbolRef
, ARCounts
> ARPoolContents
;
1608 typedef llvm::ImmutableList
<SymbolRef
> ARStack
;
1610 static int AutoRCIndex
= 0;
1611 static int AutoRBIndex
= 0;
1613 namespace { class AutoreleasePoolContents
{}; }
1614 namespace { class AutoreleaseStack
{}; }
1618 template<> struct GRStateTrait
<AutoreleaseStack
>
1619 : public GRStatePartialTrait
<ARStack
> {
1620 static inline void* GDMIndex() { return &AutoRBIndex
; }
1623 template<> struct GRStateTrait
<AutoreleasePoolContents
>
1624 : public GRStatePartialTrait
<ARPoolContents
> {
1625 static inline void* GDMIndex() { return &AutoRCIndex
; }
1627 } // end GR namespace
1628 } // end clang namespace
1630 static SymbolRef
GetCurrentAutoreleasePool(const GRState
* state
) {
1631 ARStack stack
= state
->get
<AutoreleaseStack
>();
1632 return stack
.isEmpty() ? SymbolRef() : stack
.getHead();
1635 static const GRState
* SendAutorelease(const GRState
*state
,
1636 ARCounts::Factory
&F
, SymbolRef sym
) {
1638 SymbolRef pool
= GetCurrentAutoreleasePool(state
);
1639 const ARCounts
*cnts
= state
->get
<AutoreleasePoolContents
>(pool
);
1640 ARCounts
newCnts(0);
1643 const unsigned *cnt
= (*cnts
).lookup(sym
);
1644 newCnts
= F
.add(*cnts
, sym
, cnt
? *cnt
+ 1 : 1);
1647 newCnts
= F
.add(F
.getEmptyMap(), sym
, 1);
1649 return state
->set
<AutoreleasePoolContents
>(pool
, newCnts
);
1652 //===----------------------------------------------------------------------===//
1653 // Transfer functions.
1654 //===----------------------------------------------------------------------===//
1658 class CFRefCount
: public TransferFuncs
{
1660 class BindingsPrinter
: public GRState::Printer
{
1662 virtual void Print(llvm::raw_ostream
& Out
, const GRState
* state
,
1663 const char* nl
, const char* sep
);
1667 typedef llvm::DenseMap
<const ExplodedNode
*, const RetainSummary
*>
1670 RetainSummaryManager Summaries
;
1671 SummaryLogTy SummaryLog
;
1672 const LangOptions
& LOpts
;
1673 ARCounts::Factory ARCountFactory
;
1675 BugType
*useAfterRelease
, *releaseNotOwned
;
1676 BugType
*deallocGC
, *deallocNotOwned
;
1677 BugType
*leakWithinFunction
, *leakAtReturn
;
1678 BugType
*overAutorelease
;
1679 BugType
*returnNotOwnedForOwned
;
1682 const GRState
* Update(const GRState
* state
, SymbolRef sym
, RefVal V
, ArgEffect E
,
1683 RefVal::Kind
& hasErr
);
1685 void ProcessNonLeakError(ExplodedNodeSet
& Dst
,
1686 StmtNodeBuilder
& Builder
,
1687 const Expr
* NodeExpr
, SourceRange ErrorRange
,
1690 RefVal::Kind hasErr
, SymbolRef Sym
);
1692 const GRState
* HandleSymbolDeath(const GRState
* state
, SymbolRef sid
, RefVal V
,
1693 llvm::SmallVectorImpl
<SymbolRef
> &Leaked
);
1695 ExplodedNode
* ProcessLeaks(const GRState
* state
,
1696 llvm::SmallVectorImpl
<SymbolRef
> &Leaked
,
1697 GenericNodeBuilderRefCount
&Builder
,
1699 ExplodedNode
*Pred
= 0);
1702 CFRefCount(ASTContext
& Ctx
, bool gcenabled
, const LangOptions
& lopts
)
1703 : Summaries(Ctx
, gcenabled
),
1704 LOpts(lopts
), useAfterRelease(0), releaseNotOwned(0),
1705 deallocGC(0), deallocNotOwned(0),
1706 leakWithinFunction(0), leakAtReturn(0), overAutorelease(0),
1707 returnNotOwnedForOwned(0), BR(0) {}
1709 virtual ~CFRefCount() {}
1711 void RegisterChecks(ExprEngine
&Eng
);
1713 virtual void RegisterPrinters(std::vector
<GRState::Printer
*>& Printers
) {
1714 Printers
.push_back(new BindingsPrinter());
1717 bool isGCEnabled() const { return Summaries
.isGCEnabled(); }
1718 const LangOptions
& getLangOptions() const { return LOpts
; }
1720 const RetainSummary
*getSummaryOfNode(const ExplodedNode
*N
) const {
1721 SummaryLogTy::const_iterator I
= SummaryLog
.find(N
);
1722 return I
== SummaryLog
.end() ? 0 : I
->second
;
1727 void evalSummary(ExplodedNodeSet
& Dst
,
1729 StmtNodeBuilder
& Builder
,
1731 const CallOrObjCMessage
&callOrMsg
,
1732 InstanceReceiver Receiver
,
1733 const RetainSummary
& Summ
,
1734 const MemRegion
*Callee
,
1735 ExplodedNode
* Pred
, const GRState
*state
);
1737 virtual void evalCall(ExplodedNodeSet
& Dst
,
1739 StmtNodeBuilder
& Builder
,
1740 const CallExpr
* CE
, SVal L
,
1741 ExplodedNode
* Pred
);
1744 virtual void evalObjCMessage(ExplodedNodeSet
& Dst
,
1746 StmtNodeBuilder
& Builder
,
1749 const GRState
*state
);
1751 virtual void evalBind(StmtNodeBuilderRef
& B
, SVal location
, SVal val
);
1755 virtual void evalEndPath(ExprEngine
& Engine
,
1756 EndOfFunctionNodeBuilder
& Builder
);
1758 virtual void evalDeadSymbols(ExplodedNodeSet
& Dst
,
1760 StmtNodeBuilder
& Builder
,
1762 const GRState
* state
,
1763 SymbolReaper
& SymReaper
);
1765 std::pair
<ExplodedNode
*, const GRState
*>
1766 HandleAutoreleaseCounts(const GRState
* state
, GenericNodeBuilderRefCount Bd
,
1767 ExplodedNode
* Pred
, ExprEngine
&Eng
,
1768 SymbolRef Sym
, RefVal V
, bool &stop
);
1769 // Return statements.
1771 virtual void evalReturn(ExplodedNodeSet
& Dst
,
1773 StmtNodeBuilder
& Builder
,
1774 const ReturnStmt
* S
,
1775 ExplodedNode
* Pred
);
1779 virtual const GRState
*evalAssume(const GRState
* state
, SVal condition
,
1783 } // end anonymous namespace
1785 static void PrintPool(llvm::raw_ostream
&Out
, SymbolRef Sym
,
1786 const GRState
*state
) {
1789 Out
<< Sym
->getSymbolID();
1794 // Get the contents of the pool.
1795 if (const ARCounts
*cnts
= state
->get
<AutoreleasePoolContents
>(Sym
))
1796 for (ARCounts::iterator J
=cnts
->begin(), EJ
=cnts
->end(); J
!= EJ
; ++J
)
1797 Out
<< '(' << J
.getKey() << ',' << J
.getData() << ')';
1802 void CFRefCount::BindingsPrinter::Print(llvm::raw_ostream
& Out
,
1803 const GRState
* state
,
1804 const char* nl
, const char* sep
) {
1806 RefBindings B
= state
->get
<RefBindings
>();
1811 for (RefBindings::iterator I
=B
.begin(), E
=B
.end(); I
!=E
; ++I
) {
1812 Out
<< (*I
).first
<< " : ";
1813 (*I
).second
.print(Out
);
1817 // Print the autorelease stack.
1818 Out
<< sep
<< nl
<< "AR pool stack:";
1819 ARStack stack
= state
->get
<AutoreleaseStack
>();
1821 PrintPool(Out
, SymbolRef(), state
); // Print the caller's pool.
1822 for (ARStack::iterator I
=stack
.begin(), E
=stack
.end(); I
!=E
; ++I
)
1823 PrintPool(Out
, *I
, state
);
1828 //===----------------------------------------------------------------------===//
1830 //===----------------------------------------------------------------------===//
1834 //===-------------===//
1835 // Bug Descriptions. //
1836 //===-------------===//
1838 class CFRefBug
: public BugType
{
1842 CFRefBug(CFRefCount
* tf
, llvm::StringRef name
)
1843 : BugType(name
, "Memory (Core Foundation/Objective-C)"), TF(*tf
) {}
1846 CFRefCount
& getTF() { return TF
; }
1848 // FIXME: Eventually remove.
1849 virtual const char* getDescription() const = 0;
1851 virtual bool isLeak() const { return false; }
1854 class UseAfterRelease
: public CFRefBug
{
1856 UseAfterRelease(CFRefCount
* tf
)
1857 : CFRefBug(tf
, "Use-after-release") {}
1859 const char* getDescription() const {
1860 return "Reference-counted object is used after it is released";
1864 class BadRelease
: public CFRefBug
{
1866 BadRelease(CFRefCount
* tf
) : CFRefBug(tf
, "Bad release") {}
1868 const char* getDescription() const {
1869 return "Incorrect decrement of the reference count of an object that is "
1870 "not owned at this point by the caller";
1874 class DeallocGC
: public CFRefBug
{
1876 DeallocGC(CFRefCount
*tf
)
1877 : CFRefBug(tf
, "-dealloc called while using garbage collection") {}
1879 const char *getDescription() const {
1880 return "-dealloc called while using garbage collection";
1884 class DeallocNotOwned
: public CFRefBug
{
1886 DeallocNotOwned(CFRefCount
*tf
)
1887 : CFRefBug(tf
, "-dealloc sent to non-exclusively owned object") {}
1889 const char *getDescription() const {
1890 return "-dealloc sent to object that may be referenced elsewhere";
1894 class OverAutorelease
: public CFRefBug
{
1896 OverAutorelease(CFRefCount
*tf
) :
1897 CFRefBug(tf
, "Object sent -autorelease too many times") {}
1899 const char *getDescription() const {
1900 return "Object sent -autorelease too many times";
1904 class ReturnedNotOwnedForOwned
: public CFRefBug
{
1906 ReturnedNotOwnedForOwned(CFRefCount
*tf
) :
1907 CFRefBug(tf
, "Method should return an owned object") {}
1909 const char *getDescription() const {
1910 return "Object with +0 retain counts returned to caller where a +1 "
1911 "(owning) retain count is expected";
1915 class Leak
: public CFRefBug
{
1916 const bool isReturn
;
1918 Leak(CFRefCount
* tf
, llvm::StringRef name
, bool isRet
)
1919 : CFRefBug(tf
, name
), isReturn(isRet
) {}
1922 const char* getDescription() const { return ""; }
1924 bool isLeak() const { return true; }
1927 class LeakAtReturn
: public Leak
{
1929 LeakAtReturn(CFRefCount
* tf
, llvm::StringRef name
)
1930 : Leak(tf
, name
, true) {}
1933 class LeakWithinFunction
: public Leak
{
1935 LeakWithinFunction(CFRefCount
* tf
, llvm::StringRef name
)
1936 : Leak(tf
, name
, false) {}
1943 class CFRefReport
: public RangedBugReport
{
1946 const CFRefCount
&TF
;
1948 CFRefReport(CFRefBug
& D
, const CFRefCount
&tf
,
1949 ExplodedNode
*n
, SymbolRef sym
)
1950 : RangedBugReport(D
, D
.getDescription(), n
), Sym(sym
), TF(tf
) {}
1952 CFRefReport(CFRefBug
& D
, const CFRefCount
&tf
,
1953 ExplodedNode
*n
, SymbolRef sym
, llvm::StringRef endText
)
1954 : RangedBugReport(D
, D
.getDescription(), endText
, n
), Sym(sym
), TF(tf
) {}
1956 virtual ~CFRefReport() {}
1958 CFRefBug
& getBugType() const {
1959 return (CFRefBug
&) RangedBugReport::getBugType();
1962 virtual std::pair
<ranges_iterator
, ranges_iterator
> getRanges() const {
1963 if (!getBugType().isLeak())
1964 return RangedBugReport::getRanges();
1966 return std::make_pair(ranges_iterator(), ranges_iterator());
1969 SymbolRef
getSymbol() const { return Sym
; }
1971 PathDiagnosticPiece
* getEndPath(BugReporterContext
& BRC
,
1972 const ExplodedNode
* N
);
1974 std::pair
<const char**,const char**> getExtraDescriptiveText();
1976 PathDiagnosticPiece
* VisitNode(const ExplodedNode
* N
,
1977 const ExplodedNode
* PrevN
,
1978 BugReporterContext
& BRC
);
1981 class CFRefLeakReport
: public CFRefReport
{
1982 SourceLocation AllocSite
;
1983 const MemRegion
* AllocBinding
;
1985 CFRefLeakReport(CFRefBug
& D
, const CFRefCount
&tf
,
1986 ExplodedNode
*n
, SymbolRef sym
,
1989 PathDiagnosticPiece
* getEndPath(BugReporterContext
& BRC
,
1990 const ExplodedNode
* N
);
1992 SourceLocation
getLocation() const { return AllocSite
; }
1994 } // end anonymous namespace
1998 static const char* Msgs
[] = {
2000 "Code is compiled to only use garbage collection",
2002 "Code is compiled to use reference counts",
2004 "Code is compiled to use either garbage collection (GC) or reference counts"
2005 " (non-GC). The bug occurs with GC enabled",
2006 // Hybrid, without GC
2007 "Code is compiled to use either garbage collection (GC) or reference counts"
2008 " (non-GC). The bug occurs in non-GC mode"
2011 std::pair
<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
2012 CFRefCount
& TF
= static_cast<CFRefBug
&>(getBugType()).getTF();
2014 switch (TF
.getLangOptions().getGCMode()) {
2018 case LangOptions::GCOnly
:
2019 assert (TF
.isGCEnabled());
2020 return std::make_pair(&Msgs
[0], &Msgs
[0]+1);
2022 case LangOptions::NonGC
:
2023 assert (!TF
.isGCEnabled());
2024 return std::make_pair(&Msgs
[1], &Msgs
[1]+1);
2026 case LangOptions::HybridGC
:
2027 if (TF
.isGCEnabled())
2028 return std::make_pair(&Msgs
[2], &Msgs
[2]+1);
2030 return std::make_pair(&Msgs
[3], &Msgs
[3]+1);
2034 static inline bool contains(const llvm::SmallVectorImpl
<ArgEffect
>& V
,
2036 for (llvm::SmallVectorImpl
<ArgEffect
>::const_iterator I
=V
.begin(), E
=V
.end();
2038 if (*I
== X
) return true;
2043 PathDiagnosticPiece
* CFRefReport::VisitNode(const ExplodedNode
* N
,
2044 const ExplodedNode
* PrevN
,
2045 BugReporterContext
& BRC
) {
2047 if (!isa
<PostStmt
>(N
->getLocation()))
2050 // Check if the type state has changed.
2051 const GRState
*PrevSt
= PrevN
->getState();
2052 const GRState
*CurrSt
= N
->getState();
2054 const RefVal
* CurrT
= CurrSt
->get
<RefBindings
>(Sym
);
2055 if (!CurrT
) return NULL
;
2057 const RefVal
&CurrV
= *CurrT
;
2058 const RefVal
*PrevT
= PrevSt
->get
<RefBindings
>(Sym
);
2060 // Create a string buffer to constain all the useful things we want
2061 // to tell the user.
2063 llvm::raw_string_ostream
os(sbuf
);
2065 // This is the allocation site since the previous node had no bindings
2068 const Stmt
* S
= cast
<PostStmt
>(N
->getLocation()).getStmt();
2070 if (const CallExpr
*CE
= dyn_cast
<CallExpr
>(S
)) {
2071 // Get the name of the callee (if it is available).
2072 SVal X
= CurrSt
->getSValAsScalarOrLoc(CE
->getCallee());
2073 if (const FunctionDecl
* FD
= X
.getAsFunctionDecl())
2074 os
<< "Call to function '" << FD
<< '\'';
2076 os
<< "function call";
2078 else if (isa
<ObjCMessageExpr
>(S
)) {
2084 if (CurrV
.getObjKind() == RetEffect::CF
) {
2085 os
<< " returns a Core Foundation object with a ";
2088 assert (CurrV
.getObjKind() == RetEffect::ObjC
);
2089 os
<< " returns an Objective-C object with a ";
2092 if (CurrV
.isOwned()) {
2093 os
<< "+1 retain count (owning reference).";
2095 if (static_cast<CFRefBug
&>(getBugType()).getTF().isGCEnabled()) {
2096 assert(CurrV
.getObjKind() == RetEffect::CF
);
2098 "Core Foundation objects are not automatically garbage collected.";
2102 assert (CurrV
.isNotOwned());
2103 os
<< "+0 retain count (non-owning reference).";
2106 PathDiagnosticLocation
Pos(S
, BRC
.getSourceManager());
2107 return new PathDiagnosticEventPiece(Pos
, os
.str());
2110 // Gather up the effects that were performed on the object at this
2112 llvm::SmallVector
<ArgEffect
, 2> AEffects
;
2114 if (const RetainSummary
*Summ
=
2115 TF
.getSummaryOfNode(BRC
.getNodeResolver().getOriginalNode(N
))) {
2116 // We only have summaries attached to nodes after evaluating CallExpr and
2117 // ObjCMessageExprs.
2118 const Stmt
* S
= cast
<PostStmt
>(N
->getLocation()).getStmt();
2120 if (const CallExpr
*CE
= dyn_cast
<CallExpr
>(S
)) {
2121 // Iterate through the parameter expressions and see if the symbol
2122 // was ever passed as an argument.
2125 for (CallExpr::const_arg_iterator AI
=CE
->arg_begin(), AE
=CE
->arg_end();
2126 AI
!=AE
; ++AI
, ++i
) {
2128 // Retrieve the value of the argument. Is it the symbol
2129 // we are interested in?
2130 if (CurrSt
->getSValAsScalarOrLoc(*AI
).getAsLocSymbol() != Sym
)
2133 // We have an argument. Get the effect!
2134 AEffects
.push_back(Summ
->getArg(i
));
2137 else if (const ObjCMessageExpr
*ME
= dyn_cast
<ObjCMessageExpr
>(S
)) {
2138 if (const Expr
*receiver
= ME
->getInstanceReceiver())
2139 if (CurrSt
->getSValAsScalarOrLoc(receiver
).getAsLocSymbol() == Sym
) {
2140 // The symbol we are tracking is the receiver.
2141 AEffects
.push_back(Summ
->getReceiverEffect());
2147 // Get the previous type state.
2148 RefVal PrevV
= *PrevT
;
2150 // Specially handle -dealloc.
2151 if (!TF
.isGCEnabled() && contains(AEffects
, Dealloc
)) {
2152 // Determine if the object's reference count was pushed to zero.
2153 assert(!(PrevV
== CurrV
) && "The typestate *must* have changed.");
2154 // We may not have transitioned to 'release' if we hit an error.
2155 // This case is handled elsewhere.
2156 if (CurrV
.getKind() == RefVal::Released
) {
2157 assert(CurrV
.getCombinedCounts() == 0);
2158 os
<< "Object released by directly sending the '-dealloc' message";
2163 // Specially handle CFMakeCollectable and friends.
2164 if (contains(AEffects
, MakeCollectable
)) {
2165 // Get the name of the function.
2166 const Stmt
* S
= cast
<PostStmt
>(N
->getLocation()).getStmt();
2167 SVal X
= CurrSt
->getSValAsScalarOrLoc(cast
<CallExpr
>(S
)->getCallee());
2168 const FunctionDecl
* FD
= X
.getAsFunctionDecl();
2169 const std::string
& FName
= FD
->getNameAsString();
2171 if (TF
.isGCEnabled()) {
2172 // Determine if the object's reference count was pushed to zero.
2173 assert(!(PrevV
== CurrV
) && "The typestate *must* have changed.");
2175 os
<< "In GC mode a call to '" << FName
2176 << "' decrements an object's retain count and registers the "
2177 "object with the garbage collector. ";
2179 if (CurrV
.getKind() == RefVal::Released
) {
2180 assert(CurrV
.getCount() == 0);
2181 os
<< "Since it now has a 0 retain count the object can be "
2182 "automatically collected by the garbage collector.";
2185 os
<< "An object must have a 0 retain count to be garbage collected. "
2186 "After this call its retain count is +" << CurrV
.getCount()
2190 os
<< "When GC is not enabled a call to '" << FName
2191 << "' has no effect on its argument.";
2193 // Nothing more to say.
2197 // Determine if the typestate has changed.
2198 if (!(PrevV
== CurrV
))
2199 switch (CurrV
.getKind()) {
2201 case RefVal::NotOwned
:
2203 if (PrevV
.getCount() == CurrV
.getCount()) {
2204 // Did an autorelease message get sent?
2205 if (PrevV
.getAutoreleaseCount() == CurrV
.getAutoreleaseCount())
2208 assert(PrevV
.getAutoreleaseCount() < CurrV
.getAutoreleaseCount());
2209 os
<< "Object sent -autorelease message";
2213 if (PrevV
.getCount() > CurrV
.getCount())
2214 os
<< "Reference count decremented.";
2216 os
<< "Reference count incremented.";
2218 if (unsigned Count
= CurrV
.getCount())
2219 os
<< " The object now has a +" << Count
<< " retain count.";
2221 if (PrevV
.getKind() == RefVal::Released
) {
2222 assert(TF
.isGCEnabled() && CurrV
.getCount() > 0);
2223 os
<< " The object is not eligible for garbage collection until the "
2224 "retain count reaches 0 again.";
2229 case RefVal::Released
:
2230 os
<< "Object released.";
2233 case RefVal::ReturnedOwned
:
2234 os
<< "Object returned to caller as an owning reference (single retain "
2235 "count transferred to caller).";
2238 case RefVal::ReturnedNotOwned
:
2239 os
<< "Object returned to caller with a +0 (non-owning) retain count.";
2246 // Emit any remaining diagnostics for the argument effects (if any).
2247 for (llvm::SmallVectorImpl
<ArgEffect
>::iterator I
=AEffects
.begin(),
2248 E
=AEffects
.end(); I
!= E
; ++I
) {
2250 // A bunch of things have alternate behavior under GC.
2251 if (TF
.isGCEnabled())
2255 os
<< "In GC mode an 'autorelease' has no effect.";
2258 os
<< "In GC mode the 'retain' message has no effect.";
2261 os
<< "In GC mode the 'release' message has no effect.";
2267 if (os
.str().empty())
2268 return 0; // We have nothing to say!
2270 const Stmt
* S
= cast
<PostStmt
>(N
->getLocation()).getStmt();
2271 PathDiagnosticLocation
Pos(S
, BRC
.getSourceManager());
2272 PathDiagnosticPiece
* P
= new PathDiagnosticEventPiece(Pos
, os
.str());
2274 // Add the range by scanning the children of the statement for any bindings
2276 for (Stmt::const_child_iterator I
= S
->child_begin(), E
= S
->child_end();
2278 if (const Expr
* Exp
= dyn_cast_or_null
<Expr
>(*I
))
2279 if (CurrSt
->getSValAsScalarOrLoc(Exp
).getAsLocSymbol() == Sym
) {
2280 P
->addRange(Exp
->getSourceRange());
2288 class FindUniqueBinding
:
2289 public StoreManager::BindingsHandler
{
2291 const MemRegion
* Binding
;
2295 FindUniqueBinding(SymbolRef sym
) : Sym(sym
), Binding(0), First(true) {}
2297 bool HandleBinding(StoreManager
& SMgr
, Store store
, const MemRegion
* R
,
2300 SymbolRef SymV
= val
.getAsSymbol();
2301 if (!SymV
|| SymV
!= Sym
)
2314 operator bool() { return First
&& Binding
; }
2315 const MemRegion
* getRegion() { return Binding
; }
2319 static std::pair
<const ExplodedNode
*,const MemRegion
*>
2320 GetAllocationSite(GRStateManager
& StateMgr
, const ExplodedNode
* N
,
2323 // Find both first node that referred to the tracked symbol and the
2324 // memory location that value was store to.
2325 const ExplodedNode
* Last
= N
;
2326 const MemRegion
* FirstBinding
= 0;
2329 const GRState
* St
= N
->getState();
2330 RefBindings B
= St
->get
<RefBindings
>();
2335 FindUniqueBinding
FB(Sym
);
2336 StateMgr
.iterBindings(St
, FB
);
2337 if (FB
) FirstBinding
= FB
.getRegion();
2340 N
= N
->pred_empty() ? NULL
: *(N
->pred_begin());
2343 return std::make_pair(Last
, FirstBinding
);
2346 PathDiagnosticPiece
*
2347 CFRefReport::getEndPath(BugReporterContext
& BRC
,
2348 const ExplodedNode
* EndN
) {
2349 // Tell the BugReporterContext to report cases when the tracked symbol is
2350 // assigned to different variables, etc.
2351 BRC
.addNotableSymbol(Sym
);
2352 return RangedBugReport::getEndPath(BRC
, EndN
);
2355 PathDiagnosticPiece
*
2356 CFRefLeakReport::getEndPath(BugReporterContext
& BRC
,
2357 const ExplodedNode
* EndN
){
2359 // Tell the BugReporterContext to report cases when the tracked symbol is
2360 // assigned to different variables, etc.
2361 BRC
.addNotableSymbol(Sym
);
2363 // We are reporting a leak. Walk up the graph to get to the first node where
2364 // the symbol appeared, and also get the first VarDecl that tracked object
2366 const ExplodedNode
* AllocNode
= 0;
2367 const MemRegion
* FirstBinding
= 0;
2369 llvm::tie(AllocNode
, FirstBinding
) =
2370 GetAllocationSite(BRC
.getStateManager(), EndN
, Sym
);
2372 // Get the allocate site.
2374 const Stmt
* FirstStmt
= cast
<PostStmt
>(AllocNode
->getLocation()).getStmt();
2376 SourceManager
& SMgr
= BRC
.getSourceManager();
2377 unsigned AllocLine
=SMgr
.getInstantiationLineNumber(FirstStmt
->getLocStart());
2379 // Compute an actual location for the leak. Sometimes a leak doesn't
2380 // occur at an actual statement (e.g., transition between blocks; end
2381 // of function) so we need to walk the graph and compute a real location.
2382 const ExplodedNode
* LeakN
= EndN
;
2383 PathDiagnosticLocation L
;
2386 ProgramPoint P
= LeakN
->getLocation();
2388 if (const PostStmt
*PS
= dyn_cast
<PostStmt
>(&P
)) {
2389 L
= PathDiagnosticLocation(PS
->getStmt()->getLocStart(), SMgr
);
2392 else if (const BlockEdge
*BE
= dyn_cast
<BlockEdge
>(&P
)) {
2393 if (const Stmt
* Term
= BE
->getSrc()->getTerminator()) {
2394 L
= PathDiagnosticLocation(Term
->getLocStart(), SMgr
);
2399 LeakN
= LeakN
->succ_empty() ? 0 : *(LeakN
->succ_begin());
2403 const Decl
&D
= EndN
->getCodeDecl();
2404 L
= PathDiagnosticLocation(D
.getBodyRBrace(), SMgr
);
2408 llvm::raw_string_ostream
os(sbuf
);
2410 os
<< "Object allocated on line " << AllocLine
;
2413 os
<< " and stored into '" << FirstBinding
->getString() << '\'';
2415 // Get the retain count.
2416 const RefVal
* RV
= EndN
->getState()->get
<RefBindings
>(Sym
);
2418 if (RV
->getKind() == RefVal::ErrorLeakReturned
) {
2419 // FIXME: Per comments in rdar://6320065, "create" only applies to CF
2420 // ojbects. Only "copy", "alloc", "retain" and "new" transfer ownership
2421 // to the caller for NS objects.
2422 ObjCMethodDecl
& MD
= cast
<ObjCMethodDecl
>(EndN
->getCodeDecl());
2423 os
<< " is returned from a method whose name ('"
2424 << MD
.getSelector().getAsString()
2425 << "') does not contain 'copy' or otherwise starts with"
2426 " 'new' or 'alloc'. This violates the naming convention rules given"
2427 " in the Memory Management Guide for Cocoa (object leaked)";
2429 else if (RV
->getKind() == RefVal::ErrorGCLeakReturned
) {
2430 ObjCMethodDecl
& MD
= cast
<ObjCMethodDecl
>(EndN
->getCodeDecl());
2431 os
<< " and returned from method '" << MD
.getSelector().getAsString()
2432 << "' is potentially leaked when using garbage collection. Callers "
2433 "of this method do not expect a returned object with a +1 retain "
2434 "count since they expect the object to be managed by the garbage "
2438 os
<< " is not referenced later in this execution path and has a retain "
2439 "count of +" << RV
->getCount() << " (object leaked)";
2441 return new PathDiagnosticEventPiece(L
, os
.str());
2444 CFRefLeakReport::CFRefLeakReport(CFRefBug
& D
, const CFRefCount
&tf
,
2446 SymbolRef sym
, ExprEngine
& Eng
)
2447 : CFRefReport(D
, tf
, n
, sym
) {
2449 // Most bug reports are cached at the location where they occured.
2450 // With leaks, we want to unique them by the location where they were
2451 // allocated, and only report a single path. To do this, we need to find
2452 // the allocation site of a piece of tracked memory, which we do via a
2453 // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
2454 // Note that this is *not* the trimmed graph; we are guaranteed, however,
2455 // that all ancestor nodes that represent the allocation site have the
2456 // same SourceLocation.
2457 const ExplodedNode
* AllocNode
= 0;
2459 llvm::tie(AllocNode
, AllocBinding
) = // Set AllocBinding.
2460 GetAllocationSite(Eng
.getStateManager(), getErrorNode(), getSymbol());
2462 // Get the SourceLocation for the allocation site.
2463 ProgramPoint P
= AllocNode
->getLocation();
2464 AllocSite
= cast
<PostStmt
>(P
).getStmt()->getLocStart();
2466 // Fill in the description of the bug.
2467 Description
.clear();
2468 llvm::raw_string_ostream
os(Description
);
2469 SourceManager
& SMgr
= Eng
.getContext().getSourceManager();
2470 unsigned AllocLine
= SMgr
.getInstantiationLineNumber(AllocSite
);
2471 os
<< "Potential leak ";
2472 if (tf
.isGCEnabled()) {
2473 os
<< "(when using garbage collection) ";
2475 os
<< "of an object allocated on line " << AllocLine
;
2477 // FIXME: AllocBinding doesn't get populated for RegionStore yet.
2479 os
<< " and stored into '" << AllocBinding
->getString() << '\'';
2482 //===----------------------------------------------------------------------===//
2483 // Main checker logic.
2484 //===----------------------------------------------------------------------===//
2486 /// GetReturnType - Used to get the return type of a message expression or
2487 /// function call with the intention of affixing that type to a tracked symbol.
2488 /// While the the return type can be queried directly from RetEx, when
2489 /// invoking class methods we augment to the return type to be that of
2490 /// a pointer to the class (as opposed it just being id).
2491 static QualType
GetReturnType(const Expr
* RetE
, ASTContext
& Ctx
) {
2492 QualType RetTy
= RetE
->getType();
2493 // If RetE is not a message expression just return its type.
2494 // If RetE is a message expression, return its types if it is something
2495 /// more specific than id.
2496 if (const ObjCMessageExpr
*ME
= dyn_cast
<ObjCMessageExpr
>(RetE
))
2497 if (const ObjCObjectPointerType
*PT
= RetTy
->getAs
<ObjCObjectPointerType
>())
2498 if (PT
->isObjCQualifiedIdType() || PT
->isObjCIdType() ||
2499 PT
->isObjCClassType()) {
2500 // At this point we know the return type of the message expression is
2501 // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
2502 // is a call to a class method whose type we can resolve. In such
2503 // cases, promote the return type to XXX* (where XXX is the class).
2504 const ObjCInterfaceDecl
*D
= ME
->getReceiverInterface();
2506 Ctx
.getObjCObjectPointerType(Ctx
.getObjCInterfaceType(D
));
2512 void CFRefCount::evalSummary(ExplodedNodeSet
& Dst
,
2514 StmtNodeBuilder
& Builder
,
2516 const CallOrObjCMessage
&callOrMsg
,
2517 InstanceReceiver Receiver
,
2518 const RetainSummary
& Summ
,
2519 const MemRegion
*Callee
,
2520 ExplodedNode
* Pred
, const GRState
*state
) {
2522 // Evaluate the effect of the arguments.
2523 RefVal::Kind hasErr
= (RefVal::Kind
) 0;
2524 SourceRange ErrorRange
;
2525 SymbolRef ErrorSym
= 0;
2527 llvm::SmallVector
<const MemRegion
*, 10> RegionsToInvalidate
;
2529 // HACK: Symbols that have ref-count state that are referenced directly
2530 // (not as structure or array elements, or via bindings) by an argument
2531 // should not have their ref-count state stripped after we have
2532 // done an invalidation pass.
2533 llvm::DenseSet
<SymbolRef
> WhitelistedSymbols
;
2535 for (unsigned idx
= 0, e
= callOrMsg
.getNumArgs(); idx
!= e
; ++idx
) {
2536 SVal V
= callOrMsg
.getArgSValAsScalarOrLoc(idx
);
2537 SymbolRef Sym
= V
.getAsLocSymbol();
2540 if (RefBindings::data_type
* T
= state
->get
<RefBindings
>(Sym
)) {
2541 WhitelistedSymbols
.insert(Sym
);
2542 state
= Update(state
, Sym
, *T
, Summ
.getArg(idx
), hasErr
);
2544 ErrorRange
= callOrMsg
.getArgSourceRange(idx
);
2552 if (loc::MemRegionVal
* MR
= dyn_cast
<loc::MemRegionVal
>(&V
)) {
2553 if (Summ
.getArg(idx
) == DoNothingByRef
)
2556 // Invalidate the value of the variable passed by reference.
2557 const MemRegion
*R
= MR
->getRegion();
2559 // Are we dealing with an ElementRegion? If the element type is
2560 // a basic integer type (e.g., char, int) and the underying region
2561 // is a variable region then strip off the ElementRegion.
2562 // FIXME: We really need to think about this for the general case
2563 // as sometimes we are reasoning about arrays and other times
2564 // about (char*), etc., is just a form of passing raw bytes.
2565 // e.g., void *p = alloca(); foo((char*)p);
2566 if (const ElementRegion
*ER
= dyn_cast
<ElementRegion
>(R
)) {
2567 // Checking for 'integral type' is probably too promiscuous, but
2568 // we'll leave it in for now until we have a systematic way of
2569 // handling all of these cases. Eventually we need to come up
2570 // with an interface to StoreManager so that this logic can be
2571 // approriately delegated to the respective StoreManagers while
2572 // still allowing us to do checker-specific logic (e.g.,
2573 // invalidating reference counts), probably via callbacks.
2574 if (ER
->getElementType()->isIntegralOrEnumerationType()) {
2575 const MemRegion
*superReg
= ER
->getSuperRegion();
2576 if (isa
<VarRegion
>(superReg
) || isa
<FieldRegion
>(superReg
) ||
2577 isa
<ObjCIvarRegion
>(superReg
))
2578 R
= cast
<TypedRegion
>(superReg
);
2580 // FIXME: What about layers of ElementRegions?
2583 // Mark this region for invalidation. We batch invalidate regions
2584 // below for efficiency.
2585 RegionsToInvalidate
.push_back(R
);
2589 // Nuke all other arguments passed by reference.
2590 // FIXME: is this necessary or correct? This handles the non-Region
2591 // cases. Is it ever valid to store to these?
2592 state
= state
->unbindLoc(cast
<Loc
>(V
));
2595 else if (isa
<nonloc::LocAsInteger
>(V
)) {
2596 // If we are passing a location wrapped as an integer, unwrap it and
2597 // invalidate the values referred by the location.
2598 V
= cast
<nonloc::LocAsInteger
>(V
).getLoc();
2603 // Block calls result in all captured values passed-via-reference to be
2605 if (const BlockDataRegion
*BR
= dyn_cast_or_null
<BlockDataRegion
>(Callee
)) {
2606 RegionsToInvalidate
.push_back(BR
);
2609 // Invalidate regions we designed for invalidation use the batch invalidation
2612 // FIXME: We can have collisions on the conjured symbol if the
2613 // expression *I also creates conjured symbols. We probably want
2614 // to identify conjured symbols by an expression pair: the enclosing
2615 // expression (the context) and the expression itself. This should
2616 // disambiguate conjured symbols.
2617 unsigned Count
= Builder
.getCurrentBlockCount();
2618 StoreManager::InvalidatedSymbols IS
;
2620 // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
2621 // global variables.
2622 state
= state
->InvalidateRegions(RegionsToInvalidate
.data(),
2623 RegionsToInvalidate
.data() +
2624 RegionsToInvalidate
.size(),
2626 /* invalidateGlobals = */ true);
2628 for (StoreManager::InvalidatedSymbols::iterator I
= IS
.begin(),
2629 E
= IS
.end(); I
!=E
; ++I
) {
2631 if (WhitelistedSymbols
.count(sym
))
2633 // Remove any existing reference-count binding.
2634 state
= state
->remove
<RefBindings
>(*I
);
2637 // Evaluate the effect on the message receiver.
2638 if (!ErrorRange
.isValid() && Receiver
) {
2639 SymbolRef Sym
= Receiver
.getSValAsScalarOrLoc(state
).getAsLocSymbol();
2641 if (const RefVal
* T
= state
->get
<RefBindings
>(Sym
)) {
2642 state
= Update(state
, Sym
, *T
, Summ
.getReceiverEffect(), hasErr
);
2644 ErrorRange
= Receiver
.getSourceRange();
2651 // Process any errors.
2653 ProcessNonLeakError(Dst
, Builder
, Ex
, ErrorRange
, Pred
, state
,
2658 // Consult the summary for the return value.
2659 RetEffect RE
= Summ
.getRetEffect();
2661 if (RE
.getKind() == RetEffect::OwnedWhenTrackedReceiver
) {
2664 SVal V
= Receiver
.getSValAsScalarOrLoc(state
);
2665 if (SymbolRef Sym
= V
.getAsLocSymbol())
2666 if (state
->get
<RefBindings
>(Sym
)) {
2668 RE
= Summaries
.getObjAllocRetEffect();
2670 } // FIXME: Otherwise, this is a send-to-super instance message.
2672 RE
= RetEffect::MakeNoRet();
2675 switch (RE
.getKind()) {
2677 assert (false && "Unhandled RetEffect."); break;
2679 case RetEffect::NoRet
: {
2680 // Make up a symbol for the return value (not reference counted).
2681 // FIXME: Most of this logic is not specific to the retain/release
2684 // FIXME: We eventually should handle structs and other compound types
2685 // that are returned by value.
2687 QualType T
= callOrMsg
.getResultType(Eng
.getContext());
2688 if (Loc::IsLocType(T
) || (T
->isIntegerType() && T
->isScalarType())) {
2689 unsigned Count
= Builder
.getCurrentBlockCount();
2690 SValBuilder
&svalBuilder
= Eng
.getSValBuilder();
2691 SVal X
= svalBuilder
.getConjuredSymbolVal(NULL
, Ex
, T
, Count
);
2692 state
= state
->BindExpr(Ex
, X
, false);
2698 case RetEffect::Alias
: {
2699 unsigned idx
= RE
.getIndex();
2700 assert (idx
< callOrMsg
.getNumArgs());
2701 SVal V
= callOrMsg
.getArgSValAsScalarOrLoc(idx
);
2702 state
= state
->BindExpr(Ex
, V
, false);
2706 case RetEffect::ReceiverAlias
: {
2708 SVal V
= Receiver
.getSValAsScalarOrLoc(state
);
2709 state
= state
->BindExpr(Ex
, V
, false);
2713 case RetEffect::OwnedAllocatedSymbol
:
2714 case RetEffect::OwnedSymbol
: {
2715 unsigned Count
= Builder
.getCurrentBlockCount();
2716 SValBuilder
&svalBuilder
= Eng
.getSValBuilder();
2717 SymbolRef Sym
= svalBuilder
.getConjuredSymbol(Ex
, Count
);
2718 QualType RetT
= GetReturnType(Ex
, svalBuilder
.getContext());
2719 state
= state
->set
<RefBindings
>(Sym
, RefVal::makeOwned(RE
.getObjKind(),
2721 state
= state
->BindExpr(Ex
, svalBuilder
.makeLoc(Sym
), false);
2723 // FIXME: Add a flag to the checker where allocations are assumed to
2726 if (RE
.getKind() == RetEffect::OwnedAllocatedSymbol
) {
2728 state
= state
.assume(loc::SymbolVal(Sym
), true, isFeasible
);
2729 assert(isFeasible
&& "Cannot assume fresh symbol is non-null.");
2736 case RetEffect::GCNotOwnedSymbol
:
2737 case RetEffect::NotOwnedSymbol
: {
2738 unsigned Count
= Builder
.getCurrentBlockCount();
2739 SValBuilder
&svalBuilder
= Eng
.getSValBuilder();
2740 SymbolRef Sym
= svalBuilder
.getConjuredSymbol(Ex
, Count
);
2741 QualType RetT
= GetReturnType(Ex
, svalBuilder
.getContext());
2742 state
= state
->set
<RefBindings
>(Sym
, RefVal::makeNotOwned(RE
.getObjKind(),
2744 state
= state
->BindExpr(Ex
, svalBuilder
.makeLoc(Sym
), false);
2749 // Generate a sink node if we are at the end of a path.
2750 ExplodedNode
*NewNode
=
2751 Summ
.isEndPath() ? Builder
.MakeSinkNode(Dst
, Ex
, Pred
, state
)
2752 : Builder
.MakeNode(Dst
, Ex
, Pred
, state
);
2754 // Annotate the edge with summary we used.
2755 if (NewNode
) SummaryLog
[NewNode
] = &Summ
;
2759 void CFRefCount::evalCall(ExplodedNodeSet
& Dst
,
2761 StmtNodeBuilder
& Builder
,
2762 const CallExpr
* CE
, SVal L
,
2763 ExplodedNode
* Pred
) {
2765 RetainSummary
*Summ
= 0;
2767 // FIXME: Better support for blocks. For now we stop tracking anything
2768 // that is passed to blocks.
2769 // FIXME: Need to handle variables that are "captured" by the block.
2770 if (dyn_cast_or_null
<BlockDataRegion
>(L
.getAsRegion())) {
2771 Summ
= Summaries
.getPersistentStopSummary();
2774 const FunctionDecl
* FD
= L
.getAsFunctionDecl();
2775 Summ
= !FD
? Summaries
.getDefaultSummary() :
2776 Summaries
.getSummary(FD
);
2780 evalSummary(Dst
, Eng
, Builder
, CE
,
2781 CallOrObjCMessage(CE
, Builder
.GetState(Pred
)),
2782 InstanceReceiver(), *Summ
,L
.getAsRegion(),
2783 Pred
, Builder
.GetState(Pred
));
2786 void CFRefCount::evalObjCMessage(ExplodedNodeSet
& Dst
,
2788 StmtNodeBuilder
& Builder
,
2791 const GRState
*state
) {
2792 RetainSummary
*Summ
=
2793 msg
.isInstanceMessage()
2794 ? Summaries
.getInstanceMethodSummary(msg
, state
,Pred
->getLocationContext())
2795 : Summaries
.getClassMethodSummary(msg
);
2797 assert(Summ
&& "RetainSummary is null");
2798 evalSummary(Dst
, Eng
, Builder
, msg
.getOriginExpr(),
2799 CallOrObjCMessage(msg
, Builder
.GetState(Pred
)),
2800 InstanceReceiver(msg
, Pred
->getLocationContext()), *Summ
, NULL
,
2805 class StopTrackingCallback
: public SymbolVisitor
{
2806 const GRState
*state
;
2808 StopTrackingCallback(const GRState
*st
) : state(st
) {}
2809 const GRState
*getState() const { return state
; }
2811 bool VisitSymbol(SymbolRef sym
) {
2812 state
= state
->remove
<RefBindings
>(sym
);
2816 } // end anonymous namespace
2819 void CFRefCount::evalBind(StmtNodeBuilderRef
& B
, SVal location
, SVal val
) {
2820 // Are we storing to something that causes the value to "escape"?
2821 bool escapes
= false;
2823 // A value escapes in three possible cases (this may change):
2825 // (1) we are binding to something that is not a memory region.
2826 // (2) we are binding to a memregion that does not have stack storage
2827 // (3) we are binding to a memregion with stack storage that the store
2828 // does not understand.
2829 const GRState
*state
= B
.getState();
2831 if (!isa
<loc::MemRegionVal
>(location
))
2834 const MemRegion
* R
= cast
<loc::MemRegionVal
>(location
).getRegion();
2835 escapes
= !R
->hasStackStorage();
2838 // To test (3), generate a new state with the binding removed. If it is
2839 // the same state, then it escapes (since the store cannot represent
2841 escapes
= (state
== (state
->bindLoc(cast
<Loc
>(location
), UnknownVal())));
2845 // If our store can represent the binding and we aren't storing to something
2846 // that doesn't have local storage then just return and have the simulation
2847 // state continue as is.
2851 // Otherwise, find all symbols referenced by 'val' that we are tracking
2852 // and stop tracking them.
2853 B
.MakeNode(state
->scanReachableSymbols
<StopTrackingCallback
>(val
).getState());
2856 // Return statements.
2858 void CFRefCount::evalReturn(ExplodedNodeSet
& Dst
,
2860 StmtNodeBuilder
& Builder
,
2861 const ReturnStmt
* S
,
2862 ExplodedNode
* Pred
) {
2864 const Expr
* RetE
= S
->getRetValue();
2868 const GRState
*state
= Builder
.GetState(Pred
);
2869 SymbolRef Sym
= state
->getSValAsScalarOrLoc(RetE
).getAsLocSymbol();
2874 // Get the reference count binding (if any).
2875 const RefVal
* T
= state
->get
<RefBindings
>(Sym
);
2880 // Change the reference count.
2883 switch (X
.getKind()) {
2884 case RefVal::Owned
: {
2885 unsigned cnt
= X
.getCount();
2887 X
.setCount(cnt
- 1);
2888 X
= X
^ RefVal::ReturnedOwned
;
2892 case RefVal::NotOwned
: {
2893 unsigned cnt
= X
.getCount();
2895 X
.setCount(cnt
- 1);
2896 X
= X
^ RefVal::ReturnedOwned
;
2899 X
= X
^ RefVal::ReturnedNotOwned
;
2908 // Update the binding.
2909 state
= state
->set
<RefBindings
>(Sym
, X
);
2910 Pred
= Builder
.MakeNode(Dst
, S
, Pred
, state
);
2912 // Did we cache out?
2916 // Update the autorelease counts.
2917 static unsigned autoreleasetag
= 0;
2918 GenericNodeBuilderRefCount
Bd(Builder
, S
, &autoreleasetag
);
2920 llvm::tie(Pred
, state
) = HandleAutoreleaseCounts(state
, Bd
, Pred
, Eng
, Sym
,
2923 // Did we cache out?
2927 // Get the updated binding.
2928 T
= state
->get
<RefBindings
>(Sym
);
2932 // Any leaks or other errors?
2933 if (X
.isReturnedOwned() && X
.getCount() == 0) {
2934 Decl
const *CD
= &Pred
->getCodeDecl();
2935 if (const ObjCMethodDecl
* MD
= dyn_cast
<ObjCMethodDecl
>(CD
)) {
2936 const RetainSummary
&Summ
= *Summaries
.getMethodSummary(MD
);
2937 RetEffect RE
= Summ
.getRetEffect();
2938 bool hasError
= false;
2940 if (RE
.getKind() != RetEffect::NoRet
) {
2941 if (isGCEnabled() && RE
.getObjKind() == RetEffect::ObjC
) {
2942 // Things are more complicated with garbage collection. If the
2943 // returned object is suppose to be an Objective-C object, we have
2944 // a leak (as the caller expects a GC'ed object) because no
2945 // method should return ownership unless it returns a CF object.
2947 X
= X
^ RefVal::ErrorGCLeakReturned
;
2949 else if (!RE
.isOwned()) {
2950 // Either we are using GC and the returned object is a CF type
2951 // or we aren't using GC. In either case, we expect that the
2952 // enclosing method is expected to return ownership.
2954 X
= X
^ RefVal::ErrorLeakReturned
;
2959 // Generate an error node.
2960 static int ReturnOwnLeakTag
= 0;
2961 state
= state
->set
<RefBindings
>(Sym
, X
);
2963 Builder
.generateNode(PostStmt(S
, Pred
->getLocationContext(),
2964 &ReturnOwnLeakTag
), state
, Pred
);
2966 CFRefReport
*report
=
2967 new CFRefLeakReport(*static_cast<CFRefBug
*>(leakAtReturn
), *this,
2969 BR
->EmitReport(report
);
2974 else if (X
.isReturnedNotOwned()) {
2975 Decl
const *CD
= &Pred
->getCodeDecl();
2976 if (const ObjCMethodDecl
* MD
= dyn_cast
<ObjCMethodDecl
>(CD
)) {
2977 const RetainSummary
&Summ
= *Summaries
.getMethodSummary(MD
);
2978 if (Summ
.getRetEffect().isOwned()) {
2979 // Trying to return a not owned object to a caller expecting an
2982 static int ReturnNotOwnedForOwnedTag
= 0;
2983 state
= state
->set
<RefBindings
>(Sym
, X
^ RefVal::ErrorReturnedNotOwned
);
2984 if (ExplodedNode
*N
=
2985 Builder
.generateNode(PostStmt(S
, Pred
->getLocationContext(),
2986 &ReturnNotOwnedForOwnedTag
),
2988 CFRefReport
*report
=
2989 new CFRefReport(*static_cast<CFRefBug
*>(returnNotOwnedForOwned
),
2991 BR
->EmitReport(report
);
3000 const GRState
* CFRefCount::evalAssume(const GRState
*state
,
3001 SVal Cond
, bool Assumption
) {
3003 // FIXME: We may add to the interface of evalAssume the list of symbols
3004 // whose assumptions have changed. For now we just iterate through the
3005 // bindings and check if any of the tracked symbols are NULL. This isn't
3006 // too bad since the number of symbols we will track in practice are
3007 // probably small and evalAssume is only called at branches and a few
3009 RefBindings B
= state
->get
<RefBindings
>();
3014 bool changed
= false;
3015 RefBindings::Factory
& RefBFactory
= state
->get_context
<RefBindings
>();
3017 for (RefBindings::iterator I
=B
.begin(), E
=B
.end(); I
!=E
; ++I
) {
3018 // Check if the symbol is null (or equal to any constant).
3019 // If this is the case, stop tracking the symbol.
3020 if (state
->getSymVal(I
.getKey())) {
3022 B
= RefBFactory
.remove(B
, I
.getKey());
3027 state
= state
->set
<RefBindings
>(B
);
3032 const GRState
* CFRefCount::Update(const GRState
* state
, SymbolRef sym
,
3033 RefVal V
, ArgEffect E
,
3034 RefVal::Kind
& hasErr
) {
3036 // In GC mode [... release] and [... retain] do nothing.
3039 case IncRefMsg
: E
= isGCEnabled() ? DoNothing
: IncRef
; break;
3040 case DecRefMsg
: E
= isGCEnabled() ? DoNothing
: DecRef
; break;
3041 case MakeCollectable
: E
= isGCEnabled() ? DecRef
: DoNothing
; break;
3042 case NewAutoreleasePool
: E
= isGCEnabled() ? DoNothing
:
3043 NewAutoreleasePool
; break;
3046 // Handle all use-after-releases.
3047 if (!isGCEnabled() && V
.getKind() == RefVal::Released
) {
3048 V
= V
^ RefVal::ErrorUseAfterRelease
;
3049 hasErr
= V
.getKind();
3050 return state
->set
<RefBindings
>(sym
, V
);
3055 assert (false && "Unhandled CFRef transition.");
3058 // Any use of -dealloc in GC is *bad*.
3059 if (isGCEnabled()) {
3060 V
= V
^ RefVal::ErrorDeallocGC
;
3061 hasErr
= V
.getKind();
3065 switch (V
.getKind()) {
3067 assert(false && "Invalid case.");
3069 // The object immediately transitions to the released state.
3070 V
= V
^ RefVal::Released
;
3072 return state
->set
<RefBindings
>(sym
, V
);
3073 case RefVal::NotOwned
:
3074 V
= V
^ RefVal::ErrorDeallocNotOwned
;
3075 hasErr
= V
.getKind();
3080 case NewAutoreleasePool
:
3081 assert(!isGCEnabled());
3082 return state
->add
<AutoreleaseStack
>(sym
);
3085 if (V
.getKind() == RefVal::Owned
) {
3086 V
= V
^ RefVal::NotOwned
;
3092 case DoNothingByRef
:
3100 // Update the autorelease counts.
3101 state
= SendAutorelease(state
, ARCountFactory
, sym
);
3102 V
= V
.autorelease();
3106 return state
->remove
<RefBindings
>(sym
);
3109 switch (V
.getKind()) {
3114 case RefVal::NotOwned
:
3117 case RefVal::Released
:
3118 // Non-GC cases are handled above.
3119 assert(isGCEnabled());
3120 V
= (V
^ RefVal::Owned
) + 1;
3126 V
= V
^ RefVal::NotOwned
;
3129 switch (V
.getKind()) {
3131 // case 'RefVal::Released' handled above.
3135 assert(V
.getCount() > 0);
3136 if (V
.getCount() == 1) V
= V
^ RefVal::Released
;
3140 case RefVal::NotOwned
:
3141 if (V
.getCount() > 0)
3144 V
= V
^ RefVal::ErrorReleaseNotOwned
;
3145 hasErr
= V
.getKind();
3149 case RefVal::Released
:
3150 // Non-GC cases are handled above.
3151 assert(isGCEnabled());
3152 V
= V
^ RefVal::ErrorUseAfterRelease
;
3153 hasErr
= V
.getKind();
3158 return state
->set
<RefBindings
>(sym
, V
);
3161 //===----------------------------------------------------------------------===//
3162 // Handle dead symbols and end-of-path.
3163 //===----------------------------------------------------------------------===//
3165 std::pair
<ExplodedNode
*, const GRState
*>
3166 CFRefCount::HandleAutoreleaseCounts(const GRState
* state
,
3167 GenericNodeBuilderRefCount Bd
,
3170 SymbolRef Sym
, RefVal V
, bool &stop
) {
3172 unsigned ACnt
= V
.getAutoreleaseCount();
3175 // No autorelease counts? Nothing to be done.
3177 return std::make_pair(Pred
, state
);
3179 assert(!isGCEnabled() && "Autorelease counts in GC mode?");
3180 unsigned Cnt
= V
.getCount();
3182 // FIXME: Handle sending 'autorelease' to already released object.
3184 if (V
.getKind() == RefVal::ReturnedOwned
)
3190 if (V
.getKind() == RefVal::ReturnedOwned
)
3191 V
= V
^ RefVal::ReturnedNotOwned
;
3193 V
= V
^ RefVal::NotOwned
;
3196 V
.setCount(Cnt
- ACnt
);
3197 V
.setAutoreleaseCount(0);
3199 state
= state
->set
<RefBindings
>(Sym
, V
);
3200 ExplodedNode
*N
= Bd
.MakeNode(state
, Pred
);
3202 return std::make_pair(N
, state
);
3205 // Woah! More autorelease counts then retain counts left.
3208 V
= V
^ RefVal::ErrorOverAutorelease
;
3209 state
= state
->set
<RefBindings
>(Sym
, V
);
3211 if (ExplodedNode
*N
= Bd
.MakeNode(state
, Pred
)) {
3215 llvm::raw_string_ostream
os(sbuf
);
3216 os
<< "Object over-autoreleased: object was sent -autorelease";
3217 if (V
.getAutoreleaseCount() > 1)
3218 os
<< V
.getAutoreleaseCount() << " times";
3219 os
<< " but the object has ";
3220 if (V
.getCount() == 0)
3221 os
<< "zero (locally visible)";
3223 os
<< "+" << V
.getCount();
3224 os
<< " retain counts";
3226 CFRefReport
*report
=
3227 new CFRefReport(*static_cast<CFRefBug
*>(overAutorelease
),
3228 *this, N
, Sym
, os
.str());
3229 BR
->EmitReport(report
);
3232 return std::make_pair((ExplodedNode
*)0, state
);
3236 CFRefCount::HandleSymbolDeath(const GRState
* state
, SymbolRef sid
, RefVal V
,
3237 llvm::SmallVectorImpl
<SymbolRef
> &Leaked
) {
3239 bool hasLeak
= V
.isOwned() ||
3240 ((V
.isNotOwned() || V
.isReturnedOwned()) && V
.getCount() > 0);
3243 return state
->remove
<RefBindings
>(sid
);
3245 Leaked
.push_back(sid
);
3246 return state
->set
<RefBindings
>(sid
, V
^ RefVal::ErrorLeak
);
3250 CFRefCount::ProcessLeaks(const GRState
* state
,
3251 llvm::SmallVectorImpl
<SymbolRef
> &Leaked
,
3252 GenericNodeBuilderRefCount
&Builder
,
3254 ExplodedNode
*Pred
) {
3259 // Generate an intermediate node representing the leak point.
3260 ExplodedNode
*N
= Builder
.MakeNode(state
, Pred
);
3263 for (llvm::SmallVectorImpl
<SymbolRef
>::iterator
3264 I
= Leaked
.begin(), E
= Leaked
.end(); I
!= E
; ++I
) {
3266 CFRefBug
*BT
= static_cast<CFRefBug
*>(Pred
? leakWithinFunction
3268 assert(BT
&& "BugType not initialized.");
3269 CFRefLeakReport
* report
= new CFRefLeakReport(*BT
, *this, N
, *I
, Eng
);
3270 BR
->EmitReport(report
);
3277 void CFRefCount::evalEndPath(ExprEngine
& Eng
,
3278 EndOfFunctionNodeBuilder
& Builder
) {
3280 const GRState
*state
= Builder
.getState();
3281 GenericNodeBuilderRefCount
Bd(Builder
);
3282 RefBindings B
= state
->get
<RefBindings
>();
3283 ExplodedNode
*Pred
= 0;
3285 for (RefBindings::iterator I
= B
.begin(), E
= B
.end(); I
!= E
; ++I
) {
3287 llvm::tie(Pred
, state
) = HandleAutoreleaseCounts(state
, Bd
, Pred
, Eng
,
3295 B
= state
->get
<RefBindings
>();
3296 llvm::SmallVector
<SymbolRef
, 10> Leaked
;
3298 for (RefBindings::iterator I
= B
.begin(), E
= B
.end(); I
!= E
; ++I
)
3299 state
= HandleSymbolDeath(state
, (*I
).first
, (*I
).second
, Leaked
);
3301 ProcessLeaks(state
, Leaked
, Bd
, Eng
, Pred
);
3304 void CFRefCount::evalDeadSymbols(ExplodedNodeSet
& Dst
,
3306 StmtNodeBuilder
& Builder
,
3308 const GRState
* state
,
3309 SymbolReaper
& SymReaper
) {
3310 const Stmt
*S
= Builder
.getStmt();
3311 RefBindings B
= state
->get
<RefBindings
>();
3313 // Update counts from autorelease pools
3314 for (SymbolReaper::dead_iterator I
= SymReaper
.dead_begin(),
3315 E
= SymReaper
.dead_end(); I
!= E
; ++I
) {
3317 if (const RefVal
* T
= B
.lookup(Sym
)){
3318 // Use the symbol as the tag.
3319 // FIXME: This might not be as unique as we would like.
3320 GenericNodeBuilderRefCount
Bd(Builder
, S
, Sym
);
3322 llvm::tie(Pred
, state
) = HandleAutoreleaseCounts(state
, Bd
, Pred
, Eng
,
3329 B
= state
->get
<RefBindings
>();
3330 llvm::SmallVector
<SymbolRef
, 10> Leaked
;
3332 for (SymbolReaper::dead_iterator I
= SymReaper
.dead_begin(),
3333 E
= SymReaper
.dead_end(); I
!= E
; ++I
) {
3334 if (const RefVal
* T
= B
.lookup(*I
))
3335 state
= HandleSymbolDeath(state
, *I
, *T
, Leaked
);
3338 static unsigned LeakPPTag
= 0;
3340 GenericNodeBuilderRefCount
Bd(Builder
, S
, &LeakPPTag
);
3341 Pred
= ProcessLeaks(state
, Leaked
, Bd
, Eng
, Pred
);
3344 // Did we cache out?
3348 // Now generate a new node that nukes the old bindings.
3349 RefBindings::Factory
& F
= state
->get_context
<RefBindings
>();
3351 for (SymbolReaper::dead_iterator I
= SymReaper
.dead_begin(),
3352 E
= SymReaper
.dead_end(); I
!=E
; ++I
) B
= F
.remove(B
, *I
);
3354 state
= state
->set
<RefBindings
>(B
);
3355 Builder
.MakeNode(Dst
, S
, Pred
, state
);
3358 void CFRefCount::ProcessNonLeakError(ExplodedNodeSet
& Dst
,
3359 StmtNodeBuilder
& Builder
,
3360 const Expr
* NodeExpr
,
3361 SourceRange ErrorRange
,
3364 RefVal::Kind hasErr
, SymbolRef Sym
) {
3365 Builder
.BuildSinks
= true;
3366 ExplodedNode
*N
= Builder
.MakeNode(Dst
, NodeExpr
, Pred
, St
);
3375 assert(false && "Unhandled error.");
3377 case RefVal::ErrorUseAfterRelease
:
3378 BT
= static_cast<CFRefBug
*>(useAfterRelease
);
3380 case RefVal::ErrorReleaseNotOwned
:
3381 BT
= static_cast<CFRefBug
*>(releaseNotOwned
);
3383 case RefVal::ErrorDeallocGC
:
3384 BT
= static_cast<CFRefBug
*>(deallocGC
);
3386 case RefVal::ErrorDeallocNotOwned
:
3387 BT
= static_cast<CFRefBug
*>(deallocNotOwned
);
3391 CFRefReport
*report
= new CFRefReport(*BT
, *this, N
, Sym
);
3392 report
->addRange(ErrorRange
);
3393 BR
->EmitReport(report
);
3396 //===----------------------------------------------------------------------===//
3397 // Pieces of the retain/release checker implemented using a CheckerVisitor.
3398 // More pieces of the retain/release checker will be migrated to this interface
3399 // (ideally, all of it some day).
3400 //===----------------------------------------------------------------------===//
3403 class RetainReleaseChecker
3404 : public CheckerVisitor
<RetainReleaseChecker
> {
3407 RetainReleaseChecker(CFRefCount
*tf
) : TF(tf
) {}
3408 static void* getTag() { static int x
= 0; return &x
; }
3410 void PostVisitBlockExpr(CheckerContext
&C
, const BlockExpr
*BE
);
3412 } // end anonymous namespace
3415 void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext
&C
,
3416 const BlockExpr
*BE
) {
3418 // Scan the BlockDecRefExprs for any object the retain/release checker
3420 if (!BE
->getBlockDecl()->hasCaptures())
3423 const GRState
*state
= C
.getState();
3424 const BlockDataRegion
*R
=
3425 cast
<BlockDataRegion
>(state
->getSVal(BE
).getAsRegion());
3427 BlockDataRegion::referenced_vars_iterator I
= R
->referenced_vars_begin(),
3428 E
= R
->referenced_vars_end();
3433 // FIXME: For now we invalidate the tracking of all symbols passed to blocks
3434 // via captured variables, even though captured variables result in a copy
3435 // and in implicit increment/decrement of a retain count.
3436 llvm::SmallVector
<const MemRegion
*, 10> Regions
;
3437 const LocationContext
*LC
= C
.getPredecessor()->getLocationContext();
3438 MemRegionManager
&MemMgr
= C
.getSValBuilder().getRegionManager();
3440 for ( ; I
!= E
; ++I
) {
3441 const VarRegion
*VR
= *I
;
3442 if (VR
->getSuperRegion() == R
) {
3443 VR
= MemMgr
.getVarRegion(VR
->getDecl(), LC
);
3445 Regions
.push_back(VR
);
3449 state
->scanReachableSymbols
<StopTrackingCallback
>(Regions
.data(),
3450 Regions
.data() + Regions
.size()).getState();
3451 C
.addTransition(state
);
3454 //===----------------------------------------------------------------------===//
3455 // Transfer function creation for external clients.
3456 //===----------------------------------------------------------------------===//
3458 void CFRefCount::RegisterChecks(ExprEngine
& Eng
) {
3459 BugReporter
&BR
= Eng
.getBugReporter();
3461 useAfterRelease
= new UseAfterRelease(this);
3462 BR
.Register(useAfterRelease
);
3464 releaseNotOwned
= new BadRelease(this);
3465 BR
.Register(releaseNotOwned
);
3467 deallocGC
= new DeallocGC(this);
3468 BR
.Register(deallocGC
);
3470 deallocNotOwned
= new DeallocNotOwned(this);
3471 BR
.Register(deallocNotOwned
);
3473 overAutorelease
= new OverAutorelease(this);
3474 BR
.Register(overAutorelease
);
3476 returnNotOwnedForOwned
= new ReturnedNotOwnedForOwned(this);
3477 BR
.Register(returnNotOwnedForOwned
);
3479 // First register "return" leaks.
3480 const char* name
= 0;
3483 name
= "Leak of returned object when using garbage collection";
3484 else if (getLangOptions().getGCMode() == LangOptions::HybridGC
)
3485 name
= "Leak of returned object when not using garbage collection (GC) in "
3486 "dual GC/non-GC code";
3488 assert(getLangOptions().getGCMode() == LangOptions::NonGC
);
3489 name
= "Leak of returned object";
3492 // Leaks should not be reported if they are post-dominated by a sink.
3493 leakAtReturn
= new LeakAtReturn(this, name
);
3494 leakAtReturn
->setSuppressOnSink(true);
3495 BR
.Register(leakAtReturn
);
3497 // Second, register leaks within a function/method.
3499 name
= "Leak of object when using garbage collection";
3500 else if (getLangOptions().getGCMode() == LangOptions::HybridGC
)
3501 name
= "Leak of object when not using garbage collection (GC) in "
3502 "dual GC/non-GC code";
3504 assert(getLangOptions().getGCMode() == LangOptions::NonGC
);
3508 // Leaks should not be reported if they are post-dominated by sinks.
3509 leakWithinFunction
= new LeakWithinFunction(this, name
);
3510 leakWithinFunction
->setSuppressOnSink(true);
3511 BR
.Register(leakWithinFunction
);
3513 // Save the reference to the BugReporter.
3516 // Register the RetainReleaseChecker with the ExprEngine object.
3517 // Functionality in CFRefCount will be migrated to RetainReleaseChecker
3519 Eng
.registerCheck(new RetainReleaseChecker(this));
3522 TransferFuncs
* ento::MakeCFRefCountTF(ASTContext
& Ctx
, bool GCEnabled
,
3523 const LangOptions
& lopts
) {
3524 return new CFRefCount(Ctx
, GCEnabled
, lopts
);