 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
75.2% |
675 / 898 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
89.9% |
807 / 898 |
| |
|
Line Coverage: |
90.9% |
1195 / 1314 |
| |
 |
|
 |
1 : // CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file defines the methods for CFRefCount, which implements
11 : // a reference count checker for Core Foundation (Mac OS X).
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "clang/Basic/LangOptions.h"
16 : #include "clang/Basic/SourceManager.h"
17 : #include "clang/Checker/PathSensitive/GRExprEngineBuilders.h"
18 : #include "clang/Checker/PathSensitive/GRStateTrait.h"
19 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
20 : #include "clang/Checker/Checkers/LocalCheckers.h"
21 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
22 : #include "clang/Checker/BugReporter/BugReporter.h"
23 : #include "clang/Checker/PathSensitive/SymbolManager.h"
24 : #include "clang/Checker/PathSensitive/GRTransferFuncs.h"
25 : #include "clang/Checker/PathSensitive/CheckerVisitor.h"
26 : #include "clang/Checker/DomainSpecific/CocoaConventions.h"
27 : #include "clang/AST/DeclObjC.h"
28 : #include "clang/AST/StmtVisitor.h"
29 : #include "llvm/ADT/DenseMap.h"
30 : #include "llvm/ADT/FoldingSet.h"
31 : #include "llvm/ADT/ImmutableMap.h"
32 : #include "llvm/ADT/ImmutableList.h"
33 : #include "llvm/ADT/StringExtras.h"
34 : #include "llvm/ADT/STLExtras.h"
35 : #include <stdarg.h>
36 :
37 : using namespace clang;
38 : using llvm::StringRef;
39 : using llvm::StrInStrNoCase;
40 :
41 : static const ObjCMethodDecl*
42 66: ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
43 : ObjCInterfaceDecl *ID =
44 66: const_cast<ObjCInterfaceDecl*>(MD->getClassInterface());
45 :
46 : return MD->isInstanceMethod()
47 : ? ID->lookupInstanceMethod(MD->getSelector())
54: branch 1 taken
12: branch 2 taken
48 66: : ID->lookupClassMethod(MD->getSelector());
49 : }
50 :
51 : namespace {
52 : class GenericNodeBuilder {
53 : GRStmtNodeBuilder *SNB;
54 : Stmt *S;
55 : const void *tag;
56 : GREndPathNodeBuilder *ENB;
57 : public:
58 : GenericNodeBuilder(GRStmtNodeBuilder &snb, Stmt *s,
59 1388: const void *t)
60 1388: : SNB(&snb), S(s), tag(t), ENB(0) {}
61 :
62 2600: GenericNodeBuilder(GREndPathNodeBuilder &enb)
63 2600: : SNB(0), S(0), tag(0), ENB(&enb) {}
64 :
65 208: ExplodedNode *MakeNode(const GRState *state, ExplodedNode *Pred) {
85: branch 0 taken
123: branch 1 taken
66 208: if (SNB)
67 : return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
68 85: state, Pred);
69 :
0: branch 0 not taken
123: branch 1 taken
70 123: assert(ENB);
71 123: return ENB->generateNode(state, Pred);
72 : }
73 : };
74 : } // end anonymous namespace
75 :
76 : //===----------------------------------------------------------------------===//
77 : // Primitives used for constructing summaries for function/method calls.
78 : //===----------------------------------------------------------------------===//
79 :
80 : /// ArgEffect is used to summarize a function/method call's effect on a
81 : /// particular argument.
82 : enum ArgEffect { Autorelease, Dealloc, DecRef, DecRefMsg, DoNothing,
83 : DoNothingByRef, IncRefMsg, IncRef, MakeCollectable, MayEscape,
84 : NewAutoreleasePool, SelfOwn, StopTracking };
85 :
86 : namespace llvm {
87 : template <> struct FoldingSetTrait<ArgEffect> {
88 2364: static inline void Profile(const ArgEffect X, FoldingSetNodeID& ID) {
89 2364: ID.AddInteger((unsigned) X);
90 2364: }
91 : };
92 : } // end llvm namespace
93 :
94 : /// ArgEffects summarizes the effects of a function/method call on all of
95 : /// its arguments.
96 : typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
97 :
98 : namespace {
99 :
100 : /// RetEffect is used to summarize a function/method call's behavior with
101 : /// respect to its return value.
102 : class RetEffect {
103 : public:
104 : enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
105 : NotOwnedSymbol, GCNotOwnedSymbol, ReceiverAlias,
106 : OwnedWhenTrackedReceiver };
107 :
108 : enum ObjKind { CF, ObjC, AnyObj };
109 :
110 : private:
111 : Kind K;
112 : ObjKind O;
113 : unsigned index;
114 :
115 21887: RetEffect(Kind k, unsigned idx = 0) : K(k), O(AnyObj), index(idx) {}
116 11109: RetEffect(Kind k, ObjKind o) : K(k), O(o), index(0) {}
117 :
118 : public:
119 5560: Kind getKind() const { return K; }
120 :
121 909: ObjKind getObjKind() const { return O; }
122 :
123 136: unsigned getIndex() const {
0: branch 1 not taken
136: branch 2 taken
124 136: assert(getKind() == Alias);
125 136: return index;
126 : }
127 :
128 58: bool isOwned() const {
129 : return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
58: branch 0 taken
0: branch 1 not taken
32: branch 2 taken
26: branch 3 taken
6: branch 4 taken
26: branch 5 taken
130 58: K == OwnedWhenTrackedReceiver;
131 : }
132 :
133 1900: static RetEffect MakeOwnedWhenTrackedReceiver() {
134 1900: return RetEffect(OwnedWhenTrackedReceiver, ObjC);
135 : }
136 :
137 120: static RetEffect MakeAlias(unsigned Idx) {
138 120: return RetEffect(Alias, Idx);
139 : }
140 4276: static RetEffect MakeReceiverAlias() {
141 4276: return RetEffect(ReceiverAlias);
142 : }
143 4315: static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
4315: branch 0 taken
0: branch 1 not taken
144 4315: return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
145 : }
146 4418: static RetEffect MakeNotOwned(ObjKind o) {
147 4418: return RetEffect(NotOwnedSymbol, o);
148 : }
149 476: static RetEffect MakeGCNotOwned() {
150 476: return RetEffect(GCNotOwnedSymbol, ObjC);
151 : }
152 :
153 17491: static RetEffect MakeNoRet() {
154 17491: return RetEffect(NoRet);
155 : }
156 :
157 : void Profile(llvm::FoldingSetNodeID& ID) const {
158 : ID.AddInteger((unsigned)K);
159 : ID.AddInteger((unsigned)O);
160 : ID.AddInteger(index);
161 : }
162 : };
163 :
164 : //===----------------------------------------------------------------------===//
165 : // Reference-counting logic (typestate + counts).
166 : //===----------------------------------------------------------------------===//
167 :
168 : class RefVal {
169 : public:
170 : enum Kind {
171 : Owned = 0, // Owning reference.
172 : NotOwned, // Reference is not owned by still valid (not freed).
173 : Released, // Object has been released.
174 : ReturnedOwned, // Returned object passes ownership to caller.
175 : ReturnedNotOwned, // Return object does not pass ownership to caller.
176 : ERROR_START,
177 : ErrorDeallocNotOwned, // -dealloc called on non-owned object.
178 : ErrorDeallocGC, // Calling -dealloc with GC enabled.
179 : ErrorUseAfterRelease, // Object used after released.
180 : ErrorReleaseNotOwned, // Release of an object that was not owned.
181 : ERROR_LEAK_START,
182 : ErrorLeak, // A memory leak due to excessive reference counts.
183 : ErrorLeakReturned, // A memory leak due to the returning method not having
184 : // the correct naming conventions.
185 : ErrorGCLeakReturned,
186 : ErrorOverAutorelease,
187 : ErrorReturnedNotOwned
188 : };
189 :
190 : private:
191 : Kind kind;
192 : RetEffect::ObjKind okind;
193 : unsigned Cnt;
194 : unsigned ACnt;
195 : QualType T;
196 :
197 2343: RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
198 2343: : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
199 :
200 : RefVal(Kind k, unsigned cnt = 0)
201 : : kind(k), okind(RetEffect::AnyObj), Cnt(cnt), ACnt(0) {}
202 :
203 : public:
204 5231: Kind getKind() const { return kind; }
205 :
206 1802: RetEffect::ObjKind getObjKind() const { return okind; }
207 :
208 3487: unsigned getCount() const { return Cnt; }
209 2429: unsigned getAutoreleaseCount() const { return ACnt; }
210 2: unsigned getCombinedCounts() const { return Cnt + ACnt; }
211 50: void clearCounts() { Cnt = 0; ACnt = 0; }
212 105: void setCount(unsigned i) { Cnt = i; }
213 8: void setAutoreleaseCount(unsigned i) { ACnt = i; }
214 :
215 2021: QualType getType() const { return T; }
216 :
217 : // Useful predicates.
218 :
219 : static bool isError(Kind k) { return k >= ERROR_START; }
220 :
221 : static bool isLeak(Kind k) { return k >= ERROR_LEAK_START; }
222 :
223 995: bool isOwned() const {
224 995: return getKind() == Owned;
225 : }
226 :
227 632: bool isNotOwned() const {
228 632: return getKind() == NotOwned;
229 : }
230 :
231 539: bool isReturnedOwned() const {
232 539: return getKind() == ReturnedOwned;
233 : }
234 :
235 32: bool isReturnedNotOwned() const {
236 32: return getKind() == ReturnedNotOwned;
237 : }
238 :
239 : bool isNonLeakError() const {
240 : Kind k = getKind();
241 : return isError(k) && !isLeak(k);
242 : }
243 :
244 : static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
245 741: unsigned Count = 1) {
246 741: return RefVal(Owned, o, Count, 0, t);
247 : }
248 :
249 : static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
250 158: unsigned Count = 0) {
251 158: return RefVal(NotOwned, o, Count, 0, t);
252 : }
253 :
254 : // Comparison, profiling, and pretty-printing.
255 :
256 2816: bool operator==(const RefVal& X) const {
2727: branch 0 taken
89: branch 1 taken
2641: branch 2 taken
86: branch 3 taken
2641: branch 5 taken
0: branch 6 not taken
2619: branch 7 taken
22: branch 8 taken
257 2816: return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
258 : }
259 :
260 448: RefVal operator-(size_t i) const {
261 : return RefVal(getKind(), getObjKind(), getCount() - i,
262 448: getAutoreleaseCount(), getType());
263 : }
264 :
265 111: RefVal operator+(size_t i) const {
266 : return RefVal(getKind(), getObjKind(), getCount() + i,
267 111: getAutoreleaseCount(), getType());
268 : }
269 :
270 819: RefVal operator^(Kind k) const {
271 : return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
272 819: getType());
273 : }
274 :
275 66: RefVal autorelease() const {
276 : return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
277 66: getType());
278 : }
279 :
280 3458: void Profile(llvm::FoldingSetNodeID& ID) const {
281 3458: ID.AddInteger((unsigned) kind);
282 3458: ID.AddInteger(Cnt);
283 3458: ID.AddInteger(ACnt);
284 3458: ID.Add(T);
285 3458: }
286 :
287 : void print(llvm::raw_ostream& Out) const;
288 : };
289 :
290 0: void RefVal::print(llvm::raw_ostream& Out) const {
0: branch 1 not taken
0: branch 2 not taken
291 0: if (!T.isNull())
292 0: Out << "Tracked Type:" << T.getAsString() << '\n';
293 :
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
0: branch 10 not taken
0: branch 11 not taken
0: branch 12 not taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 15 not taken
294 0: switch (getKind()) {
295 0: default: assert(false);
296 : case Owned: {
297 0: Out << "Owned";
298 0: unsigned cnt = getCount();
0: branch 0 not taken
0: branch 1 not taken
299 0: if (cnt) Out << " (+ " << cnt << ")";
300 0: break;
301 : }
302 :
303 : case NotOwned: {
304 0: Out << "NotOwned";
305 0: unsigned cnt = getCount();
0: branch 0 not taken
0: branch 1 not taken
306 0: if (cnt) Out << " (+ " << cnt << ")";
307 0: break;
308 : }
309 :
310 : case ReturnedOwned: {
311 0: Out << "ReturnedOwned";
312 0: unsigned cnt = getCount();
0: branch 0 not taken
0: branch 1 not taken
313 0: if (cnt) Out << " (+ " << cnt << ")";
314 0: break;
315 : }
316 :
317 : case ReturnedNotOwned: {
318 0: Out << "ReturnedNotOwned";
319 0: unsigned cnt = getCount();
0: branch 0 not taken
0: branch 1 not taken
320 0: if (cnt) Out << " (+ " << cnt << ")";
321 0: break;
322 : }
323 :
324 : case Released:
325 0: Out << "Released";
326 0: break;
327 :
328 : case ErrorDeallocGC:
329 0: Out << "-dealloc (GC)";
330 0: break;
331 :
332 : case ErrorDeallocNotOwned:
333 0: Out << "-dealloc (not-owned)";
334 0: break;
335 :
336 : case ErrorLeak:
337 0: Out << "Leaked";
338 0: break;
339 :
340 : case ErrorLeakReturned:
341 0: Out << "Leaked (Bad naming)";
342 0: break;
343 :
344 : case ErrorGCLeakReturned:
345 0: Out << "Leaked (GC-ed at return)";
346 0: break;
347 :
348 : case ErrorUseAfterRelease:
349 0: Out << "Use-After-Release [ERROR]";
350 0: break;
351 :
352 : case ErrorReleaseNotOwned:
353 0: Out << "Release of Not-Owned [ERROR]";
354 0: break;
355 :
356 : case RefVal::ErrorOverAutorelease:
357 0: Out << "Over autoreleased";
358 0: break;
359 :
360 : case RefVal::ErrorReturnedNotOwned:
361 0: Out << "Non-owned object returned instead of owned";
362 : break;
363 : }
364 :
0: branch 0 not taken
0: branch 1 not taken
365 0: if (ACnt) {
366 0: Out << " [ARC +" << ACnt << ']';
367 : }
368 0: }
369 : } //end anonymous namespace
370 :
371 : //===----------------------------------------------------------------------===//
372 : // RefBindings - State used to track object reference counts.
373 : //===----------------------------------------------------------------------===//
374 :
375 : typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
376 :
377 : namespace clang {
378 : template<>
379 : struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
380 49815: static void* GDMIndex() {
381 : static int RefBIndex = 0;
382 49815: return &RefBIndex;
383 : }
384 : };
385 : }
386 :
387 : //===----------------------------------------------------------------------===//
388 : // Summaries
389 : //===----------------------------------------------------------------------===//
390 :
391 : namespace {
392 : class RetainSummary {
393 : /// Args - an ordered vector of (index, ArgEffect) pairs, where index
394 : /// specifies the argument (starting from 0). This can be sparsely
395 : /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
396 : ArgEffects Args;
397 :
398 : /// DefaultArgEffect - The default ArgEffect to apply to arguments that
399 : /// do not have an entry in Args.
400 : ArgEffect DefaultArgEffect;
401 :
402 : /// Receiver - If this summary applies to an Objective-C message expression,
403 : /// this is the effect applied to the state of the receiver.
404 : ArgEffect Receiver;
405 :
406 : /// Ret - The effect on the return value. Used to indicate if the
407 : /// function/method call returns a new tracked symbol, returns an
408 : /// alias of one of the arguments in the call, and so on.
409 : RetEffect Ret;
410 :
411 : /// EndPath - Indicates that execution of this method/function should
412 : /// terminate the simulation of a path.
413 : bool EndPath;
414 :
415 : public:
416 : RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
417 41582: ArgEffect ReceiverEff, bool endpath = false)
418 : : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R),
419 41582: EndPath(endpath) {}
420 :
421 : /// getArg - Return the argument effect on the argument specified by
422 : /// idx (starting from 0).
423 1392: ArgEffect getArg(unsigned idx) const {
337: branch 1 taken
1055: branch 2 taken
424 1392: if (const ArgEffect *AE = Args.lookup(idx))
425 337: return *AE;
426 :
427 1055: return DefaultArgEffect;
428 : }
429 :
430 : /// setDefaultArgEffect - Set the default argument effect.
431 26: void setDefaultArgEffect(ArgEffect E) {
432 26: DefaultArgEffect = E;
433 26: }
434 :
435 : /// setArg - Set the argument effect on the argument specified by idx.
436 : void setArgEffect(ArgEffects::Factory& AF, unsigned idx, ArgEffect E) {
437 : Args = AF.Add(Args, idx, E);
438 : }
439 :
440 : /// getRetEffect - Returns the effect on the return value of the call.
441 2752: RetEffect getRetEffect() const { return Ret; }
442 :
443 : /// setRetEffect - Set the effect of the return value of the call.
444 42: void setRetEffect(RetEffect E) { Ret = E; }
445 :
446 : /// isEndPath - Returns true if executing the given method/function should
447 : /// terminate the path.
448 2686: bool isEndPath() const { return EndPath; }
449 :
450 : /// getReceiverEffect - Returns the effect on the receiver of the call.
451 : /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
452 687: ArgEffect getReceiverEffect() const { return Receiver; }
453 :
454 : /// setReceiverEffect - Set the effect on the receiver of the call.
455 : void setReceiverEffect(ArgEffect E) { Receiver = E; }
456 :
457 : typedef ArgEffects::iterator ExprIterator;
458 :
459 : ExprIterator begin_args() const { return Args.begin(); }
460 : ExprIterator end_args() const { return Args.end(); }
461 :
462 : static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects A,
463 : RetEffect RetEff, ArgEffect DefaultEff,
464 : ArgEffect ReceiverEff, bool EndPath) {
465 : ID.Add(A);
466 : ID.Add(RetEff);
467 : ID.AddInteger((unsigned) DefaultEff);
468 : ID.AddInteger((unsigned) ReceiverEff);
469 : ID.AddInteger((unsigned) EndPath);
470 : }
471 :
472 : void Profile(llvm::FoldingSetNodeID& ID) const {
473 : Profile(ID, Args, Ret, DefaultArgEffect, Receiver, EndPath);
474 : }
475 : };
476 : } // end anonymous namespace
477 :
478 : //===----------------------------------------------------------------------===//
479 : // Data structures for constructing summaries.
480 : //===----------------------------------------------------------------------===//
481 :
482 : namespace {
483 273664: class ObjCSummaryKey {
484 : IdentifierInfo* II;
485 : Selector S;
486 : public:
487 306085: ObjCSummaryKey(IdentifierInfo* ii, Selector s)
488 306085: : II(ii), S(s) {}
489 :
490 2191: ObjCSummaryKey(const ObjCInterfaceDecl* d, Selector s)
1538: branch 0 taken
653: branch 1 taken
491 2191: : II(d ? d->getIdentifier() : 0), S(s) {}
492 :
493 364: ObjCSummaryKey(const ObjCInterfaceDecl* d, IdentifierInfo *ii, Selector s)
267: branch 0 taken
97: branch 1 taken
494 364: : II(d ? d->getIdentifier() : ii), S(s) {}
495 :
496 25755: ObjCSummaryKey(Selector s)
497 25755: : II(0), S(s) {}
498 :
499 2092431: IdentifierInfo* getIdentifier() const { return II; }
500 836399: Selector getSelector() const { return S; }
501 : };
502 : }
503 :
504 : namespace llvm {
505 : template <> struct DenseMapInfo<ObjCSummaryKey> {
506 168175: static inline ObjCSummaryKey getEmptyKey() {
507 : return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
508 168175: DenseMapInfo<Selector>::getEmptyKey());
509 : }
510 :
511 88315: static inline ObjCSummaryKey getTombstoneKey() {
512 : return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
513 88315: DenseMapInfo<Selector>::getTombstoneKey());
514 : }
515 :
516 78295: static unsigned getHashValue(const ObjCSummaryKey &V) {
517 : return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
518 : & 0x88888888)
519 : | (DenseMapInfo<Selector>::getHashValue(V.getSelector())
520 78295: & 0x55555555);
521 : }
522 :
523 1007068: static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
524 : return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
525 : RHS.getIdentifier()) &&
526 : DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
379052: branch 3 taken
628016: branch 4 taken
351959: branch 8 taken
27093: branch 9 taken
527 1007068: RHS.getSelector());
528 : }
529 :
530 : };
531 : template <>
532 : struct isPodLike<ObjCSummaryKey> { static const bool value = true; };
533 : } // end llvm namespace
534 :
535 : namespace {
536 4276: class ObjCSummaryCache {
537 : typedef llvm::DenseMap<ObjCSummaryKey, RetainSummary*> MapTy;
538 : MapTy M;
539 : public:
540 4276: ObjCSummaryCache() {}
541 :
542 : RetainSummary* find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
543 1277: Selector S) {
544 : // Lookup the method using the decl for the class @interface. If we
545 : // have no decl, lookup using the class name.
856: branch 0 taken
421: branch 1 taken
546 1277: return D ? find(D, S) : find(ClsName, S);
547 : }
548 :
549 856: RetainSummary* find(const ObjCInterfaceDecl* D, Selector S) {
550 : // Do a lookup with the (D,S) pair. If we find a match return
551 : // the iterator.
552 856: ObjCSummaryKey K(D, S);
553 856: MapTy::iterator I = M.find(K);
554 :
657: branch 3 taken
199: branch 4 taken
0: branch 5 not taken
657: branch 6 taken
199: branch 7 taken
657: branch 8 taken
555 856: if (I != M.end() || !D)
556 199: return I->second;
557 :
558 : // Walk the super chain. If we find a hit with a parent, we'll end
559 : // up returning that summary. We actually allow that key (null,S), as
560 : // we cache summaries for the null ObjCInterfaceDecl* to allow us to
561 : // generate initial summaries without having to worry about NSObject
562 : // being declared.
563 : // FIXME: We may change this at some point.
564 1335: for (ObjCInterfaceDecl* C=D->getSuperClass() ;; C=C->getSuperClass()) {
945: branch 5 taken
390: branch 6 taken
565 1335: if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
566 390: break;
567 :
267: branch 0 taken
678: branch 1 taken
568 945: if (!C)
569 267: return NULL;
570 : }
571 :
572 : // Cache the summary with original key to make the next lookup faster
573 : // and return the iterator.
574 390: RetainSummary *Summ = I->second;
575 390: M[K] = Summ;
576 390: return Summ;
577 : }
578 :
579 :
580 : RetainSummary* find(Expr* Receiver, Selector S) {
581 : return find(getReceiverDecl(Receiver), S);
582 : }
583 :
584 421: RetainSummary* find(IdentifierInfo* II, Selector S) {
585 : // FIXME: Class method lookup. Right now we dont' have a good way
586 : // of going between IdentifierInfo* and the class hierarchy.
587 421: MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
588 :
99: branch 3 taken
322: branch 4 taken
589 421: if (I == M.end())
590 99: I = M.find(ObjCSummaryKey(S));
591 :
97: branch 3 taken
324: branch 4 taken
592 421: return I == M.end() ? NULL : I->second;
593 : }
594 :
595 : const ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
596 : if (const ObjCObjectPointerType* PT =
597 : E->getType()->getAs<ObjCObjectPointerType>())
598 : return PT->getInterfaceDecl();
599 :
600 : return NULL;
601 : }
602 :
603 : RetainSummary*& operator[](ObjCMessageExpr* ME) {
604 :
605 : Selector S = ME->getSelector();
606 :
607 : if (Expr* Receiver = ME->getReceiver()) {
608 : const ObjCInterfaceDecl* OD = getReceiverDecl(Receiver);
609 : return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
610 : }
611 :
612 : return M[ObjCSummaryKey(ME->getClassName(), S)];
613 : }
614 :
615 49538: RetainSummary*& operator[](ObjCSummaryKey K) {
616 49538: return M[K];
617 : }
618 :
619 25656: RetainSummary*& operator[](Selector S) {
620 25656: return M[ ObjCSummaryKey(S) ];
621 : }
622 : };
623 : } // end anonymous namespace
624 :
625 : //===----------------------------------------------------------------------===//
626 : // Data structures for managing collections of summaries.
627 : //===----------------------------------------------------------------------===//
628 :
629 : namespace {
630 : class RetainSummaryManager {
631 :
632 : //==-----------------------------------------------------------------==//
633 : // Typedefs.
634 : //==-----------------------------------------------------------------==//
635 :
636 : typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
637 : FuncSummariesTy;
638 :
639 : typedef ObjCSummaryCache ObjCMethodSummariesTy;
640 :
641 : //==-----------------------------------------------------------------==//
642 : // Data.
643 : //==-----------------------------------------------------------------==//
644 :
645 : /// Ctx - The ASTContext object for the analyzed ASTs.
646 : ASTContext& Ctx;
647 :
648 : /// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
649 : /// "CFDictionaryCreate".
650 : IdentifierInfo* CFDictionaryCreateII;
651 :
652 : /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
653 : const bool GCEnabled;
654 :
655 : /// FuncSummaries - A map from FunctionDecls to summaries.
656 : FuncSummariesTy FuncSummaries;
657 :
658 : /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
659 : /// to summaries.
660 : ObjCMethodSummariesTy ObjCClassMethodSummaries;
661 :
662 : /// ObjCMethodSummaries - A map from selectors to summaries.
663 : ObjCMethodSummariesTy ObjCMethodSummaries;
664 :
665 : /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
666 : /// and all other data used by the checker.
667 : llvm::BumpPtrAllocator BPAlloc;
668 :
669 : /// AF - A factory for ArgEffects objects.
670 : ArgEffects::Factory AF;
671 :
672 : /// ScratchArgs - A holding buffer for construct ArgEffects.
673 : ArgEffects ScratchArgs;
674 :
675 : /// ObjCAllocRetE - Default return effect for methods returning Objective-C
676 : /// objects.
677 : RetEffect ObjCAllocRetE;
678 :
679 : /// ObjCInitRetE - Default return effect for init methods returning
680 : /// Objective-C objects.
681 : RetEffect ObjCInitRetE;
682 :
683 : RetainSummary DefaultSummary;
684 : RetainSummary* StopSummary;
685 :
686 : //==-----------------------------------------------------------------==//
687 : // Methods.
688 : //==-----------------------------------------------------------------==//
689 :
690 : /// getArgEffects - Returns a persistent ArgEffects object based on the
691 : /// data in ScratchArgs.
692 : ArgEffects getArgEffects();
693 :
694 : enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
695 :
696 : public:
697 212: RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
698 :
699 699: RetainSummary *getDefaultSummary() {
700 699: RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
699: branch 1 taken
0: branch 2 not taken
701 699: return new (Summ) RetainSummary(DefaultSummary);
702 : }
703 :
704 : RetainSummary* getUnarySummary(const FunctionType* FT, UnaryFuncKind func);
705 :
706 : RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
707 : RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
708 : RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, StringRef FName);
709 :
710 : RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
711 : ArgEffect ReceiverEff = DoNothing,
712 : ArgEffect DefaultEff = MayEscape,
713 : bool isEndPath = false);
714 :
715 : RetainSummary* getPersistentSummary(RetEffect RE,
716 : ArgEffect ReceiverEff = DoNothing,
717 35168: ArgEffect DefaultEff = MayEscape) {
718 35168: return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
719 : }
720 :
721 104: RetainSummary *getPersistentStopSummary() {
1: branch 0 taken
103: branch 1 taken
722 104: if (StopSummary)
723 1: return StopSummary;
724 :
725 : StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
726 103: StopTracking, StopTracking);
727 :
728 103: return StopSummary;
729 : }
730 :
731 : RetainSummary *getInitMethodSummary(QualType RetTy);
732 :
733 : void InitializeClassMethodSummaries();
734 : void InitializeMethodSummaries();
735 : private:
736 :
737 : void addClsMethSummary(IdentifierInfo* ClsII, Selector S,
738 : RetainSummary* Summ) {
739 : ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
740 : }
741 :
742 6414: void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
743 6414: ObjCClassMethodSummaries[S] = Summ;
744 6414: }
745 :
746 19242: void addNSObjectMethSummary(Selector S, RetainSummary *Summ) {
747 19242: ObjCMethodSummaries[S] = Summ;
748 19242: }
749 :
750 : void addClassMethSummary(const char* Cls, const char* nullaryName,
751 12828: RetainSummary *Summ) {
752 12828: IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
753 12828: Selector S = GetNullarySelector(nullaryName, Ctx);
754 12828: ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
755 12828: }
756 :
757 : void addInstMethSummary(const char* Cls, const char* nullaryName,
758 2138: RetainSummary *Summ) {
759 2138: IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
760 2138: Selector S = GetNullarySelector(nullaryName, Ctx);
761 2138: ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
762 2138: }
763 :
764 34208: Selector generateSelector(va_list argp) {
765 34208: llvm::SmallVector<IdentifierInfo*, 10> II;
766 :
104762: branch 0 taken
34208: branch 1 taken
767 243732: while (const char* s = va_arg(argp, const char*))
768 104762: II.push_back(&Ctx.Idents.get(s));
769 :
770 34208: return Ctx.Selectors.getSelector(II.size(), &II[0]);
771 : }
772 :
773 : void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
774 34208: RetainSummary* Summ, va_list argp) {
775 34208: Selector S = generateSelector(argp);
776 34208: Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
777 34208: }
778 :
779 10690: void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) {
780 : va_list argp;
781 10690: va_start(argp, Summ);
782 10690: addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
783 10690: va_end(argp);
784 10690: }
785 :
786 4276: void addClsMethSummary(const char* Cls, RetainSummary* Summ, ...) {
787 : va_list argp;
788 4276: va_start(argp, Summ);
789 4276: addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
790 4276: va_end(argp);
791 4276: }
792 :
793 14966: void addClsMethSummary(IdentifierInfo *II, RetainSummary* Summ, ...) {
794 : va_list argp;
795 14966: va_start(argp, Summ);
796 14966: addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
797 14966: va_end(argp);
798 14966: }
799 :
800 4276: void addPanicSummary(const char* Cls, ...) {
801 : RetainSummary* Summ = getPersistentSummary(AF.GetEmptyMap(),
802 : RetEffect::MakeNoRet(),
803 4276: DoNothing, DoNothing, true);
804 : va_list argp;
805 4276: va_start (argp, Cls);
806 4276: addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
807 4276: va_end(argp);
808 4276: }
809 :
810 : public:
811 :
812 2138: RetainSummaryManager(ASTContext& ctx, bool gcenabled)
813 : : Ctx(ctx),
814 : CFDictionaryCreateII(&ctx.Idents.get("CFDictionaryCreate")),
815 : GCEnabled(gcenabled), AF(BPAlloc), ScratchArgs(AF.GetEmptyMap()),
816 : ObjCAllocRetE(gcenabled ? RetEffect::MakeGCNotOwned()
817 : : RetEffect::MakeOwned(RetEffect::ObjC, true)),
818 : ObjCInitRetE(gcenabled ? RetEffect::MakeGCNotOwned()
819 : : RetEffect::MakeOwnedWhenTrackedReceiver()),
820 : DefaultSummary(AF.GetEmptyMap() /* per-argument effects (none) */,
821 : RetEffect::MakeNoRet() /* return effect */,
822 : MayEscape, /* default argument effect */
823 : DoNothing /* receiver effect */),
238: branch 8 taken
1900: branch 9 taken
238: branch 12 taken
1900: branch 13 taken
824 2138: StopSummary(0) {
825 :
826 2138: InitializeClassMethodSummaries();
827 2138: InitializeMethodSummaries();
828 2138: }
829 :
830 : ~RetainSummaryManager();
831 :
832 : RetainSummary* getSummary(FunctionDecl* FD);
833 :
834 : RetainSummary *getInstanceMethodSummary(const ObjCMessageExpr *ME,
835 : const GRState *state,
836 : const LocationContext *LC);
837 :
838 : RetainSummary* getInstanceMethodSummary(const ObjCMessageExpr* ME,
839 846: const ObjCInterfaceDecl* ID) {
840 : return getInstanceMethodSummary(ME->getSelector(), ME->getClassName(),
841 846: ID, ME->getMethodDecl(), ME->getType());
842 : }
843 :
844 : RetainSummary* getInstanceMethodSummary(Selector S, IdentifierInfo *ClsName,
845 : const ObjCInterfaceDecl* ID,
846 : const ObjCMethodDecl *MD,
847 : QualType RetTy);
848 :
849 : RetainSummary *getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
850 : const ObjCInterfaceDecl *ID,
851 : const ObjCMethodDecl *MD,
852 : QualType RetTy);
853 :
854 365: RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME) {
855 : return getClassMethodSummary(ME->getSelector(), ME->getClassName(),
856 : ME->getClassInfo().first,
857 365: ME->getMethodDecl(), ME->getType());
858 : }
859 :
860 : /// getMethodSummary - This version of getMethodSummary is used to query
861 : /// the summary for the current method being analyzed.
862 66: RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
863 : // FIXME: Eventually this should be unneeded.
864 66: const ObjCInterfaceDecl *ID = MD->getClassInterface();
865 66: Selector S = MD->getSelector();
866 66: IdentifierInfo *ClsName = ID->getIdentifier();
867 66: QualType ResultTy = MD->getResultType();
868 :
869 : // Resolve the method decl last.
64: branch 1 taken
2: branch 2 taken
870 66: if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD))
871 64: MD = InterfaceMD;
872 :
54: branch 1 taken
12: branch 2 taken
873 66: if (MD->isInstanceMethod())
874 54: return getInstanceMethodSummary(S, ClsName, ID, MD, ResultTy);
875 : else
876 12: return getClassMethodSummary(S, ClsName, ID, MD, ResultTy);
877 : }
878 :
879 : RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD,
880 : Selector S, QualType RetTy);
881 :
882 : void updateSummaryFromAnnotations(RetainSummary &Summ,
883 : const ObjCMethodDecl *MD);
884 :
885 : void updateSummaryFromAnnotations(RetainSummary &Summ,
886 : const FunctionDecl *FD);
887 :
888 10710: bool isGCEnabled() const { return GCEnabled; }
889 :
890 26: RetainSummary *copySummary(RetainSummary *OldSumm) {
891 26: RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
26: branch 1 taken
0: branch 2 not taken
892 26: new (Summ) RetainSummary(*OldSumm);
893 26: return Summ;
894 : }
895 : };
896 :
897 : } // end anonymous namespace
898 :
899 : //===----------------------------------------------------------------------===//
900 : // Implementation of checker data structures.
901 : //===----------------------------------------------------------------------===//
902 :
903 2138: RetainSummaryManager::~RetainSummaryManager() {}
904 :
905 35168: ArgEffects RetainSummaryManager::getArgEffects() {
906 35168: ArgEffects AE = ScratchArgs;
907 35168: ScratchArgs = AF.GetEmptyMap();
908 : return AE;
909 : }
910 :
911 : RetainSummary*
912 : RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
913 : ArgEffect ReceiverEff,
914 : ArgEffect DefaultEff,
915 39444: bool isEndPath) {
916 : // Create the summary and return it.
917 39444: RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
39444: branch 1 taken
0: branch 2 not taken
918 39444: new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff, isEndPath);
919 39444: return Summ;
920 : }
921 :
922 : //===----------------------------------------------------------------------===//
923 : // Summary creation for functions (largely uses of Core Foundation).
924 : //===----------------------------------------------------------------------===//
925 :
926 343: static bool isRetain(FunctionDecl* FD, StringRef FName) {
927 343: return FName.endswith("Retain");
928 : }
929 :
930 217: static bool isRelease(FunctionDecl* FD, StringRef FName) {
931 217: return FName.endswith("Release");
932 : }
933 :
934 1464: RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
935 : // Look up a summary in our cache of FunctionDecls -> Summaries.
936 1464: FuncSummariesTy::iterator I = FuncSummaries.find(FD);
224: branch 3 taken
1240: branch 4 taken
937 1464: if (I != FuncSummaries.end())
938 224: return I->second;
939 :
940 : // No summary? Generate one.
941 1240: RetainSummary *S = 0;
942 :
943 : do {
944 : // We generate "stop" summaries for implicitly defined functions.
54: branch 1 taken
1186: branch 2 taken
945 1240: if (FD->isImplicit()) {
946 54: S = getPersistentStopSummary();
947 54: break;
948 : }
949 :
950 : // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
951 : // function's type.
952 1186: const FunctionType* FT = FD->getType()->getAs<FunctionType>();
953 1186: const IdentifierInfo *II = FD->getIdentifier();
0: branch 0 not taken
1186: branch 1 taken
954 1186: if (!II)
955 0: break;
956 :
957 1186: StringRef FName = II->getName();
958 :
959 : // Strip away preceding '_'. Doing this here will effect all the checks
960 : // down below.
961 1186: FName = FName.substr(FName.find_first_not_of('_'));
962 :
963 : // Inspect the result type.
964 1186: QualType RetTy = FT->getResultType();
965 :
966 : // FIXME: This should all be refactored into a chain of "summary lookup"
967 : // filters.
0: branch 1 not taken
1186: branch 2 taken
968 1186: assert(ScratchArgs.isEmpty());
969 :
2: branch 2 taken
1184: branch 3 taken
970 1186: if (FName == "pthread_create") {
971 : // Part of: <rdar://problem/7299394>. This will be addressed
972 : // better with IPA.
973 2: S = getPersistentStopSummary();
16: branch 2 taken
1168: branch 3 taken
974 1184: } else if (FName == "NSMakeCollectable") {
975 : // Handle: id NSMakeCollectable(CFTypeRef)
976 : S = (RetTy->isObjCIdType())
977 : ? getUnarySummary(FT, cfmakecollectable)
16: branch 2 taken
0: branch 3 not taken
978 16: : getPersistentStopSummary();
1166: branch 2 taken
2: branch 3 taken
1164: branch 6 taken
2: branch 7 taken
1162: branch 10 taken
2: branch 11 taken
1160: branch 14 taken
2: branch 15 taken
2: branch 18 taken
1158: branch 19 taken
10: branch 20 taken
1158: branch 21 taken
979 1168: } else if (FName == "IOBSDNameMatching" ||
980 : FName == "IOServiceMatching" ||
981 : FName == "IOServiceNameMatching" ||
982 : FName == "IORegistryEntryIDMatching" ||
983 : FName == "IOOpenFirmwarePathMatching") {
984 : // Part of <rdar://problem/6961230>. (IOKit)
985 : // This should be addressed using a API table.
986 : S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
987 10: DoNothing, DoNothing);
1156: branch 2 taken
2: branch 3 taken
2: branch 6 taken
1154: branch 7 taken
4: branch 8 taken
1154: branch 9 taken
988 1158: } else if (FName == "IOServiceGetMatchingService" ||
989 : FName == "IOServiceGetMatchingServices") {
990 : // FIXES: <rdar://problem/6326900>
991 : // This should be addressed using a API table. This strcmp is also
992 : // a little gross, but there is no need to super optimize here.
993 4: ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
994 4: S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1152: branch 2 taken
2: branch 3 taken
2: branch 6 taken
1150: branch 7 taken
4: branch 8 taken
1150: branch 9 taken
995 1154: } else if (FName == "IOServiceAddNotification" ||
996 : FName == "IOServiceAddMatchingNotification") {
997 : // Part of <rdar://problem/6961230>. (IOKit)
998 : // This should be addressed using a API table.
999 4: ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
1000 4: S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
2: branch 2 taken
1148: branch 3 taken
1001 1150: } else if (FName == "CVPixelBufferCreateWithBytes") {
1002 : // FIXES: <rdar://problem/7283567>
1003 : // Eventually this can be improved by recognizing that the pixel
1004 : // buffer passed to CVPixelBufferCreateWithBytes is released via
1005 : // a callback and doing full IPA to make sure this is done correctly.
1006 : // FIXME: This function has an out parameter that returns an
1007 : // allocated object.
1008 2: ScratchArgs = AF.Add(ScratchArgs, 7, StopTracking);
1009 2: S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
2: branch 2 taken
1146: branch 3 taken
1010 1148: } else if (FName == "CGBitmapContextCreateWithData") {
1011 : // FIXES: <rdar://problem/7358899>
1012 : // Eventually this can be improved by recognizing that 'releaseInfo'
1013 : // passed to CGBitmapContextCreateWithData is released via
1014 : // a callback and doing full IPA to make sure this is done correctly.
1015 2: ScratchArgs = AF.Add(ScratchArgs, 8, StopTracking);
1016 : S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
1017 2: DoNothing, DoNothing);
2: branch 2 taken
1144: branch 3 taken
1018 1146: } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
1019 : // FIXES: <rdar://problem/7283567>
1020 : // Eventually this can be improved by recognizing that the pixel
1021 : // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
1022 : // via a callback and doing full IPA to make sure this is done
1023 : // correctly.
1024 2: ScratchArgs = AF.Add(ScratchArgs, 12, StopTracking);
1025 2: S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
1026 : }
1027 :
1028 : // Did we get a summary?
42: branch 0 taken
1144: branch 1 taken
1029 1186: if (S)
1030 42: break;
1031 :
1032 : // Enable this code once the semantics of NSDeallocateObject are resolved
1033 : // for GC. <rdar://problem/6619988>
1034 : #if 0
1035 : // Handle: NSDeallocateObject(id anObject);
1036 : // This method does allow 'nil' (although we don't check it now).
1037 : if (strcmp(FName, "NSDeallocateObject") == 0) {
1038 : return RetTy == Ctx.VoidTy
1039 : ? getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, Dealloc)
1040 : : getPersistentStopSummary();
1041 : }
1042 : #endif
1043 :
481: branch 2 taken
663: branch 3 taken
1044 1144: if (RetTy->isPointerType()) {
1045 : // For CoreFoundation ('CF') types.
319: branch 2 taken
162: branch 3 taken
1046 481: if (cocoa::isRefType(RetTy, "CF", FName)) {
62: branch 1 taken
257: branch 2 taken
1047 319: if (isRetain(FD, FName))
1048 62: S = getUnarySummary(FT, cfretain);
34: branch 2 taken
223: branch 3 taken
1049 257: else if (FName.find("MakeCollectable") != StringRef::npos)
1050 34: S = getUnarySummary(FT, cfmakecollectable);
1051 : else
1052 223: S = getCFCreateGetRuleSummary(FD, FName);
1053 :
1054 319: break;
1055 : }
1056 :
1057 : // For CoreGraphics ('CG') types.
24: branch 2 taken
138: branch 3 taken
1058 162: if (cocoa::isRefType(RetTy, "CG", FName)) {
8: branch 1 taken
16: branch 2 taken
1059 24: if (isRetain(FD, FName))
1060 8: S = getUnarySummary(FT, cfretain);
1061 : else
1062 16: S = getCFCreateGetRuleSummary(FD, FName);
1063 :
1064 24: break;
1065 : }
1066 :
1067 : // For the Disk Arbitration API (DiskArbitration/DADisk.h)
132: branch 3 taken
6: branch 4 taken
130: branch 8 taken
2: branch 9 taken
2: branch 13 taken
128: branch 14 taken
10: branch 15 taken
128: branch 16 taken
1068 138: if (cocoa::isRefType(RetTy, "DADisk") ||
1069 : cocoa::isRefType(RetTy, "DADissenter") ||
1070 : cocoa::isRefType(RetTy, "DASessionRef")) {
1071 10: S = getCFCreateGetRuleSummary(FD, FName);
1072 10: break;
1073 : }
1074 :
1075 128: break;
1076 : }
1077 :
1078 : // Check for release functions, the only kind of functions that we care
1079 : // about that don't return a pointer type.
217: branch 1 taken
446: branch 2 taken
10: branch 4 taken
207: branch 5 taken
10: branch 7 taken
0: branch 8 not taken
217: branch 9 taken
446: branch 10 taken
1080 663: if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
1081 : // Test for 'CGCF'.
0: branch 2 not taken
217: branch 3 taken
1082 217: FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
1083 :
80: branch 1 taken
137: branch 2 taken
1084 217: if (isRelease(FD, FName))
1085 80: S = getUnarySummary(FT, cfrelease);
1086 : else {
0: branch 1 not taken
137: branch 2 taken
1087 137: assert (ScratchArgs.isEmpty());
1088 : // Remaining CoreFoundation and CoreGraphics functions.
1089 : // We use to assume that they all strictly followed the ownership idiom
1090 : // and that ownership cannot be transferred. While this is technically
1091 : // correct, many methods allow a tracked object to escape. For example:
1092 : //
1093 : // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
1094 : // CFDictionaryAddValue(y, key, x);
1095 : // CFRelease(x);
1096 : // ... it is okay to use 'x' since 'y' has a reference to it
1097 : //
1098 : // We handle this and similar cases with the follow heuristic. If the
1099 : // function name contains "InsertValue", "SetValue", "AddValue",
1100 : // "AppendValue", or "SetAttribute", then we assume that arguments may
1101 : // "escape." This means that something else holds on to the object,
1102 : // allowing it be used even after its local retain count drops to 0.
1103 : ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
1104 : StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
1105 : StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
1106 : StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
1107 : StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
137: branch 2 taken
0: branch 3 not taken
135: branch 6 taken
2: branch 7 taken
135: branch 10 taken
0: branch 11 not taken
131: branch 14 taken
4: branch 15 taken
2: branch 18 taken
129: branch 19 taken
1108 137: ? MayEscape : DoNothing;
1109 :
1110 137: S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
1111 : }
1112 : }
1113 : }
1114 : while (0);
1115 :
574: branch 0 taken
666: branch 1 taken
1116 1240: if (!S)
1117 574: S = getDefaultSummary();
1118 :
1119 : // Annotations override defaults.
0: branch 0 not taken
1240: branch 1 taken
1120 1240: assert(S);
1121 1240: updateSummaryFromAnnotations(*S, FD);
1122 :
1123 1240: FuncSummaries[FD] = S;
1124 1240: return S;
1125 : }
1126 :
1127 : RetainSummary*
1128 : RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
1129 249: StringRef FName) {
1130 :
32: branch 2 taken
217: branch 3 taken
4: branch 6 taken
28: branch 7 taken
221: branch 8 taken
28: branch 9 taken
1131 249: if (FName.find("Create") != StringRef::npos ||
1132 : FName.find("Copy") != StringRef::npos)
1133 221: return getCFSummaryCreateRule(FD);
1134 :
10: branch 2 taken
18: branch 3 taken
1135 28: if (FName.find("Get") != StringRef::npos)
1136 10: return getCFSummaryGetRule(FD);
1137 :
1138 18: return getDefaultSummary();
1139 : }
1140 :
1141 : RetainSummary*
1142 : RetainSummaryManager::getUnarySummary(const FunctionType* FT,
1143 200: UnaryFuncKind func) {
1144 :
1145 : // Sanity check that this is *really* a unary function. This can
1146 : // happen if people do weird things.
1147 200: const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
200: branch 0 taken
0: branch 1 not taken
0: branch 3 not taken
200: branch 4 taken
0: branch 5 not taken
200: branch 6 taken
1148 200: if (!FTP || FTP->getNumArgs() != 1)
1149 0: return getPersistentStopSummary();
1150 :
0: branch 1 not taken
200: branch 2 taken
1151 200: assert (ScratchArgs.isEmpty());
1152 :
70: branch 0 taken
80: branch 1 taken
50: branch 2 taken
0: branch 3 not taken
1153 200: switch (func) {
1154 : case cfretain: {
1155 70: ScratchArgs = AF.Add(ScratchArgs, 0, IncRef);
1156 : return getPersistentSummary(RetEffect::MakeAlias(0),
1157 70: DoNothing, DoNothing);
1158 : }
1159 :
1160 : case cfrelease: {
1161 80: ScratchArgs = AF.Add(ScratchArgs, 0, DecRef);
1162 : return getPersistentSummary(RetEffect::MakeNoRet(),
1163 80: DoNothing, DoNothing);
1164 : }
1165 :
1166 : case cfmakecollectable: {
1167 50: ScratchArgs = AF.Add(ScratchArgs, 0, MakeCollectable);
1168 50: return getPersistentSummary(RetEffect::MakeAlias(0),DoNothing, DoNothing);
1169 : }
1170 :
1171 : default:
1172 0: assert (false && "Not a supported unary function.");
1173 : return getDefaultSummary();
1174 : }
1175 : }
1176 :
1177 221: RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
0: branch 1 not taken
221: branch 2 taken
1178 221: assert (ScratchArgs.isEmpty());
1179 :
4: branch 1 taken
217: branch 2 taken
1180 221: if (FD->getIdentifier() == CFDictionaryCreateII) {
1181 4: ScratchArgs = AF.Add(ScratchArgs, 1, DoNothingByRef);
1182 4: ScratchArgs = AF.Add(ScratchArgs, 2, DoNothingByRef);
1183 : }
1184 :
1185 221: return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1186 : }
1187 :
1188 10: RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
0: branch 1 not taken
10: branch 2 taken
1189 10: assert (ScratchArgs.isEmpty());
1190 : return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1191 10: DoNothing, DoNothing);
1192 : }
1193 :
1194 : //===----------------------------------------------------------------------===//
1195 : // Summary creation for Selectors.
1196 : //===----------------------------------------------------------------------===//
1197 :
1198 : RetainSummary*
1199 95: RetainSummaryManager::getInitMethodSummary(QualType RetTy) {
0: branch 1 not taken
95: branch 2 taken
1200 95: assert(ScratchArgs.isEmpty());
1201 : // 'init' methods conceptually return a newly allocated object and claim
1202 : // the receiver.
0: branch 1 not taken
95: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
95: branch 6 taken
0: branch 7 not taken
1203 95: if (cocoa::isCocoaObjectRef(RetTy) || cocoa::isCFObjectRef(RetTy))
1204 95: return getPersistentSummary(ObjCInitRetE, DecRefMsg);
1205 :
1206 0: return getDefaultSummary();
1207 : }
1208 :
1209 : void
1210 : RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
1211 1240: const FunctionDecl *FD) {
0: branch 0 not taken
1240: branch 1 taken
1212 1240: if (!FD)
1213 0: return;
1214 :
1215 1240: QualType RetTy = FD->getResultType();
1216 :
1217 : // Determine if there is a special return effect for this method.
36: branch 1 taken
1204: branch 2 taken
1218 1240: if (cocoa::isCocoaObjectRef(RetTy)) {
0: branch 1 not taken
36: branch 2 taken
1219 36: if (FD->getAttr<NSReturnsRetainedAttr>()) {
1220 0: Summ.setRetEffect(ObjCAllocRetE);
1221 : }
0: branch 1 not taken
36: branch 2 taken
1222 36: else if (FD->getAttr<CFReturnsRetainedAttr>()) {
1223 0: Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
1224 : }
1225 : }
523: branch 2 taken
681: branch 3 taken
1226 1204: else if (RetTy->getAs<PointerType>()) {
24: branch 1 taken
499: branch 2 taken
1227 523: if (FD->getAttr<CFReturnsRetainedAttr>()) {
1228 24: Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
1229 : }
1230 : }
1231 : }
1232 :
1233 : void
1234 : RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
1235 364: const ObjCMethodDecl *MD) {
2: branch 0 taken
362: branch 1 taken
1236 364: if (!MD)
1237 2: return;
1238 :
1239 362: bool isTrackedLoc = false;
1240 :
1241 : // Determine if there is a special return effect for this method.
243: branch 2 taken
119: branch 3 taken
1242 362: if (cocoa::isCocoaObjectRef(MD->getResultType())) {
8: branch 1 taken
235: branch 2 taken
1243 243: if (MD->getAttr<NSReturnsRetainedAttr>()) {
1244 8: Summ.setRetEffect(ObjCAllocRetE);
1245 8: return;
1246 : }
1247 :
1248 235: isTrackedLoc = true;
1249 : }
1250 :
119: branch 0 taken
235: branch 1 taken
1251 354: if (!isTrackedLoc)
1252 119: isTrackedLoc = MD->getResultType()->getAs<PointerType>() != NULL;
1253 :
257: branch 0 taken
97: branch 1 taken
10: branch 3 taken
247: branch 4 taken
10: branch 5 taken
344: branch 6 taken
1254 354: if (isTrackedLoc && MD->getAttr<CFReturnsRetainedAttr>())
1255 10: Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
1256 : }
1257 :
1258 : RetainSummary*
1259 : RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
1260 269: Selector S, QualType RetTy) {
1261 :
267: branch 0 taken
2: branch 1 taken
1262 269: if (MD) {
1263 : // Scan the method decl for 'void*' arguments. These should be treated
1264 : // as 'StopTracking' because they are often used with delegates.
1265 : // Delegates are a frequent form of false positives with the retain
1266 : // count checker.
1267 267: unsigned i = 0;
185: branch 1 taken
267: branch 2 taken
1268 719: for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
1269 267: E = MD->param_end(); I != E; ++I, ++i)
185: branch 0 taken
0: branch 1 not taken
1270 185: if (ParmVarDecl *PD = *I) {
1271 185: QualType Ty = Ctx.getCanonicalType(PD->getType());
0: branch 3 not taken
185: branch 4 taken
1272 185: if (Ty.getLocalUnqualifiedType() == Ctx.VoidPtrTy)
1273 0: ScratchArgs = AF.Add(ScratchArgs, i, StopTracking);
1274 : }
1275 : }
1276 :
1277 : // Any special effect for the receiver?
1278 269: ArgEffect ReceiverEff = DoNothing;
1279 :
1280 : // If one of the arguments in the selector has the keyword 'delegate' we
1281 : // should stop tracking the reference count for the receiver. This is
1282 : // because the reference count is quite possibly handled by a delegate
1283 : // method.
115: branch 1 taken
154: branch 2 taken
1284 269: if (S.isKeywordSelector()) {
1285 115: const std::string &str = S.getAsString();
0: branch 1 not taken
115: branch 2 taken
1286 115: assert(!str.empty());
2: branch 3 taken
113: branch 4 taken
1287 115: if (StrInStrNoCase(str, "delegate:") != StringRef::npos)
1288 2: ReceiverEff = StopTracking;
1289 : }
1290 :
1291 : // Look for methods that return an owned object.
150: branch 1 taken
119: branch 2 taken
1292 269: if (cocoa::isCocoaObjectRef(RetTy)) {
1293 : // EXPERIMENTAL: Assume the Cocoa conventions for all objects returned
1294 : // by instance methods.
1295 : RetEffect E = cocoa::followsFundamentalRule(S)
26: branch 1 taken
124: branch 2 taken
1296 150: ? ObjCAllocRetE : RetEffect::MakeNotOwned(RetEffect::ObjC);
1297 :
1298 150: return getPersistentSummary(E, ReceiverEff, MayEscape);
1299 : }
1300 :
1301 : // Look for methods that return an owned core foundation object.
18: branch 1 taken
101: branch 2 taken
1302 119: if (cocoa::isCFObjectRef(RetTy)) {
1303 : RetEffect E = cocoa::followsFundamentalRule(S)
1304 : ? RetEffect::MakeOwned(RetEffect::CF, true)
10: branch 1 taken
8: branch 2 taken
1305 18: : RetEffect::MakeNotOwned(RetEffect::CF);
1306 :
1307 18: return getPersistentSummary(E, ReceiverEff, MayEscape);
1308 : }
1309 :
101: branch 1 taken
0: branch 2 not taken
99: branch 3 taken
2: branch 4 taken
99: branch 5 taken
2: branch 6 taken
1310 101: if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing)
1311 99: return getDefaultSummary();
1312 :
1313 2: return getPersistentSummary(RetEffect::MakeNoRet(), ReceiverEff, MayEscape);
1314 : }
1315 :
1316 : RetainSummary*
1317 : RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageExpr *ME,
1318 : const GRState *state,
1319 846: const LocationContext *LC) {
1320 :
1321 : // We need the type-information of the tracked receiver object
1322 : // Retrieve it from the state.
1323 846: const Expr *Receiver = ME->getReceiver();
1324 846: const ObjCInterfaceDecl* ID = 0;
1325 :
1326 : // FIXME: Is this really working as expected? There are cases where
1327 : // we just use the 'ID' from the message expression.
1328 846: SVal receiverV = state->getSValAsScalarOrLoc(Receiver);
1329 :
1330 : // FIXME: Eventually replace the use of state->get<RefBindings> with
1331 : // a generic API for reasoning about the Objective-C types of symbolic
1332 : // objects.
809: branch 1 taken
37: branch 2 taken
1333 846: if (SymbolRef Sym = receiverV.getAsLocSymbol())
577: branch 1 taken
232: branch 2 taken
1334 809: if (const RefVal *T = state->get<RefBindings>(Sym))
214: branch 0 taken
363: branch 1 taken
1335 577: if (const ObjCObjectPointerType* PT =
1336 577: T->getType()->getAs<ObjCObjectPointerType>())
1337 214: ID = PT->getInterfaceDecl();
1338 :
1339 : // FIXME: this is a hack. This may or may not be the actual method
1340 : // that is called.
806: branch 0 taken
40: branch 1 taken
1341 846: if (!ID) {
804: branch 0 taken
2: branch 1 taken
1342 806: if (const ObjCObjectPointerType *PT =
1343 806: Receiver->getType()->getAs<ObjCObjectPointerType>())
1344 804: ID = PT->getInterfaceDecl();
1345 : }
1346 :
1347 : // FIXME: The receiver could be a reference to a class, meaning that
1348 : // we should use the class method.
1349 846: RetainSummary *Summ = getInstanceMethodSummary(ME, ID);
1350 :
1351 : // Special-case: are we sending a mesage to "self"?
1352 : // This is a hack. When we have full-IP this should be removed.
250: branch 2 taken
596: branch 3 taken
1353 846: if (isa<ObjCMethodDecl>(LC->getDecl())) {
214: branch 1 taken
36: branch 2 taken
1354 250: if (const loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&receiverV)) {
1355 : // Get the region associated with 'self'.
214: branch 1 taken
0: branch 2 not taken
1356 214: if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl()) {
1357 214: SVal SelfVal = state->getSVal(state->getRegion(SelfDecl, LC));
26: branch 2 taken
188: branch 3 taken
1358 214: if (L->StripCasts() == SelfVal.getAsRegion()) {
1359 : // Update the summary to make the default argument effect
1360 : // 'StopTracking'.
1361 26: Summ = copySummary(Summ);
1362 26: Summ->setDefaultArgEffect(StopTracking);
1363 214: }
1364 : }
1365 : }
1366 : }
1367 :
0: branch 0 not taken
846: branch 1 taken
1368 846: return Summ ? Summ : getDefaultSummary();
1369 : }
1370 :
1371 : RetainSummary*
1372 : RetainSummaryManager::getInstanceMethodSummary(Selector S,
1373 : IdentifierInfo *ClsName,
1374 : const ObjCInterfaceDecl* ID,
1375 : const ObjCMethodDecl *MD,
1376 900: QualType RetTy) {
1377 :
1378 : // Look up a summary in our summary cache.
1379 900: RetainSummary *Summ = ObjCMethodSummaries.find(ID, ClsName, S);
1380 :
286: branch 0 taken
614: branch 1 taken
1381 900: if (!Summ) {
0: branch 1 not taken
286: branch 2 taken
1382 286: assert(ScratchArgs.isEmpty());
1383 :
1384 : // "initXXX": pass-through for receiver.
95: branch 1 taken
191: branch 2 taken
1385 286: if (cocoa::deriveNamingConvention(S) == cocoa::InitRule)
1386 95: Summ = getInitMethodSummary(RetTy);
1387 : else
1388 191: Summ = getCommonMethodSummary(MD, S, RetTy);
1389 :
1390 : // Annotations override defaults.
1391 286: updateSummaryFromAnnotations(*Summ, MD);
1392 :
1393 : // Memoize the summary.
1394 286: ObjCMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
1395 : }
1396 :
1397 900: return Summ;
1398 : }
1399 :
1400 : RetainSummary*
1401 : RetainSummaryManager::getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
1402 : const ObjCInterfaceDecl *ID,
1403 : const ObjCMethodDecl *MD,
1404 377: QualType RetTy) {
1405 :
0: branch 0 not taken
377: branch 1 taken
1406 377: assert(ClsName && "Class name must be specified.");
1407 377: RetainSummary *Summ = ObjCClassMethodSummaries.find(ID, ClsName, S);
1408 :
78: branch 0 taken
299: branch 1 taken
1409 377: if (!Summ) {
1410 78: Summ = getCommonMethodSummary(MD, S, RetTy);
1411 : // Annotations override defaults.
1412 78: updateSummaryFromAnnotations(*Summ, MD);
1413 : // Memoize the summary.
1414 78: ObjCClassMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
1415 : }
1416 :
1417 377: return Summ;
1418 : }
1419 :
1420 2138: void RetainSummaryManager::InitializeClassMethodSummaries() {
0: branch 1 not taken
2138: branch 2 taken
1421 2138: assert(ScratchArgs.isEmpty());
1422 2138: RetainSummary* Summ = getPersistentSummary(ObjCAllocRetE);
1423 :
1424 : // Create the summaries for "alloc", "new", and "allocWithZone:" for
1425 : // NSObject and its derivatives.
1426 2138: addNSObjectClsMethSummary(GetNullarySelector("alloc", Ctx), Summ);
1427 2138: addNSObjectClsMethSummary(GetNullarySelector("new", Ctx), Summ);
1428 2138: addNSObjectClsMethSummary(GetUnarySelector("allocWithZone", Ctx), Summ);
1429 :
1430 : // Create the [NSAssertionHandler currentHander] summary.
1431 : addClassMethSummary("NSAssertionHandler", "currentHandler",
1432 2138: getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
1433 :
1434 : // Create the [NSAutoreleasePool addObject:] summary.
1435 2138: ScratchArgs = AF.Add(ScratchArgs, 0, Autorelease);
1436 : addClassMethSummary("NSAutoreleasePool", "addObject",
1437 : getPersistentSummary(RetEffect::MakeNoRet(),
1438 2138: DoNothing, Autorelease));
1439 :
1440 : // Create a summary for [NSCursor dragCopyCursor].
1441 : addClassMethSummary("NSCursor", "dragCopyCursor",
1442 : getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
1443 2138: DoNothing));
1444 :
1445 : // Create the summaries for [NSObject performSelector...]. We treat
1446 : // these as 'stop tracking' for the arguments because they are often
1447 : // used for delegates that can release the object. When we have better
1448 : // inter-procedural analysis we can potentially do something better. This
1449 : // workaround is to remove false positives.
1450 2138: Summ = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking);
1451 2138: IdentifierInfo *NSObjectII = &Ctx.Idents.get("NSObject");
1452 : addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
1453 2138: "afterDelay", NULL);
1454 : addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
1455 2138: "afterDelay", "inModes", NULL);
1456 : addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
1457 2138: "withObject", "waitUntilDone", NULL);
1458 : addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
1459 2138: "withObject", "waitUntilDone", "modes", NULL);
1460 : addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
1461 2138: "withObject", "waitUntilDone", NULL);
1462 : addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
1463 2138: "withObject", "waitUntilDone", "modes", NULL);
1464 : addClsMethSummary(NSObjectII, Summ, "performSelectorInBackground",
1465 2138: "withObject", NULL);
1466 :
1467 : // Specially handle NSData.
1468 : RetainSummary *dataWithBytesNoCopySumm =
1469 : getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC), DoNothing,
1470 2138: DoNothing);
1471 : addClsMethSummary("NSData", dataWithBytesNoCopySumm,
1472 2138: "dataWithBytesNoCopy", "length", NULL);
1473 : addClsMethSummary("NSData", dataWithBytesNoCopySumm,
1474 2138: "dataWithBytesNoCopy", "length", "freeWhenDone", NULL);
1475 2138: }
1476 :
1477 2138: void RetainSummaryManager::InitializeMethodSummaries() {
1478 :
0: branch 1 not taken
2138: branch 2 taken
1479 2138: assert (ScratchArgs.isEmpty());
1480 :
1481 : // Create the "init" selector. It just acts as a pass-through for the
1482 : // receiver.
1483 2138: RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
1484 2138: addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
1485 :
1486 : // awakeAfterUsingCoder: behaves basically like an 'init' method. It
1487 : // claims the receiver and returns a retained object.
1488 : addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
1489 2138: InitSumm);
1490 :
1491 : // The next methods are allocators.
1492 2138: RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1493 : RetainSummary *CFAllocSumm =
1494 2138: getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
1495 :
1496 : // Create the "copy" selector.
1497 2138: addNSObjectMethSummary(GetNullarySelector("copy", Ctx), AllocSumm);
1498 :
1499 : // Create the "mutableCopy" selector.
1500 2138: addNSObjectMethSummary(GetNullarySelector("mutableCopy", Ctx), AllocSumm);
1501 :
1502 : // Create the "retain" selector.
1503 2138: RetEffect E = RetEffect::MakeReceiverAlias();
1504 2138: RetainSummary *Summ = getPersistentSummary(E, IncRefMsg);
1505 2138: addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
1506 :
1507 : // Create the "release" selector.
1508 2138: Summ = getPersistentSummary(E, DecRefMsg);
1509 2138: addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
1510 :
1511 : // Create the "drain" selector.
238: branch 1 taken
1900: branch 2 taken
1512 2138: Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
1513 2138: addNSObjectMethSummary(GetNullarySelector("drain", Ctx), Summ);
1514 :
1515 : // Create the -dealloc summary.
1516 2138: Summ = getPersistentSummary(RetEffect::MakeNoRet(), Dealloc);
1517 2138: addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
1518 :
1519 : // Create the "autorelease" selector.
1520 2138: Summ = getPersistentSummary(E, Autorelease);
1521 2138: addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
1522 :
1523 : // Specially handle NSAutoreleasePool.
1524 : addInstMethSummary("NSAutoreleasePool", "init",
1525 : getPersistentSummary(RetEffect::MakeReceiverAlias(),
1526 2138: NewAutoreleasePool));
1527 :
1528 : // For NSWindow, allocated objects are (initially) self-owned.
1529 : // FIXME: For now we opt for false negatives with NSWindow, as these objects
1530 : // self-own themselves. However, they only do this once they are displayed.
1531 : // Thus, we need to track an NSWindow's display status.
1532 : // This is tracked in <rdar://problem/6062711>.
1533 : // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1534 : RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1535 : StopTracking,
1536 2138: StopTracking);
1537 :
1538 2138: addClassMethSummary("NSWindow", "alloc", NoTrackYet);
1539 :
1540 : #if 0
1541 : addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
1542 : "styleMask", "backing", "defer", NULL);
1543 :
1544 : addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
1545 : "styleMask", "backing", "defer", "screen", NULL);
1546 : #endif
1547 :
1548 : // For NSPanel (which subclasses NSWindow), allocated objects are not
1549 : // self-owned.
1550 : // FIXME: For now we don't track NSPanels. object for the same reason
1551 : // as for NSWindow objects.
1552 2138: addClassMethSummary("NSPanel", "alloc", NoTrackYet);
1553 :
1554 : #if 0
1555 : addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
1556 : "styleMask", "backing", "defer", NULL);
1557 :
1558 : addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
1559 : "styleMask", "backing", "defer", "screen", NULL);
1560 : #endif
1561 :
1562 : // Don't track allocated autorelease pools yet, as it is okay to prematurely
1563 : // exit a method.
1564 2138: addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
1565 :
1566 : // Create NSAssertionHandler summaries.
1567 : addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
1568 2138: "lineNumber", "description", NULL);
1569 :
1570 : addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
1571 2138: "file", "lineNumber", "description", NULL);
1572 :
1573 : // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
1574 : addInstMethSummary("QCRenderer", AllocSumm,
1575 2138: "createSnapshotImageOfType", NULL);
1576 : addInstMethSummary("QCView", AllocSumm,
1577 2138: "createSnapshotImageOfType", NULL);
1578 :
1579 : // Create summaries for CIContext, 'createCGImage' and
1580 : // 'createCGLayerWithSize'. These objects are CF objects, and are not
1581 : // automatically garbage collected.
1582 : addInstMethSummary("CIContext", CFAllocSumm,
1583 2138: "createCGImage", "fromRect", NULL);
1584 : addInstMethSummary("CIContext", CFAllocSumm,
1585 2138: "createCGImage", "fromRect", "format", "colorSpace", NULL);
1586 : addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize",
1587 2138: "info", NULL);
1588 2138: }
1589 :
1590 : //===----------------------------------------------------------------------===//
1591 : // AutoreleaseBindings - State used to track objects in autorelease pools.
1592 : //===----------------------------------------------------------------------===//
1593 :
1594 : typedef llvm::ImmutableMap<SymbolRef, unsigned> ARCounts;
1595 : typedef llvm::ImmutableMap<SymbolRef, ARCounts> ARPoolContents;
1596 : typedef llvm::ImmutableList<SymbolRef> ARStack;
1597 :
1598 : static int AutoRCIndex = 0;
1599 : static int AutoRBIndex = 0;
1600 :
1601 : namespace { class AutoreleasePoolContents {}; }
1602 : namespace { class AutoreleaseStack {}; }
1603 :
1604 : namespace clang {
1605 : template<> struct GRStateTrait<AutoreleaseStack>
1606 : : public GRStatePartialTrait<ARStack> {
1607 66: static inline void* GDMIndex() { return &AutoRBIndex; }
1608 : };
1609 :
1610 : template<> struct GRStateTrait<AutoreleasePoolContents>
1611 : : public GRStatePartialTrait<ARPoolContents> {
1612 264: static inline void* GDMIndex() { return &AutoRCIndex; }
1613 : };
1614 : } // end clang namespace
1615 :
1616 66: static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
1617 66: ARStack stack = state->get<AutoreleaseStack>();
66: branch 1 taken
0: branch 2 not taken
1618 66: return stack.isEmpty() ? SymbolRef() : stack.getHead();
1619 : }
1620 :
1621 : static const GRState * SendAutorelease(const GRState *state,
1622 66: ARCounts::Factory &F, SymbolRef sym) {
1623 :
1624 66: SymbolRef pool = GetCurrentAutoreleasePool(state);
1625 66: const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
1626 66: ARCounts newCnts(0);
1627 :
22: branch 0 taken
44: branch 1 taken
1628 66: if (cnts) {
1629 22: const unsigned *cnt = (*cnts).lookup(sym);
10: branch 0 taken
12: branch 1 taken
1630 22: newCnts = F.Add(*cnts, sym, cnt ? *cnt + 1 : 1);
1631 : }
1632 : else
1633 44: newCnts = F.Add(F.GetEmptyMap(), sym, 1);
1634 :
1635 66: return state->set<AutoreleasePoolContents>(pool, newCnts);
1636 : }
1637 :
1638 : //===----------------------------------------------------------------------===//
1639 : // Transfer functions.
1640 : //===----------------------------------------------------------------------===//
1641 :
1642 : namespace {
1643 :
1644 : class CFRefCount : public GRTransferFuncs {
1645 : public:
2138: branch 2 taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
1646 4276: class BindingsPrinter : public GRState::Printer {
1647 : public:
1648 : virtual void Print(llvm::raw_ostream& Out, const GRState* state,
1649 : const char* nl, const char* sep);
1650 : };
1651 :
1652 : private:
1653 : typedef llvm::DenseMap<const ExplodedNode*, const RetainSummary*>
1654 : SummaryLogTy;
1655 :
1656 : RetainSummaryManager Summaries;
1657 : SummaryLogTy SummaryLog;
1658 : const LangOptions& LOpts;
1659 : ARCounts::Factory ARCountFactory;
1660 :
1661 : BugType *useAfterRelease, *releaseNotOwned;
1662 : BugType *deallocGC, *deallocNotOwned;
1663 : BugType *leakWithinFunction, *leakAtReturn;
1664 : BugType *overAutorelease;
1665 : BugType *returnNotOwnedForOwned;
1666 : BugReporter *BR;
1667 :
1668 : const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
1669 : RefVal::Kind& hasErr);
1670 :
1671 : void ProcessNonLeakError(ExplodedNodeSet& Dst,
1672 : GRStmtNodeBuilder& Builder,
1673 : Expr* NodeExpr, Expr* ErrorExpr,
1674 : ExplodedNode* Pred,
1675 : const GRState* St,
1676 : RefVal::Kind hasErr, SymbolRef Sym);
1677 :
1678 : const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
1679 : llvm::SmallVectorImpl<SymbolRef> &Leaked);
1680 :
1681 : ExplodedNode* ProcessLeaks(const GRState * state,
1682 : llvm::SmallVectorImpl<SymbolRef> &Leaked,
1683 : GenericNodeBuilder &Builder,
1684 : GRExprEngine &Eng,
1685 : ExplodedNode *Pred = 0);
1686 :
1687 : public:
1688 2138: CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
1689 : : Summaries(Ctx, gcenabled),
1690 : LOpts(lopts), useAfterRelease(0), releaseNotOwned(0),
1691 : deallocGC(0), deallocNotOwned(0),
1692 : leakWithinFunction(0), leakAtReturn(0), overAutorelease(0),
1693 2138: returnNotOwnedForOwned(0), BR(0) {}
1694 :
2138: branch 4 taken
0: branch 5 not taken
0: branch 11 not taken
0: branch 12 not taken
1695 2138: virtual ~CFRefCount() {}
1696 :
1697 : void RegisterChecks(GRExprEngine &Eng);
1698 :
1699 2138: virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
1700 2138: Printers.push_back(new BindingsPrinter());
1701 2138: }
1702 :
1703 8572: bool isGCEnabled() const { return Summaries.isGCEnabled(); }
1704 7453: const LangOptions& getLangOptions() const { return LOpts; }
1705 :
1706 1713: const RetainSummary *getSummaryOfNode(const ExplodedNode *N) const {
1707 1713: SummaryLogTy::const_iterator I = SummaryLog.find(N);
1419: branch 2 taken
294: branch 3 taken
1708 1713: return I == SummaryLog.end() ? 0 : I->second;
1709 : }
1710 :
1711 : // Calls.
1712 :
1713 : void EvalSummary(ExplodedNodeSet& Dst,
1714 : GRExprEngine& Eng,
1715 : GRStmtNodeBuilder& Builder,
1716 : Expr* Ex,
1717 : Expr* Receiver,
1718 : const RetainSummary& Summ,
1719 : const MemRegion *Callee,
1720 : ExprIterator arg_beg, ExprIterator arg_end,
1721 : ExplodedNode* Pred, const GRState *state);
1722 :
1723 : virtual void EvalCall(ExplodedNodeSet& Dst,
1724 : GRExprEngine& Eng,
1725 : GRStmtNodeBuilder& Builder,
1726 : CallExpr* CE, SVal L,
1727 : ExplodedNode* Pred);
1728 :
1729 :
1730 : virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
1731 : GRExprEngine& Engine,
1732 : GRStmtNodeBuilder& Builder,
1733 : ObjCMessageExpr* ME,
1734 : ExplodedNode* Pred,
1735 : const GRState *state);
1736 :
1737 : bool EvalObjCMessageExprAux(ExplodedNodeSet& Dst,
1738 : GRExprEngine& Engine,
1739 : GRStmtNodeBuilder& Builder,
1740 : ObjCMessageExpr* ME,
1741 : ExplodedNode* Pred);
1742 :
1743 : // Stores.
1744 : virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val);
1745 :
1746 : // End-of-path.
1747 :
1748 : virtual void EvalEndPath(GRExprEngine& Engine,
1749 : GREndPathNodeBuilder& Builder);
1750 :
1751 : virtual void EvalDeadSymbols(ExplodedNodeSet& Dst,
1752 : GRExprEngine& Engine,
1753 : GRStmtNodeBuilder& Builder,
1754 : ExplodedNode* Pred,
1755 : Stmt* S, const GRState* state,
1756 : SymbolReaper& SymReaper);
1757 :
1758 : std::pair<ExplodedNode*, const GRState *>
1759 : HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
1760 : ExplodedNode* Pred, GRExprEngine &Eng,
1761 : SymbolRef Sym, RefVal V, bool &stop);
1762 : // Return statements.
1763 :
1764 : virtual void EvalReturn(ExplodedNodeSet& Dst,
1765 : GRExprEngine& Engine,
1766 : GRStmtNodeBuilder& Builder,
1767 : ReturnStmt* S,
1768 : ExplodedNode* Pred);
1769 :
1770 : // Assumptions.
1771 :
1772 : virtual const GRState *EvalAssume(const GRState* state, SVal condition,
1773 : bool assumption);
1774 : };
1775 :
1776 : } // end anonymous namespace
1777 :
1778 : static void PrintPool(llvm::raw_ostream &Out, SymbolRef Sym,
1779 0: const GRState *state) {
1780 0: Out << ' ';
0: branch 0 not taken
0: branch 1 not taken
1781 0: if (Sym)
1782 0: Out << Sym->getSymbolID();
1783 : else
1784 0: Out << "<pool>";
1785 0: Out << ":{";
1786 :
1787 : // Get the contents of the pool.
0: branch 1 not taken
0: branch 2 not taken
1788 0: if (const ARCounts *cnts = state->get<AutoreleasePoolContents>(Sym))
0: branch 4 not taken
0: branch 5 not taken
1789 0: for (ARCounts::iterator J=cnts->begin(), EJ=cnts->end(); J != EJ; ++J)
1790 0: Out << '(' << J.getKey() << ',' << J.getData() << ')';
1791 :
1792 0: Out << '}';
1793 0: }
1794 :
1795 : void CFRefCount::BindingsPrinter::Print(llvm::raw_ostream& Out,
1796 : const GRState* state,
1797 0: const char* nl, const char* sep) {
1798 :
1799 0: RefBindings B = state->get<RefBindings>();
1800 :
0: branch 1 not taken
0: branch 2 not taken
1801 0: if (!B.isEmpty())
1802 0: Out << sep << nl;
1803 :
0: branch 4 not taken
0: branch 5 not taken
1804 0: for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1805 0: Out << (*I).first << " : ";
1806 0: (*I).second.print(Out);
1807 0: Out << nl;
1808 0: }
1809 :
1810 : // Print the autorelease stack.
1811 0: Out << sep << nl << "AR pool stack:";
1812 0: ARStack stack = state->get<AutoreleaseStack>();
1813 :
1814 0: PrintPool(Out, SymbolRef(), state); // Print the caller's pool.
0: branch 4 not taken
0: branch 5 not taken
1815 0: for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
1816 0: PrintPool(Out, *I, state);
1817 :
1818 0: Out << nl;
1819 0: }
1820 :
1821 : //===----------------------------------------------------------------------===//
1822 : // Error reporting.
1823 : //===----------------------------------------------------------------------===//
1824 :
1825 : namespace {
1826 :
1827 : //===-------------===//
1828 : // Bug Descriptions. //
1829 : //===-------------===//
1830 :
0: branch 1 not taken
17104: branch 2 taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 9 not taken
0: branch 10 not taken
1831 17104: class CFRefBug : public BugType {
1832 : protected:
1833 : CFRefCount& TF;
1834 :
1835 17104: CFRefBug(CFRefCount* tf, llvm::StringRef name)
1836 17104: : BugType(name, "Memory (Core Foundation/Objective-C)"), TF(*tf) {}
1837 : public:
1838 :
1839 454: CFRefCount& getTF() { return TF; }
1840 : const CFRefCount& getTF() const { return TF; }
1841 :
1842 : // FIXME: Eventually remove.
1843 : virtual const char* getDescription() const = 0;
1844 :
1845 110: virtual bool isLeak() const { return false; }
1846 : };
1847 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1848 2138: class UseAfterRelease : public CFRefBug {
1849 : public:
1850 2138: UseAfterRelease(CFRefCount* tf)
1851 2138: : CFRefBug(tf, "Use-after-release") {}
1852 :
1853 35: const char* getDescription() const {
1854 35: return "Reference-counted object is used after it is released";
1855 : }
1856 : };
1857 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1858 2138: class BadRelease : public CFRefBug {
1859 : public:
1860 2138: BadRelease(CFRefCount* tf) : CFRefBug(tf, "Bad release") {}
1861 :
1862 10: const char* getDescription() const {
1863 : return "Incorrect decrement of the reference count of an object that is "
1864 10: "not owned at this point by the caller";
1865 : }
1866 : };
1867 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1868 2138: class DeallocGC : public CFRefBug {
1869 : public:
1870 2138: DeallocGC(CFRefCount *tf)
1871 2138: : CFRefBug(tf, "-dealloc called while using garbage collection") {}
1872 :
1873 0: const char *getDescription() const {
1874 0: return "-dealloc called while using garbage collection";
1875 : }
1876 : };
1877 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1878 2138: class DeallocNotOwned : public CFRefBug {
1879 : public:
1880 2138: DeallocNotOwned(CFRefCount *tf)
1881 2138: : CFRefBug(tf, "-dealloc sent to non-exclusively owned object") {}
1882 :
1883 0: const char *getDescription() const {
1884 0: return "-dealloc sent to object that may be referenced elsewhere";
1885 : }
1886 : };
1887 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1888 2138: class OverAutorelease : public CFRefBug {
1889 : public:
1890 2138: OverAutorelease(CFRefCount *tf) :
1891 2138: CFRefBug(tf, "Object sent -autorelease too many times") {}
1892 :
1893 6: const char *getDescription() const {
1894 6: return "Object sent -autorelease too many times";
1895 : }
1896 : };
1897 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1898 2138: class ReturnedNotOwnedForOwned : public CFRefBug {
1899 : public:
1900 2138: ReturnedNotOwnedForOwned(CFRefCount *tf) :
1901 2138: CFRefBug(tf, "Method should return an owned object") {}
1902 :
1903 4: const char *getDescription() const {
1904 : return "Object with +0 retain counts returned to caller where a +1 "
1905 4: "(owning) retain count is expected";
1906 : }
1907 : };
1908 :
0: branch 1 not taken
4276: branch 2 taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 9 not taken
0: branch 10 not taken
1909 4276: class Leak : public CFRefBug {
1910 : const bool isReturn;
1911 : protected:
1912 4276: Leak(CFRefCount* tf, llvm::StringRef name, bool isRet)
1913 4276: : CFRefBug(tf, name), isReturn(isRet) {}
1914 : public:
1915 :
1916 190: const char* getDescription() const { return ""; }
1917 :
1918 182: bool isLeak() const { return true; }
1919 : };
1920 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1921 2138: class LeakAtReturn : public Leak {
1922 : public:
1923 2138: LeakAtReturn(CFRefCount* tf, llvm::StringRef name)
1924 2138: : Leak(tf, name, true) {}
1925 : };
1926 :
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1927 2138: class LeakWithinFunction : public Leak {
1928 : public:
1929 2138: LeakWithinFunction(CFRefCount* tf, llvm::StringRef name)
1930 2138: : Leak(tf, name, false) {}
1931 : };
1932 :
1933 : //===---------===//
1934 : // Bug Reports. //
1935 : //===---------===//
1936 :
1937 : class CFRefReport : public RangedBugReport {
1938 : protected:
1939 : SymbolRef Sym;
1940 : const CFRefCount &TF;
1941 : public:
1942 : CFRefReport(CFRefBug& D, const CFRefCount &tf,
1943 239: ExplodedNode *n, SymbolRef sym)
1944 239: : RangedBugReport(D, D.getDescription(), n), Sym(sym), TF(tf) {}
1945 :
1946 : CFRefReport(CFRefBug& D, const CFRefCount &tf,
1947 6: ExplodedNode *n, SymbolRef sym, llvm::StringRef endText)
1948 6: : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
1949 :
55: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 9 not taken
190: branch 10 taken
1950 245: virtual ~CFRefReport() {}
1951 :
1952 746: CFRefBug& getBugType() {
1953 746: return (CFRefBug&) RangedBugReport::getBugType();
1954 : }
1955 : const CFRefBug& getBugType() const {
1956 : return (const CFRefBug&) RangedBugReport::getBugType();
1957 : }
1958 :
1959 292: virtual void getRanges(const SourceRange*& beg, const SourceRange*& end) {
110: branch 2 taken
182: branch 3 taken
1960 292: if (!getBugType().isLeak())
1961 110: RangedBugReport::getRanges(beg, end);
1962 : else
1963 182: beg = end = 0;
1964 292: }
1965 :
1966 190: SymbolRef getSymbol() const { return Sym; }
1967 :
1968 : PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
1969 : const ExplodedNode* N);
1970 :
1971 : std::pair<const char**,const char**> getExtraDescriptiveText();
1972 :
1973 : PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
1974 : const ExplodedNode* PrevN,
1975 : BugReporterContext& BRC);
1976 : };
1977 :
190: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
1978 190: class CFRefLeakReport : public CFRefReport {
1979 : SourceLocation AllocSite;
1980 : const MemRegion* AllocBinding;
1981 : public:
1982 : CFRefLeakReport(CFRefBug& D, const CFRefCount &tf,
1983 : ExplodedNode *n, SymbolRef sym,
1984 : GRExprEngine& Eng);
1985 :
1986 : PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
1987 : const ExplodedNode* N);
1988 :
1989 559: SourceLocation getLocation() const { return AllocSite; }
1990 : };
1991 : } // end anonymous namespace
1992 :
1993 :
1994 :
1995 : static const char* Msgs[] = {
1996 : // GC only
1997 : "Code is compiled to only use garbage collection",
1998 : // No GC.
1999 : "Code is compiled to use reference counts",
2000 : // Hybrid, with GC.
2001 : "Code is compiled to use either garbage collection (GC) or reference counts"
2002 : " (non-GC). The bug occurs with GC enabled",
2003 : // Hybrid, without GC
2004 : "Code is compiled to use either garbage collection (GC) or reference counts"
2005 : " (non-GC). The bug occurs in non-GC mode"
2006 : };
2007 :
2008 237: std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
2009 237: CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
2010 :
0: branch 2 not taken
20: branch 3 taken
189: branch 4 taken
28: branch 5 taken
2011 237: switch (TF.getLangOptions().getGCMode()) {
2012 : default:
2013 0: assert(false);
2014 :
2015 : case LangOptions::GCOnly:
0: branch 1 not taken
20: branch 2 taken
2016 20: assert (TF.isGCEnabled());
2017 20: return std::make_pair(&Msgs[0], &Msgs[0]+1);
2018 :
2019 : case LangOptions::NonGC:
0: branch 1 not taken
189: branch 2 taken
2020 189: assert (!TF.isGCEnabled());
2021 189: return std::make_pair(&Msgs[1], &Msgs[1]+1);
2022 :
2023 : case LangOptions::HybridGC:
9: branch 1 taken
19: branch 2 taken
2024 28: if (TF.isGCEnabled())
2025 9: return std::make_pair(&Msgs[2], &Msgs[2]+1);
2026 : else
2027 19: return std::make_pair(&Msgs[3], &Msgs[3]+1);
2028 : }
2029 : }
2030 :
2031 : static inline bool contains(const llvm::SmallVectorImpl<ArgEffect>& V,
2032 3283: ArgEffect X) {
390: branch 2 taken
3267: branch 3 taken
2033 3657: for (llvm::SmallVectorImpl<ArgEffect>::const_iterator I=V.begin(), E=V.end();
2034 : I!=E; ++I)
16: branch 0 taken
374: branch 1 taken
2035 390: if (*I == X) return true;
2036 :
2037 3267: return false;
2038 : }
2039 :
2040 : PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N,
2041 : const ExplodedNode* PrevN,
2042 4380: BugReporterContext& BRC) {
2043 :
514: branch 2 taken
3866: branch 3 taken
2044 4380: if (!isa<PostStmt>(N->getLocation()))
2045 514: return NULL;
2046 :
2047 : // Check if the type state has changed.
2048 3866: const GRState *PrevSt = PrevN->getState();
2049 3866: const GRState *CurrSt = N->getState();
2050 :
2051 3866: const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
1916: branch 0 taken
1950: branch 1 taken
2052 3866: if (!CurrT) return NULL;
2053 :
2054 1950: const RefVal &CurrV = *CurrT;
2055 1950: const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
2056 :
2057 : // Create a string buffer to constain all the useful things we want
2058 : // to tell the user.
2059 1950: std::string sbuf;
2060 1950: llvm::raw_string_ostream os(sbuf);
2061 :
2062 : // This is the allocation site since the previous node had no bindings
2063 : // for this symbol.
237: branch 0 taken
1713: branch 1 taken
2064 1950: if (!PrevT) {
2065 237: const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2066 :
129: branch 1 taken
108: branch 2 taken
2067 237: if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2068 : // Get the name of the callee (if it is available).
2069 129: SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
129: branch 1 taken
0: branch 2 not taken
2070 129: if (const FunctionDecl* FD = X.getAsFunctionDecl())
2071 129: os << "Call to function '" << FD->getNameAsString() <<'\'';
2072 : else
2073 0: os << "function call";
2074 : }
2075 : else {
0: branch 1 not taken
108: branch 2 taken
2076 108: assert (isa<ObjCMessageExpr>(S));
2077 108: os << "Method";
2078 : }
2079 :
143: branch 1 taken
94: branch 2 taken
2080 237: if (CurrV.getObjKind() == RetEffect::CF) {
2081 143: os << " returns a Core Foundation object with a ";
2082 : }
2083 : else {
0: branch 1 not taken
94: branch 2 taken
2084 94: assert (CurrV.getObjKind() == RetEffect::ObjC);
2085 94: os << " returns an Objective-C object with a ";
2086 : }
2087 :
217: branch 1 taken
20: branch 2 taken
2088 237: if (CurrV.isOwned()) {
2089 217: os << "+1 retain count (owning reference).";
2090 :
27: branch 3 taken
190: branch 4 taken
2091 217: if (static_cast<CFRefBug&>(getBugType()).getTF().isGCEnabled()) {
0: branch 1 not taken
27: branch 2 taken
2092 27: assert(CurrV.getObjKind() == RetEffect::CF);
2093 : os << " "
2094 27: "Core Foundation objects are not automatically garbage collected.";
2095 : }
2096 : }
2097 : else {
0: branch 1 not taken
20: branch 2 taken
2098 20: assert (CurrV.isNotOwned());
2099 20: os << "+0 retain count (non-owning reference).";
2100 : }
2101 :
2102 237: PathDiagnosticLocation Pos(S, BRC.getSourceManager());
2103 237: return new PathDiagnosticEventPiece(Pos, os.str());
2104 : }
2105 :
2106 : // Gather up the effects that were performed on the object at this
2107 : // program point
2108 1713: llvm::SmallVector<ArgEffect, 2> AEffects;
2109 :
294: branch 0 taken
1419: branch 1 taken
2110 1713: if (const RetainSummary *Summ =
2111 1713: TF.getSummaryOfNode(BRC.getNodeResolver().getOriginalNode(N))) {
2112 : // We only have summaries attached to nodes after evaluating CallExpr and
2113 : // ObjCMessageExprs.
2114 294: const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2115 :
114: branch 1 taken
180: branch 2 taken
2116 294: if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2117 : // Iterate through the parameter expressions and see if the symbol
2118 : // was ever passed as an argument.
2119 114: unsigned i = 0;
2120 :
176: branch 4 taken
114: branch 5 taken
2121 290: for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
2122 : AI!=AE; ++AI, ++i) {
2123 :
2124 : // Retrieve the value of the argument. Is it the symbol
2125 : // we are interested in?
76: branch 4 taken
100: branch 5 taken
2126 176: if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
2127 76: continue;
2128 :
2129 : // We have an argument. Get the effect!
2130 100: AEffects.push_back(Summ->getArg(i));
2131 : }
2132 : }
180: branch 1 taken
0: branch 2 not taken
2133 180: else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
160: branch 1 taken
20: branch 2 taken
2134 180: if (const Expr *receiver = ME->getReceiver())
110: branch 3 taken
50: branch 4 taken
2135 160: if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
2136 : // The symbol we are tracking is the receiver.
2137 110: AEffects.push_back(Summ->getReceiverEffect());
2138 : }
2139 : }
2140 : }
2141 :
2142 : do {
2143 : // Get the previous type state.
2144 1713: RefVal PrevV = *PrevT;
2145 :
2146 : // Specially handle -dealloc.
1572: branch 1 taken
141: branch 2 taken
2: branch 4 taken
1570: branch 5 taken
2: branch 6 taken
1711: branch 7 taken
2147 1713: if (!TF.isGCEnabled() && contains(AEffects, Dealloc)) {
2148 : // Determine if the object's reference count was pushed to zero.
2: branch 1 taken
0: branch 2 not taken
2149 2: assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
2150 : // We may not have transitioned to 'release' if we hit an error.
2151 : // This case is handled elsewhere.
2: branch 1 taken
0: branch 2 not taken
2152 2: if (CurrV.getKind() == RefVal::Released) {
0: branch 1 not taken
2: branch 2 taken
2153 2: assert(CurrV.getCombinedCounts() == 0);
2154 2: os << "Object released by directly sending the '-dealloc' message";
2155 2: break;
2156 : }
2157 : }
2158 :
2159 : // Specially handle CFMakeCollectable and friends.
14: branch 1 taken
1697: branch 2 taken
2160 1711: if (contains(AEffects, MakeCollectable)) {
2161 : // Get the name of the function.
2162 14: const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2163 14: SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
2164 14: const FunctionDecl* FD = X.getAsFunctionDecl();
2165 14: const std::string& FName = FD->getNameAsString();
2166 :
4: branch 1 taken
10: branch 2 taken
2167 14: if (TF.isGCEnabled()) {
2168 : // Determine if the object's reference count was pushed to zero.
4: branch 1 taken
0: branch 2 not taken
2169 4: assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
2170 :
2171 : os << "In GC mode a call to '" << FName
2172 : << "' decrements an object's retain count and registers the "
2173 4: "object with the garbage collector. ";
2174 :
4: branch 1 taken
0: branch 2 not taken
2175 4: if (CurrV.getKind() == RefVal::Released) {
0: branch 1 not taken
4: branch 2 taken
2176 4: assert(CurrV.getCount() == 0);
2177 : os << "Since it now has a 0 retain count the object can be "
2178 4: "automatically collected by the garbage collector.";
2179 : }
2180 : else
2181 : os << "An object must have a 0 retain count to be garbage collected. "
2182 : "After this call its retain count is +" << CurrV.getCount()
2183 0: << '.';
2184 : }
2185 : else
2186 : os << "When GC is not enabled a call to '" << FName
2187 10: << "' has no effect on its argument.";
2188 :
2189 : // Nothing more to say.
2190 14: break;
2191 : }
2192 :
2193 : // Determine if the typestate has changed.
191: branch 1 taken
1506: branch 2 taken
2194 1697: if (!(PrevV == CurrV))
120: branch 1 taken
33: branch 2 taken
34: branch 3 taken
4: branch 4 taken
0: branch 5 not taken
2195 191: switch (CurrV.getKind()) {
2196 : case RefVal::Owned:
2197 : case RefVal::NotOwned:
2198 :
30: branch 2 taken
90: branch 3 taken
2199 120: if (PrevV.getCount() == CurrV.getCount()) {
2200 : // Did an autorelease message get sent?
8: branch 2 taken
22: branch 3 taken
2201 30: if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2202 8: return 0;
2203 :
0: branch 2 not taken
22: branch 3 taken
2204 22: assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2205 22: os << "Object sent -autorelease message";
2206 22: break;
2207 : }
2208 :
26: branch 2 taken
64: branch 3 taken
2209 90: if (PrevV.getCount() > CurrV.getCount())
2210 26: os << "Reference count decremented.";
2211 : else
2212 64: os << "Reference count incremented.";
2213 :
84: branch 1 taken
6: branch 2 taken
2214 90: if (unsigned Count = CurrV.getCount())
2215 84: os << " The object now has a +" << Count << " retain count.";
2216 :
4: branch 1 taken
86: branch 2 taken
2217 90: if (PrevV.getKind() == RefVal::Released) {
4: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
4: branch 5 taken
2218 4: assert(TF.isGCEnabled() && CurrV.getCount() > 0);
2219 : os << " The object is not eligible for garbage collection until the "
2220 4: "retain count reaches 0 again.";
2221 : }
2222 :
2223 90: break;
2224 :
2225 : case RefVal::Released:
2226 33: os << "Object released.";
2227 33: break;
2228 :
2229 : case RefVal::ReturnedOwned:
2230 : os << "Object returned to caller as an owning reference (single retain "
2231 34: "count transferred to caller).";
2232 34: break;
2233 :
2234 : case RefVal::ReturnedNotOwned:
2235 4: os << "Object returned to caller with a +0 (non-owning) retain count.";
2236 4: break;
2237 :
2238 : default:
2239 0: return NULL;
2240 : }
2241 :
2242 : // Emit any remaining diagnostics for the argument effects (if any).
188: branch 1 taken
1689: branch 2 taken
2243 3566: for (llvm::SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
2244 1689: E=AEffects.end(); I != E; ++I) {
2245 :
2246 : // A bunch of things have alternate behavior under GC.
24: branch 1 taken
164: branch 2 taken
2247 188: if (TF.isGCEnabled())
6: branch 0 taken
2: branch 1 taken
7: branch 2 taken
9: branch 3 taken
2248 24: switch (*I) {
2249 6: default: break;
2250 : case Autorelease:
2251 2: os << "In GC mode an 'autorelease' has no effect.";
2252 2: continue;
2253 : case IncRefMsg:
2254 7: os << "In GC mode the 'retain' message has no effect.";
2255 7: continue;
2256 : case DecRefMsg:
2257 9: os << "In GC mode the 'release' message has no effect.";
2258 9: continue;
2259 : }
2260 : }
2261 : } while (0);
2262 :
1488: branch 2 taken
217: branch 3 taken
2263 1705: if (os.str().empty())
2264 1488: return 0; // We have nothing to say!
2265 :
2266 217: const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2267 217: PathDiagnosticLocation Pos(S, BRC.getSourceManager());
2268 217: PathDiagnosticPiece* P = new PathDiagnosticEventPiece(Pos, os.str());
2269 :
2270 : // Add the range by scanning the children of the statement for any bindings
2271 : // to Sym.
300: branch 4 taken
0: branch 5 not taken
2272 300: for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
2273 : I!=E; ++I)
300: branch 2 taken
0: branch 3 not taken
2274 300: if (const Expr* Exp = dyn_cast_or_null<Expr>(*I))
217: branch 3 taken
83: branch 4 taken
2275 300: if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
2276 217: P->addRange(Exp->getSourceRange());
2277 217: break;
2278 : }
2279 :
2280 217: return P;
2281 : }
2282 :
2283 : namespace {
2284 : class FindUniqueBinding :
0: branch 1 not taken
0: branch 2 not taken
0: branch 5 not taken
3178: branch 6 taken
2285 3178: public StoreManager::BindingsHandler {
2286 : SymbolRef Sym;
2287 : const MemRegion* Binding;
2288 : bool First;
2289 :
2290 : public:
2291 3178: FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {}
2292 :
2293 : bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
2294 2507: SVal val) {
2295 :
2296 2507: SymbolRef SymV = val.getAsSymbol();
2413: branch 0 taken
94: branch 1 taken
1782: branch 2 taken
631: branch 3 taken
2297 2507: if (!SymV || SymV != Sym)
2298 1876: return true;
2299 :
0: branch 0 not taken
631: branch 1 taken
2300 631: if (Binding) {
2301 0: First = false;
2302 0: return false;
2303 : }
2304 : else
2305 631: Binding = R;
2306 :
2307 631: return true;
2308 : }
2309 :
3178: branch 0 taken
0: branch 1 not taken
631: branch 2 taken
2547: branch 3 taken
2310 3178: operator bool() { return First && Binding; }
2311 631: const MemRegion* getRegion() { return Binding; }
2312 : };
2313 : }
2314 :
2315 : static std::pair<const ExplodedNode*,const MemRegion*>
2316 : GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode* N,
2317 372: SymbolRef Sym) {
2318 :
2319 : // Find both first node that referred to the tracked symbol and the
2320 : // memory location that value was store to.
2321 372: const ExplodedNode* Last = N;
2322 372: const MemRegion* FirstBinding = 0;
2323 :
3550: branch 1 taken
0: branch 2 not taken
2324 3550: while (N) {
2325 3550: const GRState* St = N->getState();
2326 3550: RefBindings B = St->get<RefBindings>();
2327 :
372: branch 1 taken
3178: branch 2 taken
2328 3550: if (!B.lookup(Sym))
2329 372: break;
2330 :
2331 3178: FindUniqueBinding FB(Sym);
2332 3178: StateMgr.iterBindings(St, FB);
631: branch 1 taken
2547: branch 2 taken
2333 3178: if (FB) FirstBinding = FB.getRegion();
2334 :
2335 3178: Last = N;
0: branch 1 not taken
3178: branch 2 taken
2336 3178: N = N->pred_empty() ? NULL : *(N->pred_begin());
2337 : }
2338 :
2339 372: return std::make_pair(Last, FirstBinding);
2340 : }
2341 :
2342 : PathDiagnosticPiece*
2343 : CFRefReport::getEndPath(BugReporterContext& BRC,
2344 55: const ExplodedNode* EndN) {
2345 : // Tell the BugReporterContext to report cases when the tracked symbol is
2346 : // assigned to different variables, etc.
2347 55: BRC.addNotableSymbol(Sym);
2348 55: return RangedBugReport::getEndPath(BRC, EndN);
2349 : }
2350 :
2351 : PathDiagnosticPiece*
2352 : CFRefLeakReport::getEndPath(BugReporterContext& BRC,
2353 182: const ExplodedNode* EndN){
2354 :
2355 : // Tell the BugReporterContext to report cases when the tracked symbol is
2356 : // assigned to different variables, etc.
2357 182: BRC.addNotableSymbol(Sym);
2358 :
2359 : // We are reporting a leak. Walk up the graph to get to the first node where
2360 : // the symbol appeared, and also get the first VarDecl that tracked object
2361 : // is stored to.
2362 182: const ExplodedNode* AllocNode = 0;
2363 182: const MemRegion* FirstBinding = 0;
2364 :
2365 : llvm::tie(AllocNode, FirstBinding) =
2366 182: GetAllocationSite(BRC.getStateManager(), EndN, Sym);
2367 :
2368 : // Get the allocate site.
0: branch 0 not taken
182: branch 1 taken
2369 182: assert(AllocNode);
2370 182: const Stmt* FirstStmt = cast<PostStmt>(AllocNode->getLocation()).getStmt();
2371 :
2372 182: SourceManager& SMgr = BRC.getSourceManager();
2373 182: unsigned AllocLine =SMgr.getInstantiationLineNumber(FirstStmt->getLocStart());
2374 :
2375 : // Compute an actual location for the leak. Sometimes a leak doesn't
2376 : // occur at an actual statement (e.g., transition between blocks; end
2377 : // of function) so we need to walk the graph and compute a real location.
2378 182: const ExplodedNode* LeakN = EndN;
2379 182: PathDiagnosticLocation L;
2380 :
182: branch 0 taken
123: branch 1 taken
2381 487: while (LeakN) {
2382 182: ProgramPoint P = LeakN->getLocation();
2383 :
59: branch 1 taken
123: branch 2 taken
2384 182: if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
2385 59: L = PathDiagnosticLocation(PS->getStmt()->getLocStart(), SMgr);
2386 59: break;
2387 : }
0: branch 1 not taken
123: branch 2 taken
2388 123: else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
0: branch 2 not taken
0: branch 3 not taken
2389 0: if (const Stmt* Term = BE->getSrc()->getTerminator()) {
2390 0: L = PathDiagnosticLocation(Term->getLocStart(), SMgr);
2391 0: break;
2392 : }
2393 : }
2394 :
123: branch 1 taken
0: branch 2 not taken
2395 123: LeakN = LeakN->succ_empty() ? 0 : *(LeakN->succ_begin());
2396 : }
2397 :
123: branch 1 taken
59: branch 2 taken
2398 182: if (!L.isValid()) {
2399 123: const Decl &D = EndN->getCodeDecl();
2400 123: L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr);
2401 : }
2402 :
2403 182: std::string sbuf;
2404 182: llvm::raw_string_ostream os(sbuf);
2405 :
2406 182: os << "Object allocated on line " << AllocLine;
2407 :
40: branch 0 taken
142: branch 1 taken
2408 182: if (FirstBinding)
2409 40: os << " and stored into '" << FirstBinding->getString() << '\'';
2410 :
2411 : // Get the retain count.
2412 182: const RefVal* RV = EndN->getState()->get<RefBindings>(Sym);
2413 :
16: branch 1 taken
166: branch 2 taken
2414 182: if (RV->getKind() == RefVal::ErrorLeakReturned) {
2415 : // FIXME: Per comments in rdar://6320065, "create" only applies to CF
2416 : // ojbects. Only "copy", "alloc", "retain" and "new" transfer ownership
2417 : // to the caller for NS objects.
2418 16: ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
2419 : os << " is returned from a method whose name ('"
2420 : << MD.getSelector().getAsString()
2421 : << "') does not contain 'copy' or otherwise starts with"
2422 : " 'new' or 'alloc'. This violates the naming convention rules given"
2423 16: " in the Memory Management Guide for Cocoa (object leaked)";
2424 : }
6: branch 1 taken
160: branch 2 taken
2425 166: else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2426 6: ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
2427 : os << " and returned from method '" << MD.getSelector().getAsString()
2428 : << "' is potentially leaked when using garbage collection. Callers "
2429 : "of this method do not expect a returned object with a +1 retain "
2430 : "count since they expect the object to be managed by the garbage "
2431 6: "collector";
2432 : }
2433 : else
2434 : os << " is no longer referenced after this point and has a retain count of"
2435 160: " +" << RV->getCount() << " (object leaked)";
2436 :
2437 182: return new PathDiagnosticEventPiece(L, os.str());
2438 : }
2439 :
2440 : CFRefLeakReport::CFRefLeakReport(CFRefBug& D, const CFRefCount &tf,
2441 : ExplodedNode *n,
2442 190: SymbolRef sym, GRExprEngine& Eng)
2443 190: : CFRefReport(D, tf, n, sym) {
2444 :
2445 : // Most bug reports are cached at the location where they occured.
2446 : // With leaks, we want to unique them by the location where they were
2447 : // allocated, and only report a single path. To do this, we need to find
2448 : // the allocation site of a piece of tracked memory, which we do via a
2449 : // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
2450 : // Note that this is *not* the trimmed graph; we are guaranteed, however,
2451 : // that all ancestor nodes that represent the allocation site have the
2452 : // same SourceLocation.
2453 190: const ExplodedNode* AllocNode = 0;
2454 :
2455 : llvm::tie(AllocNode, AllocBinding) = // Set AllocBinding.
2456 190: GetAllocationSite(Eng.getStateManager(), getEndNode(), getSymbol());
2457 :
2458 : // Get the SourceLocation for the allocation site.
2459 190: ProgramPoint P = AllocNode->getLocation();
2460 190: AllocSite = cast<PostStmt>(P).getStmt()->getLocStart();
2461 :
2462 : // Fill in the description of the bug.
2463 190: Description.clear();
2464 190: llvm::raw_string_ostream os(Description);
2465 190: SourceManager& SMgr = Eng.getContext().getSourceManager();
2466 190: unsigned AllocLine = SMgr.getInstantiationLineNumber(AllocSite);
2467 190: os << "Potential leak ";
29: branch 1 taken
161: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
2468 190: if (tf.isGCEnabled()) {
2469 29: os << "(when using garbage collection) ";
2470 : }
2471 190: os << "of an object allocated on line " << AllocLine;
2472 :
2473 : // FIXME: AllocBinding doesn't get populated for RegionStore yet.
44: branch 0 taken
146: branch 1 taken
146: branch 2 taken
146: branch 3 taken
2474 190: if (AllocBinding)
2475 44: os << " and stored into '" << AllocBinding->getString() << '\'';
2476 190: }
2477 :
2478 : //===----------------------------------------------------------------------===//
2479 : // Main checker logic.
2480 : //===----------------------------------------------------------------------===//
2481 :
2482 : /// GetReturnType - Used to get the return type of a message expression or
2483 : /// function call with the intention of affixing that type to a tracked symbol.
2484 : /// While the the return type can be queried directly from RetEx, when
2485 : /// invoking class methods we augment to the return type to be that of
2486 : /// a pointer to the class (as opposed it just being id).
2487 899: static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
2488 899: QualType RetTy = RetE->getType();
2489 : // If RetE is not a message expression just return its type.
2490 : // If RetE is a message expression, return its types if it is something
2491 : /// more specific than id.
614: branch 1 taken
285: branch 2 taken
2492 899: if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
604: branch 2 taken
10: branch 3 taken
2493 614: if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
604: branch 1 taken
0: branch 2 not taken
76: branch 4 taken
528: branch 5 taken
6: branch 7 taken
70: branch 8 taken
534: branch 9 taken
70: branch 10 taken
2494 604: if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2495 : PT->isObjCClassType()) {
2496 : // At this point we know the return type of the message expression is
2497 : // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
2498 : // is a call to a class method whose type we can resolve. In such
2499 : // cases, promote the return type to XXX* (where XXX is the class).
2500 534: const ObjCInterfaceDecl *D = ME->getClassInfo().first;
258: branch 0 taken
276: branch 1 taken
2501 534: return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D));
2502 : }
2503 :
2504 365: return RetTy;
2505 : }
2506 :
2507 : void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
2508 : GRExprEngine& Eng,
2509 : GRStmtNodeBuilder& Builder,
2510 : Expr* Ex,
2511 : Expr* Receiver,
2512 : const RetainSummary& Summ,
2513 : const MemRegion *Callee,
2514 : ExprIterator arg_beg, ExprIterator arg_end,
2515 2731: ExplodedNode* Pred, const GRState *state) {
2516 :
2517 : // Evaluate the effect of the arguments.
2518 2731: RefVal::Kind hasErr = (RefVal::Kind) 0;
2519 2731: unsigned idx = 0;
2520 2731: Expr* ErrorExpr = NULL;
2521 2731: SymbolRef ErrorSym = 0;
2522 :
2523 2731: llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
2524 :
1189: branch 1 taken
29: branch 2 taken
1263: branch 3 taken
2481: branch 6 taken
2702: branch 7 taken
2525 7664: for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
2526 2481: SVal V = state->getSValAsScalarOrLoc(*I);
2527 2481: SymbolRef Sym = V.getAsLocSymbol();
2528 :
883: branch 0 taken
1598: branch 1 taken
2529 2481: if (Sym)
471: branch 1 taken
412: branch 2 taken
2530 883: if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
2531 471: state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
29: branch 0 taken
442: branch 1 taken
2532 471: if (hasErr) {
2533 29: ErrorExpr = *I;
2534 29: ErrorSym = Sym;
2535 29: break;
2536 : }
2537 1263: continue;
2538 : }
2539 :
2540 2020: tryAgain:
1118: branch 1 taken
902: branch 2 taken
2541 2020: if (isa<Loc>(V)) {
821: branch 1 taken
297: branch 2 taken
2542 1118: if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(&V)) {
8: branch 1 taken
813: branch 2 taken
2543 821: if (Summ.getArg(idx) == DoNothingByRef)
2544 : continue;
2545 :
2546 : // Invalidate the value of the variable passed by reference.
2547 813: const MemRegion *R = MR->getRegion();
2548 :
2549 : // Are we dealing with an ElementRegion? If the element type is
2550 : // a basic integer type (e.g., char, int) and the underying region
2551 : // is a variable region then strip off the ElementRegion.
2552 : // FIXME: We really need to think about this for the general case
2553 : // as sometimes we are reasoning about arrays and other times
2554 : // about (char*), etc., is just a form of passing raw bytes.
2555 : // e.g., void *p = alloca(); foo((char*)p);
289: branch 1 taken
524: branch 2 taken
2556 813: if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
2557 : // Checking for 'integral type' is probably too promiscuous, but
2558 : // we'll leave it in for now until we have a systematic way of
2559 : // handling all of these cases. Eventually we need to come up
2560 : // with an interface to StoreManager so that this logic can be
2561 : // approriately delegated to the respective StoreManagers while
2562 : // still allowing us to do checker-specific logic (e.g.,
2563 : // invalidating reference counts), probably via callbacks.
166: branch 3 taken
123: branch 4 taken
2564 289: if (ER->getElementType()->isIntegralType()) {
2565 166: const MemRegion *superReg = ER->getSuperRegion();
134: branch 1 taken
32: branch 2 taken
122: branch 4 taken
12: branch 5 taken
0: branch 7 not taken
122: branch 8 taken
44: branch 9 taken
122: branch 10 taken
2566 166: if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
2567 : isa<ObjCIvarRegion>(superReg))
2568 44: R = cast<TypedRegion>(superReg);
2569 : }
2570 : // FIXME: What about layers of ElementRegions?
2571 : }
2572 :
2573 : // Mark this region for invalidation. We batch invalidate regions
2574 : // below for efficiency.
2575 813: RegionsToInvalidate.push_back(R);
2576 : continue;
2577 : }
2578 : else {
2579 : // Nuke all other arguments passed by reference.
2580 : // FIXME: is this necessary or correct? This handles the non-Region
2581 : // cases. Is it ever valid to store to these?
2582 297: state = state->unbindLoc(cast<Loc>(V));
2583 : }
2584 : }
10: branch 1 taken
892: branch 2 taken
2585 902: else if (isa<nonloc::LocAsInteger>(V)) {
2586 : // If we are passing a location wrapped as an integer, unwrap it and
2587 : // invalidate the values referred by the location.
2588 10: V = cast<nonloc::LocAsInteger>(V).getLoc();
2589 10: goto tryAgain;
2590 : }
2591 : }
2592 :
2593 : // Block calls result in all captured values passed-via-reference to be
2594 : // invalidated.
48: branch 1 taken
2683: branch 2 taken
2595 2731: if (const BlockDataRegion *BR = dyn_cast_or_null<BlockDataRegion>(Callee)) {
2596 48: RegionsToInvalidate.push_back(BR);
2597 : }
2598 :
2599 : // Invalidate regions we designed for invalidation use the batch invalidation
2600 : // API.
677: branch 1 taken
2054: branch 2 taken
2601 2731: if (!RegionsToInvalidate.empty()) {
2602 : // FIXME: We can have collisions on the conjured symbol if the
2603 : // expression *I also creates conjured symbols. We probably want
2604 : // to identify conjured symbols by an expression pair: the enclosing
2605 : // expression (the context) and the expression itself. This should
2606 : // disambiguate conjured symbols.
2607 677: unsigned Count = Builder.getCurrentBlockCount();
2608 677: StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
2609 :
2610 :
2611 677: StoreManager::InvalidatedSymbols IS;
2612 677: Store store = state->getStore();
2613 : store = StoreMgr.InvalidateRegions(store, RegionsToInvalidate.data(),
2614 : RegionsToInvalidate.data() +
2615 : RegionsToInvalidate.size(),
2616 677: Ex, Count, &IS);
2617 677: state = state->makeWithStore(store);
291: branch 3 taken
677: branch 4 taken
2618 1645: for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
2619 677: E = IS.end(); I!=E; ++I) {
2620 : // Remove any existing reference-count binding.
2621 291: state = state->remove<RefBindings>(*I);
2622 677: }
2623 : }
2624 :
2625 : // Evaluate the effect on the message receiver.
2702: branch 0 taken
29: branch 1 taken
846: branch 2 taken
1856: branch 3 taken
2626 2731: if (!ErrorExpr && Receiver) {
2627 846: SymbolRef Sym = state->getSValAsScalarOrLoc(Receiver).getAsLocSymbol();
809: branch 0 taken
37: branch 1 taken
2628 846: if (Sym) {
577: branch 1 taken
232: branch 2 taken
2629 809: if (const RefVal* T = state->get<RefBindings>(Sym)) {
2630 577: state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
16: branch 0 taken
561: branch 1 taken
2631 577: if (hasErr) {
2632 16: ErrorExpr = Receiver;
2633 16: ErrorSym = Sym;
2634 : }
2635 : }
2636 : }
2637 : }
2638 :
2639 : // Process any errors.
45: branch 0 taken
2686: branch 1 taken
2640 2731: if (hasErr) {
2641 : ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, state,
2642 45: hasErr, ErrorSym);
2643 45: return;
2644 : }
2645 :
2646 : // Consult the summary for the return value.
2647 2686: RetEffect RE = Summ.getRetEffect();
2648 :
265: branch 1 taken
2421: branch 2 taken
2649 2686: if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
0: branch 0 not taken
265: branch 1 taken
2650 265: assert(Receiver);
2651 265: SVal V = state->getSValAsScalarOrLoc(Receiver);
2652 265: bool found = false;
245: branch 1 taken
20: branch 2 taken
2653 265: if (SymbolRef Sym = V.getAsLocSymbol())
212: branch 1 taken
33: branch 2 taken
2654 245: if (state->get<RefBindings>(Sym)) {
2655 212: found = true;
2656 212: RE = Summaries.getObjAllocRetEffect();
2657 : }
2658 :
53: branch 0 taken
212: branch 1 taken
2659 265: if (!found)
2660 53: RE = RetEffect::MakeNoRet();
2661 : }
2662 :
0: branch 1 not taken
1317: branch 2 taken
136: branch 3 taken
334: branch 4 taken
741: branch 5 taken
158: branch 6 taken
2663 2686: switch (RE.getKind()) {
2664 : default:
2665 0: assert (false && "Unhandled RetEffect."); break;
2666 :
2667 : case RetEffect::NoRet: {
2668 : // Make up a symbol for the return value (not reference counted).
2669 : // FIXME: Most of this logic is not specific to the retain/release
2670 : // checker.
2671 :
2672 : // FIXME: We eventually should handle structs and other compound types
2673 : // that are returned by value.
2674 :
2675 1317: QualType T = Ex->getType();
2676 :
2677 : // For CallExpr, use the result type to know if it returns a reference.
1070: branch 1 taken
247: branch 2 taken
2678 1317: if (const CallExpr *CE = dyn_cast<CallExpr>(Ex)) {
2679 1070: const Expr *Callee = CE->getCallee();
1014: branch 3 taken
56: branch 4 taken
2680 1070: if (const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl())
2681 1014: T = FD->getResultType();
2682 : }
247: branch 1 taken
0: branch 2 not taken
2683 247: else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Ex)) {
247: branch 1 taken
0: branch 2 not taken
2684 247: if (const ObjCMethodDecl *MD = ME->getMethodDecl())
2685 247: T = MD->getResultType();
2686 : }
2687 :
944: branch 1 taken
373: branch 2 taken
244: branch 5 taken
700: branch 6 taken
244: branch 9 taken
0: branch 10 not taken
617: branch 11 taken
700: branch 12 taken
2688 1317: if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
2689 617: unsigned Count = Builder.getCurrentBlockCount();
2690 617: ValueManager &ValMgr = Eng.getValueManager();
2691 617: SVal X = ValMgr.getConjuredSymbolVal(NULL, Ex, T, Count);
2692 617: state = state->BindExpr(Ex, X, false);
2693 : }
2694 :
2695 1317: break;
2696 : }
2697 :
2698 : case RetEffect::Alias: {
2699 136: unsigned idx = RE.getIndex();
0: branch 1 not taken
136: branch 2 taken
2700 136: assert (arg_end >= arg_beg);
0: branch 1 not taken
136: branch 2 taken
2701 136: assert (idx < (unsigned) (arg_end - arg_beg));
2702 136: SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx));
2703 136: state = state->BindExpr(Ex, V, false);
2704 136: break;
2705 : }
2706 :
2707 : case RetEffect::ReceiverAlias: {
0: branch 0 not taken
334: branch 1 taken
2708 334: assert (Receiver);
2709 334: SVal V = state->getSValAsScalarOrLoc(Receiver);
2710 334: state = state->BindExpr(Ex, V, false);
2711 334: break;
2712 : }
2713 :
2714 : case RetEffect::OwnedAllocatedSymbol:
2715 : case RetEffect::OwnedSymbol: {
2716 741: unsigned Count = Builder.getCurrentBlockCount();
2717 741: ValueManager &ValMgr = Eng.getValueManager();
2718 741: SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
2719 741: QualType RetT = GetReturnType(Ex, ValMgr.getContext());
2720 : state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
2721 741: RetT));
2722 741: state = state->BindExpr(Ex, ValMgr.makeLoc(Sym), false);
2723 :
2724 : // FIXME: Add a flag to the checker where allocations are assumed to
2725 : // *not fail.
2726 : #if 0
2727 : if (RE.getKind() == RetEffect::OwnedAllocatedSymbol) {
2728 : bool isFeasible;
2729 : state = state.Assume(loc::SymbolVal(Sym), true, isFeasible);
2730 : assert(isFeasible && "Cannot assume fresh symbol is non-null.");
2731 : }
2732 : #endif
2733 :
2734 741: break;
2735 : }
2736 :
2737 : case RetEffect::GCNotOwnedSymbol:
2738 : case RetEffect::NotOwnedSymbol: {
2739 158: unsigned Count = Builder.getCurrentBlockCount();
2740 158: ValueManager &ValMgr = Eng.getValueManager();
2741 158: SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
2742 158: QualType RetT = GetReturnType(Ex, ValMgr.getContext());
2743 : state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
2744 158: RetT));
2745 158: state = state->BindExpr(Ex, ValMgr.makeLoc(Sym), false);
2746 : break;
2747 : }
2748 : }
2749 :
2750 : // Generate a sink node if we are at the end of a path.
2751 : ExplodedNode *NewNode =
2752 : Summ.isEndPath() ? Builder.MakeSinkNode(Dst, Ex, Pred, state)
8: branch 1 taken
2678: branch 2 taken
2753 2686: : Builder.MakeNode(Dst, Ex, Pred, state);
2754 :
2755 : // Annotate the edge with summary we used.
2686: branch 0 taken
0: branch 1 not taken
2686: branch 4 taken
45: branch 5 taken
2756 2686: if (NewNode) SummaryLog[NewNode] = &Summ;
2757 : }
2758 :
2759 :
2760 : void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
2761 : GRExprEngine& Eng,
2762 : GRStmtNodeBuilder& Builder,
2763 : CallExpr* CE, SVal L,
2764 1520: ExplodedNode* Pred) {
2765 :
2766 1520: RetainSummary *Summ = 0;
2767 :
2768 : // FIXME: Better support for blocks. For now we stop tracking anything
2769 : // that is passed to blocks.
2770 : // FIXME: Need to handle variables that are "captured" by the block.
48: branch 2 taken
1472: branch 3 taken
2771 1520: if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
2772 48: Summ = Summaries.getPersistentStopSummary();
2773 : }
2774 : else {
2775 1472: const FunctionDecl* FD = L.getAsFunctionDecl();
2776 : Summ = !FD ? Summaries.getDefaultSummary() :
8: branch 0 taken
1464: branch 1 taken
2777 1472: Summaries.getSummary(const_cast<FunctionDecl*>(FD));
2778 : }
2779 :
0: branch 0 not taken
1520: branch 1 taken
2780 1520: assert(Summ);
2781 : EvalSummary(Dst, Eng, Builder, CE, 0, *Summ, L.getAsRegion(),
2782 1520: CE->arg_begin(), CE->arg_end(), Pred, Builder.GetState(Pred));
2783 1520: }
2784 :
2785 : void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst,
2786 : GRExprEngine& Eng,
2787 : GRStmtNodeBuilder& Builder,
2788 : ObjCMessageExpr* ME,
2789 : ExplodedNode* Pred,
2790 1211: const GRState *state) {
2791 : RetainSummary *Summ =
2792 : ME->getReceiver()
2793 : ? Summaries.getInstanceMethodSummary(ME, state,Pred->getLocationContext())
846: branch 1 taken
365: branch 2 taken
2794 1211: : Summaries.getClassMethodSummary(ME);
2795 :
0: branch 0 not taken
1211: branch 1 taken
2796 1211: assert(Summ && "RetainSummary is null");
2797 : EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), *Summ, NULL,
2798 1211: ME->arg_begin(), ME->arg_end(), Pred, state);
2799 1211: }
2800 :
2801 : namespace {
0: branch 1 not taken
0: branch 2 not taken
0: branch 5 not taken
687: branch 6 taken
2802 687: class StopTrackingCallback : public SymbolVisitor {
2803 : const GRState *state;
2804 : public:
2805 687: StopTrackingCallback(const GRState *st) : state(st) {}
2806 687: const GRState *getState() const { return state; }
2807 :
2808 214: bool VisitSymbol(SymbolRef sym) {
2809 214: state = state->remove<RefBindings>(sym);
2810 214: return true;
2811 : }
2812 : };
2813 : } // end anonymous namespace
2814 :
2815 :
2816 3973: void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
2817 : // Are we storing to something that causes the value to "escape"?
2818 3973: bool escapes = false;
2819 :
2820 : // A value escapes in three possible cases (this may change):
2821 : //
2822 : // (1) we are binding to something that is not a memory region.
2823 : // (2) we are binding to a memregion that does not have stack storage
2824 : // (3) we are binding to a memregion with stack storage that the store
2825 : // does not understand.
2826 3973: const GRState *state = B.getState();
2827 :
50: branch 1 taken
3923: branch 2 taken
2828 3973: if (!isa<loc::MemRegionVal>(location))
2829 50: escapes = true;
2830 : else {
2831 3923: const MemRegion* R = cast<loc::MemRegionVal>(location).getRegion();
2832 3923: escapes = !R->hasStackStorage();
2833 :
3568: branch 0 taken
355: branch 1 taken
2834 3923: if (!escapes) {
2835 : // To test (3), generate a new state with the binding removed. If it is
2836 : // the same state, then it escapes (since the store cannot represent
2837 : // the binding).
2838 3568: escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal())));
2839 : }
2840 : }
2841 :
2842 : // If our store can represent the binding and we aren't storing to something
2843 : // that doesn't have local storage then just return and have the simulation
2844 : // state continue as is.
3337: branch 0 taken
636: branch 1 taken
2845 3973: if (!escapes)
2846 3337: return;
2847 :
2848 : // Otherwise, find all symbols referenced by 'val' that we are tracking
2849 : // and stop tracking them.
2850 636: B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState());
2851 : }
2852 :
2853 : // Return statements.
2854 :
2855 : void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,
2856 : GRExprEngine& Eng,
2857 : GRStmtNodeBuilder& Builder,
2858 : ReturnStmt* S,
2859 1305: ExplodedNode* Pred) {
2860 :
2861 1305: Expr* RetE = S->getRetValue();
236: branch 0 taken
1069: branch 1 taken
2862 1305: if (!RetE)
2863 236: return;
2864 :
2865 1069: const GRState *state = Builder.GetState(Pred);
2866 1069: SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
2867 :
819: branch 0 taken
250: branch 1 taken
2868 1069: if (!Sym)
2869 819: return;
2870 :
2871 : // Get the reference count binding (if any).
2872 250: const RefVal* T = state->get<RefBindings>(Sym);
2873 :
143: branch 0 taken
107: branch 1 taken
2874 250: if (!T)
2875 143: return;
2876 :
2877 : // Change the reference count.
2878 107: RefVal X = *T;
2879 :
95: branch 1 taken
12: branch 2 taken
0: branch 3 not taken
2880 107: switch (X.getKind()) {
2881 : case RefVal::Owned: {
2882 95: unsigned cnt = X.getCount();
0: branch 0 not taken
95: branch 1 taken
2883 95: assert (cnt > 0);
2884 95: X.setCount(cnt - 1);
2885 95: X = X ^ RefVal::ReturnedOwned;
2886 95: break;
2887 : }
2888 :
2889 : case RefVal::NotOwned: {
2890 12: unsigned cnt = X.getCount();
2: branch 0 taken
10: branch 1 taken
2891 12: if (cnt) {
2892 2: X.setCount(cnt - 1);
2893 2: X = X ^ RefVal::ReturnedOwned;
2894 : }
2895 : else {
2896 10: X = X ^ RefVal::ReturnedNotOwned;
2897 : }
2898 12: break;
2899 : }
2900 :
2901 : default:
2902 0: return;
2903 : }
2904 :
2905 : // Update the binding.
2906 107: state = state->set<RefBindings>(Sym, X);
2907 107: Pred = Builder.MakeNode(Dst, S, Pred, state);
2908 :
2909 : // Did we cache out?
0: branch 0 not taken
107: branch 1 taken
2910 107: if (!Pred)
2911 0: return;
2912 :
2913 : // Update the autorelease counts.
2914 : static unsigned autoreleasetag = 0;
2915 107: GenericNodeBuilder Bd(Builder, S, &autoreleasetag);
2916 107: bool stop = false;
2917 : llvm::tie(Pred, state) = HandleAutoreleaseCounts(state , Bd, Pred, Eng, Sym,
2918 107: X, stop);
2919 :
2920 : // Did we cache out?
105: branch 0 taken
2: branch 1 taken
0: branch 2 not taken
105: branch 3 taken
2921 107: if (!Pred || stop)
2922 2: return;
2923 :
2924 : // Get the updated binding.
2925 105: T = state->get<RefBindings>(Sym);
0: branch 0 not taken
105: branch 1 taken
2926 105: assert(T);
2927 105: X = *T;
2928 :
2929 : // Any leaks or other errors?
81: branch 1 taken
24: branch 2 taken
73: branch 4 taken
8: branch 5 taken
73: branch 6 taken
32: branch 7 taken
2930 105: if (X.isReturnedOwned() && X.getCount() == 0) {
2931 73: Decl const *CD = &Pred->getCodeDecl();
52: branch 1 taken
21: branch 2 taken
2932 73: if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
2933 52: const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
2934 52: RetEffect RE = Summ.getRetEffect();
2935 52: bool hasError = false;
2936 :
50: branch 1 taken
2: branch 2 taken
2937 52: if (RE.getKind() != RetEffect::NoRet) {
10: branch 1 taken
40: branch 2 taken
6: branch 4 taken
4: branch 5 taken
6: branch 6 taken
44: branch 7 taken
2938 50: if (isGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
2939 : // Things are more complicated with garbage collection. If the
2940 : // returned object is suppose to be an Objective-C object, we have
2941 : // a leak (as the caller expects a GC'ed object) because no
2942 : // method should return ownership unless it returns a CF object.
2943 6: hasError = true;
2944 6: X = X ^ RefVal::ErrorGCLeakReturned;
2945 : }
16: branch 1 taken
28: branch 2 taken
2946 44: else if (!RE.isOwned()) {
2947 : // Either we are using GC and the returned object is a CF type
2948 : // or we aren't using GC. In either case, we expect that the
2949 : // enclosing method is expected to return ownership.
2950 16: hasError = true;
2951 16: X = X ^ RefVal::ErrorLeakReturned;
2952 : }
2953 : }
2954 :
22: branch 0 taken
30: branch 1 taken
2955 52: if (hasError) {
2956 : // Generate an error node.
2957 : static int ReturnOwnLeakTag = 0;
2958 22: state = state->set<RefBindings>(Sym, X);
2959 : ExplodedNode *N =
2960 : Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
2961 22: &ReturnOwnLeakTag), state, Pred);
22: branch 0 taken
0: branch 1 not taken
2962 22: if (N) {
2963 : CFRefReport *report =
2964 : new CFRefLeakReport(*static_cast<CFRefBug*>(leakAtReturn), *this,
2965 22: N, Sym, Eng);
2966 22: BR->EmitReport(report);
2967 : }
2968 : }
2969 : }
2970 : }
24: branch 1 taken
8: branch 2 taken
2971 32: else if (X.isReturnedNotOwned()) {
2972 24: Decl const *CD = &Pred->getCodeDecl();
14: branch 1 taken
10: branch 2 taken
2973 24: if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
2974 14: const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
4: branch 2 taken
10: branch 3 taken
2975 14: if (Summ.getRetEffect().isOwned()) {
2976 : // Trying to return a not owned object to a caller expecting an
2977 : // owned object.
2978 :
2979 : static int ReturnNotOwnedForOwnedTag = 0;
2980 4: state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
4: branch 0 taken
0: branch 1 not taken
2981 4: if (ExplodedNode *N =
2982 : Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
2983 : &ReturnNotOwnedForOwnedTag),
2984 4: state, Pred)) {
2985 : CFRefReport *report =
2986 : new CFRefReport(*static_cast<CFRefBug*>(returnNotOwnedForOwned),
2987 4: *this, N, Sym);
2988 4: BR->EmitReport(report);
2989 : }
2990 : }
2991 : }
2992 : }
2993 : }
2994 :
2995 : // Assumptions.
2996 :
2997 : const GRState* CFRefCount::EvalAssume(const GRState *state,
2998 15777: SVal Cond, bool Assumption) {
2999 :
3000 : // FIXME: We may add to the interface of EvalAssume the list of symbols
3001 : // whose assumptions have changed. For now we just iterate through the
3002 : // bindings and check if any of the tracked symbols are NULL. This isn't
3003 : // too bad since the number of symbols we will track in practice are
3004 : // probably small and EvalAssume is only called at branches and a few
3005 : // other places.
3006 15777: RefBindings B = state->get<RefBindings>();
3007 :
13071: branch 1 taken
2706: branch 2 taken
3008 15777: if (B.isEmpty())
3009 13071: return state;
3010 :
3011 2706: bool changed = false;
3012 2706: RefBindings::Factory& RefBFactory = state->get_context<RefBindings>();
3013 :
3641: branch 4 taken
2706: branch 5 taken
3014 6347: for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
3015 : // Check if the symbol is null (or equal to any constant).
3016 : // If this is the case, stop tracking the symbol.
532: branch 2 taken
3109: branch 3 taken
3017 3641: if (state->getSymVal(I.getKey())) {
3018 532: changed = true;
3019 532: B = RefBFactory.Remove(B, I.getKey());
3020 : }
3021 2706: }
3022 :
532: branch 0 taken
2174: branch 1 taken
3023 2706: if (changed)
3024 532: state = state->set<RefBindings>(B);
3025 :
3026 2706: return state;
3027 : }
3028 :
3029 : const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
3030 : RefVal V, ArgEffect E,
3031 1048: RefVal::Kind& hasErr) {
3032 :
3033 : // In GC mode [... release] and [... retain] do nothing.
571: branch 0 taken
52: branch 1 taken
361: branch 2 taken
64: branch 3 taken
0: branch 4 not taken
3034 1048: switch (E) {
3035 571: default: break;
9: branch 1 taken
43: branch 2 taken
3036 52: case IncRefMsg: E = isGCEnabled() ? DoNothing : IncRef; break;
32: branch 1 taken
329: branch 2 taken
3037 361: case DecRefMsg: E = isGCEnabled() ? DoNothing : DecRef; break;
37: branch 1 taken
27: branch 2 taken
3038 64: case MakeCollectable: E = isGCEnabled() ? DecRef : DoNothing; break;
3039 : case NewAutoreleasePool: E = isGCEnabled() ? DoNothing :
0: branch 1 not taken
0: branch 2 not taken
3040 0: NewAutoreleasePool; break;
3041 : }
3042 :
3043 : // Handle all use-after-releases.
834: branch 1 taken
214: branch 2 taken
35: branch 4 taken
799: branch 5 taken
35: branch 6 taken
1013: branch 7 taken
3044 1048: if (!isGCEnabled() && V.getKind() == RefVal::Released) {
3045 35: V = V ^ RefVal::ErrorUseAfterRelease;
3046 35: hasErr = V.getKind();
3047 35: return state->set<RefBindings>(sym, V);
3048 : }
3049 :
0: branch 0 not taken
4: branch 1 taken
0: branch 2 not taken
108: branch 3 taken
214: branch 4 taken
90: branch 5 taken
28: branch 6 taken
111: branch 7 taken
0: branch 8 not taken
458: branch 9 taken
3050 1013: switch (E) {
3051 : default:
3052 0: assert (false && "Unhandled CFRef transition.");
3053 :
3054 : case Dealloc:
3055 : // Any use of -dealloc in GC is *bad*.
0: branch 1 not taken
4: branch 2 taken
3056 4: if (isGCEnabled()) {
3057 0: V = V ^ RefVal::ErrorDeallocGC;
3058 0: hasErr = V.getKind();
3059 0: break;
3060 : }
3061 :
0: branch 1 not taken
4: branch 2 taken
0: branch 3 not taken
3062 4: switch (V.getKind()) {
3063 : default:
3064 0: assert(false && "Invalid case.");
3065 : case RefVal::Owned:
3066 : // The object immediately transitions to the released state.
3067 4: V = V ^ RefVal::Released;
3068 4: V.clearCounts();
3069 4: return state->set<RefBindings>(sym, V);
3070 : case RefVal::NotOwned:
3071 0: V = V ^ RefVal::ErrorDeallocNotOwned;
3072 0: hasErr = V.getKind();
3073 : break;
3074 : }
3075 0: break;
3076 :
3077 : case NewAutoreleasePool:
0: branch 1 not taken
0: branch 2 not taken
3078 0: assert(!isGCEnabled());
3079 0: return state->add<AutoreleaseStack>(sym);
3080 :
3081 : case MayEscape:
48: branch 1 taken
60: branch 2 taken
3082 108: if (V.getKind() == RefVal::Owned) {
3083 48: V = V ^ RefVal::NotOwned;
3084 48: break;
3085 : }
3086 :
3087 : // Fall-through.
3088 :
3089 : case DoNothingByRef:
3090 : case DoNothing:
3091 274: return state;
3092 :
3093 : case Autorelease:
24: branch 1 taken
66: branch 2 taken
3094 90: if (isGCEnabled())
3095 24: return state;
3096 :
3097 : // Update the autorelease counts.
3098 66: state = SendAutorelease(state, ARCountFactory, sym);
3099 66: V = V.autorelease();
3100 66: break;
3101 :
3102 : case StopTracking:
3103 28: return state->remove<RefBindings>(sym);
3104 :
3105 : case IncRef:
0: branch 1 not taken
107: branch 2 taken
4: branch 3 taken
3106 111: switch (V.getKind()) {
3107 : default:
3108 0: assert(false);
3109 :
3110 : case RefVal::Owned:
3111 : case RefVal::NotOwned:
3112 107: V = V + 1;
3113 107: break;
3114 : case RefVal::Released:
3115 : // Non-GC cases are handled above.
0: branch 1 not taken
4: branch 2 taken
3116 4: assert(isGCEnabled());
3117 4: V = (V ^ RefVal::Owned) + 1;
3118 : break;
3119 : }
3120 111: break;
3121 :
3122 : case SelfOwn:
3123 0: V = V ^ RefVal::NotOwned;
3124 : // Fall-through.
3125 : case DecRef:
0: branch 1 not taken
412: branch 2 taken
46: branch 3 taken
0: branch 4 not taken
3126 458: switch (V.getKind()) {
3127 : default:
3128 : // case 'RefVal::Released' handled above.
3129 0: assert (false);
3130 :
3131 : case RefVal::Owned:
0: branch 1 not taken
412: branch 2 taken
3132 412: assert(V.getCount() > 0);
365: branch 1 taken
47: branch 2 taken
3133 412: if (V.getCount() == 1) V = V ^ RefVal::Released;
3134 412: V = V - 1;
3135 412: break;
3136 :
3137 : case RefVal::NotOwned:
36: branch 1 taken
10: branch 2 taken
3138 46: if (V.getCount() > 0)
3139 36: V = V - 1;
3140 : else {
3141 10: V = V ^ RefVal::ErrorReleaseNotOwned;
3142 10: hasErr = V.getKind();
3143 : }
3144 46: break;
3145 :
3146 : case RefVal::Released:
3147 : // Non-GC cases are handled above.
0: branch 1 not taken
0: branch 2 not taken
3148 0: assert(isGCEnabled());
3149 0: V = V ^ RefVal::ErrorUseAfterRelease;
3150 0: hasErr = V.getKind();
3151 : break;
3152 : }
3153 : break;
3154 : }
3155 683: return state->set<RefBindings>(sym, V);
3156 : }
3157 :
3158 : //===----------------------------------------------------------------------===//
3159 : // Handle dead symbols and end-of-path.
3160 : //===----------------------------------------------------------------------===//
3161 :
3162 : std::pair<ExplodedNode*, const GRState *>
3163 : CFRefCount::HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
3164 : ExplodedNode* Pred,
3165 : GRExprEngine &Eng,
3166 869: SymbolRef Sym, RefVal V, bool &stop) {
3167 :
3168 869: unsigned ACnt = V.getAutoreleaseCount();
3169 869: stop = false;
3170 :
3171 : // No autorelease counts? Nothing to be done.
809: branch 0 taken
60: branch 1 taken
3172 869: if (!ACnt)
3173 809: return std::make_pair(Pred, state);
3174 :
60: branch 1 taken
0: branch 2 not taken
3175 60: assert(!isGCEnabled() && "Autorelease counts in GC mode?");
3176 60: unsigned Cnt = V.getCount();
3177 :
3178 : // FIXME: Handle sending 'autorelease' to already released object.
3179 :
16: branch 1 taken
44: branch 2 taken
3180 60: if (V.getKind() == RefVal::ReturnedOwned)
3181 16: ++Cnt;
3182 :
54: branch 0 taken
6: branch 1 taken
3183 60: if (ACnt <= Cnt) {
46: branch 0 taken
8: branch 1 taken
3184 54: if (ACnt == Cnt) {
3185 46: V.clearCounts();
14: branch 1 taken
32: branch 2 taken
3186 46: if (V.getKind() == RefVal::ReturnedOwned)
3187 14: V = V ^ RefVal::ReturnedNotOwned;
3188 : else
3189 32: V = V ^ RefVal::NotOwned;
3190 : }
3191 : else {
3192 8: V.setCount(Cnt - ACnt);
3193 8: V.setAutoreleaseCount(0);
3194 : }
3195 54: state = state->set<RefBindings>(Sym, V);
3196 54: ExplodedNode *N = Bd.MakeNode(state, Pred);
3197 54: stop = (N == 0);
3198 54: return std::make_pair(N, state);
3199 : }
3200 :
3201 : // Woah! More autorelease counts then retain counts left.
3202 : // Emit hard error.
3203 6: stop = true;
3204 6: V = V ^ RefVal::ErrorOverAutorelease;
3205 6: state = state->set<RefBindings>(Sym, V);
3206 :
6: branch 1 taken
0: branch 2 not taken
3207 6: if (ExplodedNode *N = Bd.MakeNode(state, Pred)) {
3208 6: N->markAsSink();
3209 :
3210 6: std::string sbuf;
3211 6: llvm::raw_string_ostream os(sbuf);
3212 6: os << "Object over-autoreleased: object was sent -autorelease";
6: branch 1 taken
0: branch 2 not taken
3213 6: if (V.getAutoreleaseCount() > 1)
3214 6: os << V.getAutoreleaseCount() << " times";
3215 6: os << " but the object has ";
2: branch 1 taken
4: branch 2 taken
3216 6: if (V.getCount() == 0)
3217 2: os << "zero (locally visible)";
3218 : else
3219 4: os << "+" << V.getCount();
3220 6: os << " retain counts";
3221 :
3222 : CFRefReport *report =
3223 : new CFRefReport(*static_cast<CFRefBug*>(overAutorelease),
3224 6: *this, N, Sym, os.str());
3225 6: BR->EmitReport(report);
3226 : }
3227 :
3228 6: return std::make_pair((ExplodedNode*)0, state);
3229 : }
3230 :
3231 : const GRState *
3232 : CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
3233 758: llvm::SmallVectorImpl<SymbolRef> &Leaked) {
3234 :
3235 : bool hasLeak = V.isOwned() ||
612: branch 1 taken
146: branch 2 taken
434: branch 4 taken
178: branch 5 taken
59: branch 7 taken
375: branch 8 taken
22: branch 10 taken
215: branch 11 taken
3236 758: ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
3237 :
590: branch 0 taken
168: branch 1 taken
3238 758: if (!hasLeak)
3239 590: return state->remove<RefBindings>(sid);
3240 :
3241 168: Leaked.push_back(sid);
3242 168: return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
3243 : }
3244 :
3245 : ExplodedNode*
3246 : CFRefCount::ProcessLeaks(const GRState * state,
3247 : llvm::SmallVectorImpl<SymbolRef> &Leaked,
3248 : GenericNodeBuilder &Builder,
3249 : GRExprEngine& Eng,
3250 3507: ExplodedNode *Pred) {
3251 :
3359: branch 1 taken
148: branch 2 taken
3252 3507: if (Leaked.empty())
3253 3359: return Pred;
3254 :
3255 : // Generate an intermediate node representing the leak point.
3256 148: ExplodedNode *N = Builder.MakeNode(state, Pred);
3257 :
148: branch 0 taken
0: branch 1 not taken
3258 148: if (N) {
168: branch 0 taken
148: branch 1 taken
3259 316: for (llvm::SmallVectorImpl<SymbolRef>::iterator
3260 148: I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
3261 :
3262 : CFRefBug *BT = static_cast<CFRefBug*>(Pred ? leakWithinFunction
53: branch 0 taken
115: branch 1 taken
3263 168: : leakAtReturn);
0: branch 0 not taken
168: branch 1 taken
3264 168: assert(BT && "BugType not initialized.");
3265 168: CFRefLeakReport* report = new CFRefLeakReport(*BT, *this, N, *I, Eng);
3266 168: BR->EmitReport(report);
3267 : }
3268 : }
3269 :
3270 148: return N;
3271 : }
3272 :
3273 : void CFRefCount::EvalEndPath(GRExprEngine& Eng,
3274 2600: GREndPathNodeBuilder& Builder) {
3275 :
3276 2600: const GRState *state = Builder.getState();
3277 2600: GenericNodeBuilder Bd(Builder);
3278 2600: RefBindings B = state->get<RefBindings>();
3279 2600: ExplodedNode *Pred = 0;
3280 :
390: branch 4 taken
2598: branch 5 taken
3281 2988: for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3282 390: bool stop = false;
3283 : llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
3284 : (*I).first,
3285 390: (*I).second, stop);
3286 :
2: branch 0 taken
388: branch 1 taken
3287 390: if (stop)
3288 2: return;
2598: branch 1 taken
2: branch 2 taken
2598: branch 4 taken
2: branch 5 taken
3289 2600: }
3290 :
3291 2598: B = state->get<RefBindings>();
3292 2598: llvm::SmallVector<SymbolRef, 10> Leaked;
3293 :
388: branch 4 taken
2598: branch 5 taken
3294 2986: for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
3295 2986: state = HandleSymbolDeath(state, (*I).first, (*I).second, Leaked);
3296 :
3297 2598: ProcessLeaks(state, Leaked, Bd, Eng, Pred);
3298 : }
3299 :
3300 : void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst,
3301 : GRExprEngine& Eng,
3302 : GRStmtNodeBuilder& Builder,
3303 : ExplodedNode* Pred,
3304 : Stmt* S,
3305 : const GRState* state,
3306 911: SymbolReaper& SymReaper) {
3307 :
3308 911: RefBindings B = state->get<RefBindings>();
3309 :
3310 : // Update counts from autorelease pools
1054: branch 3 taken
909: branch 4 taken
3311 2874: for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3312 911: E = SymReaper.dead_end(); I != E; ++I) {
3313 1054: SymbolRef Sym = *I;
372: branch 1 taken
682: branch 2 taken
3314 1054: if (const RefVal* T = B.lookup(Sym)){
3315 : // Use the symbol as the tag.
3316 : // FIXME: This might not be as unique as we would like.
3317 372: GenericNodeBuilder Bd(Builder, S, Sym);
3318 372: bool stop = false;
3319 : llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
3320 372: Sym, *T, stop);
2: branch 0 taken
370: branch 1 taken
3321 372: if (stop)
3322 2: return;
3323 : }
3324 : }
3325 :
3326 909: B = state->get<RefBindings>();
3327 909: llvm::SmallVector<SymbolRef, 10> Leaked;
3328 :
1052: branch 3 taken
909: branch 4 taken
3329 2870: for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3330 909: E = SymReaper.dead_end(); I != E; ++I) {
370: branch 2 taken
682: branch 3 taken
3331 1052: if (const RefVal* T = B.lookup(*I))
3332 370: state = HandleSymbolDeath(state, *I, *T, Leaked);
3333 : }
3334 :
3335 : static unsigned LeakPPTag = 0;
3336 : {
3337 909: GenericNodeBuilder Bd(Builder, S, &LeakPPTag);
3338 909: Pred = ProcessLeaks(state, Leaked, Bd, Eng, Pred);
3339 : }
3340 :
3341 : // Did we cache out?
0: branch 0 not taken
909: branch 1 taken
3342 909: if (!Pred)
3343 0: return;
3344 :
3345 : // Now generate a new node that nukes the old bindings.
3346 909: RefBindings::Factory& F = state->get_context<RefBindings>();
3347 :
1052: branch 3 taken
909: branch 4 taken
3348 2870: for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
3349 1961: E = SymReaper.dead_end(); I!=E; ++I) B = F.Remove(B, *I);
3350 :
3351 909: state = state->set<RefBindings>(B);
909: bran