blob: 1777071c6996a033b00c25078217730a732a73d0 [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
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//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek072192b2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenekc9fa2f72008-05-01 23:13:35 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000020#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000021#include "clang/Analysis/PathDiagnostic.h"
22#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek900a2d72008-05-07 18:36:45 +000026#include "llvm/ADT/StringExtras.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000027#include "llvm/Support/Compiler.h"
Ted Kremenek6ed9afc2008-05-16 18:33:44 +000028#include "llvm/ADT/STLExtras.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000029#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000030#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000031
32using namespace clang;
Ted Kremenek900a2d72008-05-07 18:36:45 +000033using llvm::CStrInCStrNoCase;
Ted Kremenek2fff37e2008-03-06 00:08:09 +000034
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000035//===----------------------------------------------------------------------===//
Ted Kremenek553cf182008-06-25 21:21:56 +000036// Selector creation functions.
Ted Kremenek4fd88972008-04-17 18:12:53 +000037//===----------------------------------------------------------------------===//
38
Ted Kremenekb83e02e2008-05-01 18:31:44 +000039static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenek4fd88972008-04-17 18:12:53 +000040 IdentifierInfo* II = &Ctx.Idents.get(name);
41 return Ctx.Selectors.getSelector(0, &II);
42}
43
Ted Kremenek9c32d082008-05-06 00:30:21 +000044static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
45 IdentifierInfo* II = &Ctx.Idents.get(name);
46 return Ctx.Selectors.getSelector(1, &II);
47}
48
Ted Kremenek553cf182008-06-25 21:21:56 +000049//===----------------------------------------------------------------------===//
50// Type querying functions.
51//===----------------------------------------------------------------------===//
52
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000053static bool isCFRefType(QualType T) {
54
55 if (!T->isPointerType())
56 return false;
57
Ted Kremenek553cf182008-06-25 21:21:56 +000058 // Check the typedef for the name "CF" and the substring "Ref".
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000059 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
60
61 if (!TD)
62 return false;
63
64 const char* TDName = TD->getDecl()->getIdentifier()->getName();
65 assert (TDName);
66
67 if (TDName[0] != 'C' || TDName[1] != 'F')
68 return false;
69
70 if (strstr(TDName, "Ref") == 0)
71 return false;
72
73 return true;
74}
75
Ted Kremenek37d785b2008-07-15 16:50:12 +000076static bool isCGRefType(QualType T) {
77
78 if (!T->isPointerType())
79 return false;
80
81 // Check the typedef for the name "CG" and the substring "Ref".
82 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
83
84 if (!TD)
85 return false;
86
87 const char* TDName = TD->getDecl()->getIdentifier()->getName();
88 assert (TDName);
89
90 if (TDName[0] != 'C' || TDName[1] != 'G')
91 return false;
92
93 if (strstr(TDName, "Ref") == 0)
94 return false;
95
96 return true;
97}
98
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000099static bool isNSType(QualType T) {
100
101 if (!T->isPointerType())
102 return false;
103
104 ObjCInterfaceType* OT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
105
106 if (!OT)
107 return false;
108
109 const char* ClsName = OT->getDecl()->getIdentifier()->getName();
110 assert (ClsName);
111
112 if (ClsName[0] != 'N' || ClsName[1] != 'S')
113 return false;
114
115 return true;
116}
117
Ted Kremenek4fd88972008-04-17 18:12:53 +0000118//===----------------------------------------------------------------------===//
Ted Kremenek553cf182008-06-25 21:21:56 +0000119// Primitives used for constructing summaries for function/method calls.
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000120//===----------------------------------------------------------------------===//
121
Ted Kremenek553cf182008-06-25 21:21:56 +0000122namespace {
123/// ArgEffect is used to summarize a function/method call's effect on a
124/// particular argument.
Ted Kremenek070a8252008-07-09 18:11:16 +0000125enum ArgEffect { IncRef, DecRef, DoNothing, DoNothingByRef,
126 StopTracking, MayEscape, SelfOwn, Autorelease };
Ted Kremenek553cf182008-06-25 21:21:56 +0000127
128/// ArgEffects summarizes the effects of a function/method call on all of
129/// its arguments.
130typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000131}
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000132
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000133namespace llvm {
Ted Kremenek553cf182008-06-25 21:21:56 +0000134template <> struct FoldingSetTrait<ArgEffects> {
135 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
136 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
137 ID.AddInteger(I->first);
138 ID.AddInteger((unsigned) I->second);
139 }
140 }
141};
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000142} // end llvm namespace
143
144namespace {
Ted Kremenek553cf182008-06-25 21:21:56 +0000145
146/// RetEffect is used to summarize a function/method call's behavior with
147/// respect to its return value.
148class VISIBILITY_HIDDEN RetEffect {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000149public:
Ted Kremeneka7344702008-06-23 18:02:52 +0000150 enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
151 NotOwnedSymbol, ReceiverAlias };
Ted Kremenek553cf182008-06-25 21:21:56 +0000152
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000153private:
154 unsigned Data;
Ted Kremenek553cf182008-06-25 21:21:56 +0000155 RetEffect(Kind k, unsigned D = 0) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000156
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000157public:
Ted Kremenek553cf182008-06-25 21:21:56 +0000158
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000159 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremenek553cf182008-06-25 21:21:56 +0000160
161 unsigned getIndex() const {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000162 assert(getKind() == Alias);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000163 return Data >> 3;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000164 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000165
Ted Kremenek553cf182008-06-25 21:21:56 +0000166 static RetEffect MakeAlias(unsigned Idx) {
167 return RetEffect(Alias, Idx);
168 }
169 static RetEffect MakeReceiverAlias() {
170 return RetEffect(ReceiverAlias);
171 }
Ted Kremeneka7344702008-06-23 18:02:52 +0000172 static RetEffect MakeOwned(bool isAllocated = false) {
Ted Kremenek553cf182008-06-25 21:21:56 +0000173 return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol);
174 }
175 static RetEffect MakeNotOwned() {
176 return RetEffect(NotOwnedSymbol);
177 }
178 static RetEffect MakeNoRet() {
179 return RetEffect(NoRet);
Ted Kremeneka7344702008-06-23 18:02:52 +0000180 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000181
Ted Kremenek553cf182008-06-25 21:21:56 +0000182 operator Kind() const {
183 return getKind();
184 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000185
Ted Kremenek553cf182008-06-25 21:21:56 +0000186 void Profile(llvm::FoldingSetNodeID& ID) const {
187 ID.AddInteger(Data);
188 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000189};
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000190
Ted Kremenek553cf182008-06-25 21:21:56 +0000191
192class VISIBILITY_HIDDEN RetainSummary : public llvm::FoldingSetNode {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000193 /// Args - an ordered vector of (index, ArgEffect) pairs, where index
194 /// specifies the argument (starting from 0). This can be sparsely
195 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000196 ArgEffects* Args;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000197
198 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
199 /// do not have an entry in Args.
200 ArgEffect DefaultArgEffect;
201
Ted Kremenek553cf182008-06-25 21:21:56 +0000202 /// Receiver - If this summary applies to an Objective-C message expression,
203 /// this is the effect applied to the state of the receiver.
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000204 ArgEffect Receiver;
Ted Kremenek553cf182008-06-25 21:21:56 +0000205
206 /// Ret - The effect on the return value. Used to indicate if the
207 /// function/method call returns a new tracked symbol, returns an
208 /// alias of one of the arguments in the call, and so on.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000209 RetEffect Ret;
Ted Kremenek553cf182008-06-25 21:21:56 +0000210
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000211public:
212
Ted Kremenek1bffd742008-05-06 15:44:25 +0000213 RetainSummary(ArgEffects* A, RetEffect R, ArgEffect defaultEff,
214 ArgEffect ReceiverEff)
215 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000216
Ted Kremenek553cf182008-06-25 21:21:56 +0000217 /// getArg - Return the argument effect on the argument specified by
218 /// idx (starting from 0).
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000219 ArgEffect getArg(unsigned idx) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000220
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000221 if (!Args)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000222 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000223
224 // If Args is present, it is likely to contain only 1 element.
225 // Just do a linear search. Do it from the back because functions with
226 // large numbers of arguments will be tail heavy with respect to which
Ted Kremenek553cf182008-06-25 21:21:56 +0000227 // argument they actually modify with respect to the reference count.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000228 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
229 I!=E; ++I) {
230
231 if (idx > I->first)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000232 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000233
234 if (idx == I->first)
235 return I->second;
236 }
237
Ted Kremenek1bffd742008-05-06 15:44:25 +0000238 return DefaultArgEffect;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000239 }
240
Ted Kremenek553cf182008-06-25 21:21:56 +0000241 /// getRetEffect - Returns the effect on the return value of the call.
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000242 RetEffect getRetEffect() const {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000243 return Ret;
244 }
245
Ted Kremenek553cf182008-06-25 21:21:56 +0000246 /// getReceiverEffect - Returns the effect on the receiver of the call.
247 /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000248 ArgEffect getReceiverEffect() const {
249 return Receiver;
250 }
251
Ted Kremenek55499762008-06-17 02:43:46 +0000252 typedef ArgEffects::const_iterator ExprIterator;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000253
Ted Kremenek55499762008-06-17 02:43:46 +0000254 ExprIterator begin_args() const { return Args->begin(); }
255 ExprIterator end_args() const { return Args->end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000256
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000257 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000258 RetEffect RetEff, ArgEffect DefaultEff,
259 ArgEffect ReceiverEff) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000260 ID.AddPointer(A);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000261 ID.Add(RetEff);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000262 ID.AddInteger((unsigned) DefaultEff);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000263 ID.AddInteger((unsigned) ReceiverEff);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000264 }
265
266 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000267 Profile(ID, Args, Ret, DefaultArgEffect, Receiver);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000268 }
269};
Ted Kremenek4f22a782008-06-23 23:30:29 +0000270} // end anonymous namespace
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000271
Ted Kremenek553cf182008-06-25 21:21:56 +0000272//===----------------------------------------------------------------------===//
273// Data structures for constructing summaries.
274//===----------------------------------------------------------------------===//
Ted Kremenek53301ba2008-06-24 03:49:48 +0000275
Ted Kremenek553cf182008-06-25 21:21:56 +0000276namespace {
277class VISIBILITY_HIDDEN ObjCSummaryKey {
278 IdentifierInfo* II;
279 Selector S;
280public:
281 ObjCSummaryKey(IdentifierInfo* ii, Selector s)
282 : II(ii), S(s) {}
283
284 ObjCSummaryKey(ObjCInterfaceDecl* d, Selector s)
285 : II(d ? d->getIdentifier() : 0), S(s) {}
286
287 ObjCSummaryKey(Selector s)
288 : II(0), S(s) {}
289
290 IdentifierInfo* getIdentifier() const { return II; }
291 Selector getSelector() const { return S; }
292};
Ted Kremenek4f22a782008-06-23 23:30:29 +0000293}
294
295namespace llvm {
Ted Kremenek553cf182008-06-25 21:21:56 +0000296template <> struct DenseMapInfo<ObjCSummaryKey> {
297 static inline ObjCSummaryKey getEmptyKey() {
298 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
299 DenseMapInfo<Selector>::getEmptyKey());
300 }
Ted Kremenek4f22a782008-06-23 23:30:29 +0000301
Ted Kremenek553cf182008-06-25 21:21:56 +0000302 static inline ObjCSummaryKey getTombstoneKey() {
303 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
304 DenseMapInfo<Selector>::getTombstoneKey());
305 }
306
307 static unsigned getHashValue(const ObjCSummaryKey &V) {
308 return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
309 & 0x88888888)
310 | (DenseMapInfo<Selector>::getHashValue(V.getSelector())
311 & 0x55555555);
312 }
313
314 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
315 return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
316 RHS.getIdentifier()) &&
317 DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
318 RHS.getSelector());
319 }
320
321 static bool isPod() {
322 return DenseMapInfo<ObjCInterfaceDecl*>::isPod() &&
323 DenseMapInfo<Selector>::isPod();
324 }
325};
Ted Kremenek4f22a782008-06-23 23:30:29 +0000326} // end llvm namespace
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000327
Ted Kremenek4f22a782008-06-23 23:30:29 +0000328namespace {
Ted Kremenek553cf182008-06-25 21:21:56 +0000329class VISIBILITY_HIDDEN ObjCSummaryCache {
330 typedef llvm::DenseMap<ObjCSummaryKey, RetainSummary*> MapTy;
331 MapTy M;
332public:
333 ObjCSummaryCache() {}
334
335 typedef MapTy::iterator iterator;
336
337 iterator find(ObjCInterfaceDecl* D, Selector S) {
338
339 // Do a lookup with the (D,S) pair. If we find a match return
340 // the iterator.
341 ObjCSummaryKey K(D, S);
342 MapTy::iterator I = M.find(K);
343
344 if (I != M.end() || !D)
345 return I;
346
347 // Walk the super chain. If we find a hit with a parent, we'll end
348 // up returning that summary. We actually allow that key (null,S), as
349 // we cache summaries for the null ObjCInterfaceDecl* to allow us to
350 // generate initial summaries without having to worry about NSObject
351 // being declared.
352 // FIXME: We may change this at some point.
353 for (ObjCInterfaceDecl* C=D->getSuperClass() ;; C=C->getSuperClass()) {
354 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
355 break;
356
357 if (!C)
358 return I;
359 }
360
361 // Cache the summary with original key to make the next lookup faster
362 // and return the iterator.
363 M[K] = I->second;
364 return I;
365 }
366
367
368 iterator find(Expr* Receiver, Selector S) {
369 return find(getReceiverDecl(Receiver), S);
370 }
371
372 iterator find(IdentifierInfo* II, Selector S) {
373 // FIXME: Class method lookup. Right now we dont' have a good way
374 // of going between IdentifierInfo* and the class hierarchy.
375 iterator I = M.find(ObjCSummaryKey(II, S));
376 return I == M.end() ? M.find(ObjCSummaryKey(S)) : I;
377 }
378
379 ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
380
381 const PointerType* PT = E->getType()->getAsPointerType();
382 if (!PT) return 0;
383
384 ObjCInterfaceType* OI = dyn_cast<ObjCInterfaceType>(PT->getPointeeType());
385 if (!OI) return 0;
386
387 return OI ? OI->getDecl() : 0;
388 }
389
390 iterator end() { return M.end(); }
391
392 RetainSummary*& operator[](ObjCMessageExpr* ME) {
393
394 Selector S = ME->getSelector();
395
396 if (Expr* Receiver = ME->getReceiver()) {
397 ObjCInterfaceDecl* OD = getReceiverDecl(Receiver);
398 return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
399 }
400
401 return M[ObjCSummaryKey(ME->getClassName(), S)];
402 }
403
404 RetainSummary*& operator[](ObjCSummaryKey K) {
405 return M[K];
406 }
407
408 RetainSummary*& operator[](Selector S) {
409 return M[ ObjCSummaryKey(S) ];
410 }
411};
412} // end anonymous namespace
413
414//===----------------------------------------------------------------------===//
415// Data structures for managing collections of summaries.
416//===----------------------------------------------------------------------===//
417
418namespace {
419class VISIBILITY_HIDDEN RetainSummaryManager {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000420
421 //==-----------------------------------------------------------------==//
422 // Typedefs.
423 //==-----------------------------------------------------------------==//
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000424
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000425 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
426 ArgEffectsSetTy;
427
428 typedef llvm::FoldingSet<RetainSummary>
429 SummarySetTy;
430
431 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
432 FuncSummariesTy;
433
Ted Kremenek4f22a782008-06-23 23:30:29 +0000434 typedef ObjCSummaryCache ObjCMethodSummariesTy;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000435
436 //==-----------------------------------------------------------------==//
437 // Data.
438 //==-----------------------------------------------------------------==//
439
Ted Kremenek553cf182008-06-25 21:21:56 +0000440 /// Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek377e2302008-04-29 05:33:51 +0000441 ASTContext& Ctx;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000442
Ted Kremenek553cf182008-06-25 21:21:56 +0000443 /// NSWindowII - An IdentifierInfo* representing the identifier "NSWindow."
444 IdentifierInfo* NSWindowII;
Ted Kremenek179064e2008-07-01 17:21:27 +0000445
446 /// NSPanelII - An IdentifierInfo* representing the identifier "NSPanel."
447 IdentifierInfo* NSPanelII;
Ted Kremenek553cf182008-06-25 21:21:56 +0000448
Ted Kremenek070a8252008-07-09 18:11:16 +0000449 /// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
450 /// "CFDictionaryCreate".
451 IdentifierInfo* CFDictionaryCreateII;
452
Ted Kremenek553cf182008-06-25 21:21:56 +0000453 /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek377e2302008-04-29 05:33:51 +0000454 const bool GCEnabled;
455
Ted Kremenek553cf182008-06-25 21:21:56 +0000456 /// SummarySet - A FoldingSet of uniqued summaries.
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000457 SummarySetTy SummarySet;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000458
Ted Kremenek553cf182008-06-25 21:21:56 +0000459 /// FuncSummaries - A map from FunctionDecls to summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000460 FuncSummariesTy FuncSummaries;
461
Ted Kremenek553cf182008-06-25 21:21:56 +0000462 /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
463 /// to summaries.
Ted Kremenek1f180c32008-06-23 22:21:20 +0000464 ObjCMethodSummariesTy ObjCClassMethodSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000465
Ted Kremenek553cf182008-06-25 21:21:56 +0000466 /// ObjCMethodSummaries - A map from selectors to summaries.
Ted Kremenek1f180c32008-06-23 22:21:20 +0000467 ObjCMethodSummariesTy ObjCMethodSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000468
Ted Kremenek553cf182008-06-25 21:21:56 +0000469 /// ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000470 ArgEffectsSetTy ArgEffectsSet;
471
Ted Kremenek553cf182008-06-25 21:21:56 +0000472 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
473 /// and all other data used by the checker.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000474 llvm::BumpPtrAllocator BPAlloc;
475
Ted Kremenek553cf182008-06-25 21:21:56 +0000476 /// ScratchArgs - A holding buffer for construct ArgEffects.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000477 ArgEffects ScratchArgs;
478
Ted Kremenek432af592008-05-06 18:11:36 +0000479 RetainSummary* StopSummary;
480
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000481 //==-----------------------------------------------------------------==//
482 // Methods.
483 //==-----------------------------------------------------------------==//
484
Ted Kremenek553cf182008-06-25 21:21:56 +0000485 /// getArgEffects - Returns a persistent ArgEffects object based on the
486 /// data in ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000487 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000488
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000489 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000490 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek377e2302008-04-29 05:33:51 +0000491
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000492 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
493 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek37d785b2008-07-15 16:50:12 +0000494 RetainSummary* getCGSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000495
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000496 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
497 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenek37d785b2008-07-15 16:50:12 +0000498 RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000499
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000500 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000501 ArgEffect ReceiverEff = DoNothing,
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000502 ArgEffect DefaultEff = MayEscape);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000503
Ted Kremenek9c32d082008-05-06 00:30:21 +0000504
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000505 RetainSummary* getPersistentSummary(RetEffect RE,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000506 ArgEffect ReceiverEff = DoNothing,
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000507 ArgEffect DefaultEff = MayEscape) {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000508 return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000509 }
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000510
Ted Kremenek432af592008-05-06 18:11:36 +0000511
Ted Kremenek1bffd742008-05-06 15:44:25 +0000512 RetainSummary* getPersistentStopSummary() {
Ted Kremenek432af592008-05-06 18:11:36 +0000513 if (StopSummary)
514 return StopSummary;
515
516 StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
517 StopTracking, StopTracking);
518
519 return StopSummary;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000520 }
Ted Kremenekb3095252008-05-06 04:20:12 +0000521
Ted Kremenek553cf182008-06-25 21:21:56 +0000522 RetainSummary* getInitMethodSummary(ObjCMessageExpr* ME);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000523
Ted Kremenek1f180c32008-06-23 22:21:20 +0000524 void InitializeClassMethodSummaries();
525 void InitializeMethodSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000526
Ted Kremenek553cf182008-06-25 21:21:56 +0000527 void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
528 ObjCClassMethodSummaries[S] = Summ;
529 }
530
531 void addNSObjectMethSummary(Selector S, RetainSummary *Summ) {
532 ObjCMethodSummaries[S] = Summ;
533 }
534
535 void addNSWindowMethSummary(Selector S, RetainSummary *Summ) {
536 ObjCMethodSummaries[ObjCSummaryKey(NSWindowII, S)] = Summ;
537 }
538
Ted Kremenek179064e2008-07-01 17:21:27 +0000539 void addNSPanelMethSummary(Selector S, RetainSummary *Summ) {
540 ObjCMethodSummaries[ObjCSummaryKey(NSPanelII, S)] = Summ;
541 }
542
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000543public:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000544
545 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek179064e2008-07-01 17:21:27 +0000546 : Ctx(ctx),
547 NSWindowII(&ctx.Idents.get("NSWindow")),
548 NSPanelII(&ctx.Idents.get("NSPanel")),
Ted Kremenek070a8252008-07-09 18:11:16 +0000549 CFDictionaryCreateII(&ctx.Idents.get("CFDictionaryCreate")),
Ted Kremenek553cf182008-06-25 21:21:56 +0000550 GCEnabled(gcenabled), StopSummary(0) {
551
552 InitializeClassMethodSummaries();
553 InitializeMethodSummaries();
554 }
Ted Kremenek377e2302008-04-29 05:33:51 +0000555
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000556 ~RetainSummaryManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000557
Ted Kremenekab592272008-06-24 03:56:45 +0000558 RetainSummary* getSummary(FunctionDecl* FD);
Ted Kremenek553cf182008-06-25 21:21:56 +0000559 RetainSummary* getMethodSummary(ObjCMessageExpr* ME, ObjCInterfaceDecl* ID);
Ted Kremenek1f180c32008-06-23 22:21:20 +0000560 RetainSummary* getClassMethodSummary(IdentifierInfo* ClsName, Selector S);
Ted Kremenekb3095252008-05-06 04:20:12 +0000561
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000562 bool isGCEnabled() const { return GCEnabled; }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000563};
564
565} // end anonymous namespace
566
567//===----------------------------------------------------------------------===//
568// Implementation of checker data structures.
569//===----------------------------------------------------------------------===//
570
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000571RetainSummaryManager::~RetainSummaryManager() {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000572
573 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
574 // mitigating the need to do explicit cleanup of the
575 // Argument-Effect summaries.
576
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000577 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
578 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000579 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000580}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000581
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000582ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000583
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000584 if (ScratchArgs.empty())
585 return NULL;
586
587 // Compute a profile for a non-empty ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000588 llvm::FoldingSetNodeID profile;
589 profile.Add(ScratchArgs);
590 void* InsertPos;
591
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000592 // Look up the uniqued copy, or create a new one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000593 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000594 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000595
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000596 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000597 ScratchArgs.clear();
598 return &E->getValue();
599 }
600
601 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
Ted Kremenek553cf182008-06-25 21:21:56 +0000602 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000603
604 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000605 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000606
607 ScratchArgs.clear();
608 return &E->getValue();
609}
610
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000611RetainSummary*
612RetainSummaryManager::getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000613 ArgEffect ReceiverEff,
614 ArgEffect DefaultEff) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000615
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000616 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000617 llvm::FoldingSetNodeID profile;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000618 RetainSummary::Profile(profile, AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000619
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000620 // Look up the uniqued summary, or create one if it doesn't exist.
621 void* InsertPos;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000622 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000623
624 if (Summ)
625 return Summ;
626
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000627 // Create the summary and return it.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000628 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
Ted Kremenek1bffd742008-05-06 15:44:25 +0000629 new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000630 SummarySet.InsertNode(Summ, InsertPos);
631
632 return Summ;
633}
634
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000635//===----------------------------------------------------------------------===//
636// Summary creation for functions (largely uses of Core Foundation).
637//===----------------------------------------------------------------------===//
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000638
Ted Kremenekab592272008-06-24 03:56:45 +0000639RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000640
641 SourceLocation Loc = FD->getLocation();
642
643 if (!Loc.isFileID())
644 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000645
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000646 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000647 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000648
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000649 if (I != FuncSummaries.end())
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000650 return I->second;
651
652 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000653 const char* FName = FD->getIdentifier()->getName();
654
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000655 RetainSummary *S = 0;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000656
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000657 FunctionType* FT = dyn_cast<FunctionType>(FD->getType());
Ted Kremenek37d785b2008-07-15 16:50:12 +0000658
659 do {
660 if (FT) {
661
662 QualType T = FT->getResultType();
663
664 if (isCFRefType(T)) {
665 S = getCFSummary(FD, FName);
666 break;
667 }
668
669 if (isCGRefType(T)) {
670 S = getCGSummary(FD, FName );
671 break;
672 }
673 }
674
675 if (FName[0] == 'C' && FName[1] == 'F')
676 S = getCFSummary(FD, FName);
677 else if (FName[0] == 'N' && FName[1] == 'S')
678 S = getNSSummary(FD, FName);
679 }
680 while (0);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000681
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000682 FuncSummaries[FD] = S;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000683 return S;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000684}
685
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000686RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000687 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000688 FName += 2;
689
690 if (strcmp(FName, "MakeCollectable") == 0)
691 return getUnarySummary(FD, cfmakecollectable);
692
693 return 0;
694}
Ted Kremenek37d785b2008-07-15 16:50:12 +0000695
696static bool isRetain(FunctionDecl* FD, const char* FName) {
697 return (strstr(FName, "Retain") != 0);
698}
699
700static bool isRelease(FunctionDecl* FD, const char* FName) {
701 return (strstr(FName, "Release") != 0);
702}
703
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000704RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000705 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000706
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000707 if (FName[0] == 'C' && FName[1] == 'F')
708 FName += 2;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000709
Ted Kremenek37d785b2008-07-15 16:50:12 +0000710 if (isRetain(FD, FName))
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000711 return getUnarySummary(FD, cfretain);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000712
Ted Kremenek37d785b2008-07-15 16:50:12 +0000713 if (isRelease(FD, FName))
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000714 return getUnarySummary(FD, cfrelease);
Ted Kremenek070a8252008-07-09 18:11:16 +0000715
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000716 if (strcmp(FName, "MakeCollectable") == 0)
717 return getUnarySummary(FD, cfmakecollectable);
Ted Kremenek37d785b2008-07-15 16:50:12 +0000718
719 return getCFCreateGetRuleSummary(FD, FName);
720}
721
722RetainSummary* RetainSummaryManager::getCGSummary(FunctionDecl* FD,
723 const char* FName) {
724
725 if (FName[0] == 'C' && FName[1] == 'G')
726 FName += 2;
727
728 if (isRelease(FD, FName))
729 return getUnarySummary(FD, cfrelease);
730
731 if (isRetain(FD, FName))
732 return getUnarySummary(FD, cfretain);
733
734 return getCFCreateGetRuleSummary(FD, FName);
735}
736
737RetainSummary*
738RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
739 const char* FName) {
740
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000741 if (strstr(FName, "Create") || strstr(FName, "Copy"))
742 return getCFSummaryCreateRule(FD);
Ted Kremenek37d785b2008-07-15 16:50:12 +0000743
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000744 if (strstr(FName, "Get"))
745 return getCFSummaryGetRule(FD);
746
747 return 0;
748}
749
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000750RetainSummary*
751RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000752
753 FunctionTypeProto* FT =
754 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
755
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000756 if (FT) {
757
758 if (FT->getNumArgs() != 1)
759 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000760
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000761 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
762
763 if (!ArgT)
764 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000765
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000766 if (!ArgT->isPointerType())
767 return NULL;
768 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000769
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000770 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000771
Ted Kremenek377e2302008-04-29 05:33:51 +0000772 switch (func) {
773 case cfretain: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000774 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000775 return getPersistentSummary(RetEffect::MakeAlias(0),
776 DoNothing, DoNothing);
Ted Kremenek377e2302008-04-29 05:33:51 +0000777 }
778
779 case cfrelease: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000780 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000781 return getPersistentSummary(RetEffect::MakeNoRet(),
782 DoNothing, DoNothing);
Ted Kremenek377e2302008-04-29 05:33:51 +0000783 }
784
785 case cfmakecollectable: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000786 if (GCEnabled)
787 ScratchArgs.push_back(std::make_pair(0, DecRef));
788
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000789 return getPersistentSummary(RetEffect::MakeAlias(0),
790 DoNothing, DoNothing);
Ted Kremenek377e2302008-04-29 05:33:51 +0000791 }
792
793 default:
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000794 assert (false && "Not a supported unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000795 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000796}
797
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000798RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000799
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000800 FunctionType* FT =
801 dyn_cast<FunctionType>(FD->getType().getTypePtr());
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000802
803 if (FT && !isCFRefType(FT->getResultType()))
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000804 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000805
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000806 assert (ScratchArgs.empty());
Ted Kremenek070a8252008-07-09 18:11:16 +0000807
808 if (FD->getIdentifier() == CFDictionaryCreateII) {
809 ScratchArgs.push_back(std::make_pair(1, DoNothingByRef));
810 ScratchArgs.push_back(std::make_pair(2, DoNothingByRef));
811 }
812
Ted Kremeneka7344702008-06-23 18:02:52 +0000813 return getPersistentSummary(RetEffect::MakeOwned(true));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000814}
815
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000816RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000817
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000818 FunctionType* FT =
819 dyn_cast<FunctionType>(FD->getType().getTypePtr());
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000820
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000821 if (FT) {
822 QualType RetTy = FT->getResultType();
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000823
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000824 // FIXME: For now we assume that all pointer types returned are referenced
825 // counted. Since this is the "Get" rule, we assume non-ownership, which
826 // works fine for things that are not reference counted. We do this because
827 // some generic data structures return "void*". We need something better
828 // in the future.
829
830 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000831 return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000832 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000833
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000834 // FIXME: Add special-cases for functions that retain/release. For now
835 // just handle the default case.
836
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000837 assert (ScratchArgs.empty());
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000838 return getPersistentSummary(RetEffect::MakeNotOwned(), DoNothing, DoNothing);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000839}
840
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000841//===----------------------------------------------------------------------===//
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000842// Summary creation for Selectors.
843//===----------------------------------------------------------------------===//
844
Ted Kremenek1bffd742008-05-06 15:44:25 +0000845RetainSummary*
Ted Kremenek553cf182008-06-25 21:21:56 +0000846RetainSummaryManager::getInitMethodSummary(ObjCMessageExpr* ME) {
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000847 assert(ScratchArgs.empty());
848
849 RetainSummary* Summ =
Ted Kremenek9c32d082008-05-06 00:30:21 +0000850 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000851
Ted Kremenek553cf182008-06-25 21:21:56 +0000852 ObjCMethodSummaries[ME] = Summ;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000853 return Summ;
854}
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000855
Ted Kremenek553cf182008-06-25 21:21:56 +0000856
Ted Kremenek1bffd742008-05-06 15:44:25 +0000857RetainSummary*
Ted Kremenek553cf182008-06-25 21:21:56 +0000858RetainSummaryManager::getMethodSummary(ObjCMessageExpr* ME,
859 ObjCInterfaceDecl* ID) {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000860
861 Selector S = ME->getSelector();
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000862
Ted Kremenek553cf182008-06-25 21:21:56 +0000863 // Look up a summary in our summary cache.
864 ObjCMethodSummariesTy::iterator I = ObjCMethodSummaries.find(ID, S);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000865
Ted Kremenek1f180c32008-06-23 22:21:20 +0000866 if (I != ObjCMethodSummaries.end())
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000867 return I->second;
Ted Kremenek553cf182008-06-25 21:21:56 +0000868
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000869 if (!ME->getType()->isPointerType())
870 return 0;
871
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000872 // "initXXX": pass-through for receiver.
873
874 const char* s = S.getIdentifierInfoForSlot(0)->getName();
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000875 assert (ScratchArgs.empty());
Ted Kremenekaee9e572008-05-06 06:09:09 +0000876
Ted Kremenek0327f772008-06-02 17:14:13 +0000877 if (strncmp(s, "init", 4) == 0 || strncmp(s, "_init", 5) == 0)
Ted Kremenek553cf182008-06-25 21:21:56 +0000878 return getInitMethodSummary(ME);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000879
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000880 // "copyXXX", "createXXX", "newXXX": allocators.
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000881
Ted Kremenek84060db2008-05-07 04:25:59 +0000882 if (!isNSType(ME->getReceiver()->getType()))
883 return 0;
884
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000885 if (CStrInCStrNoCase(s, "create") || CStrInCStrNoCase(s, "copy") ||
886 CStrInCStrNoCase(s, "new")) {
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000887
888 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
Ted Kremeneka7344702008-06-23 18:02:52 +0000889 : RetEffect::MakeOwned(true);
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000890
891 RetainSummary* Summ = getPersistentSummary(E);
Ted Kremenek553cf182008-06-25 21:21:56 +0000892 ObjCMethodSummaries[ME] = Summ;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000893 return Summ;
894 }
Ted Kremenek1bffd742008-05-06 15:44:25 +0000895
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000896 return 0;
897}
898
Ted Kremenekc8395602008-05-06 21:26:51 +0000899RetainSummary*
Ted Kremenek1f180c32008-06-23 22:21:20 +0000900RetainSummaryManager::getClassMethodSummary(IdentifierInfo* ClsName,
901 Selector S) {
Ted Kremenekc8395602008-05-06 21:26:51 +0000902
Ted Kremenek553cf182008-06-25 21:21:56 +0000903 // FIXME: Eventually we should properly do class method summaries, but
904 // it requires us being able to walk the type hierarchy. Unfortunately,
905 // we cannot do this with just an IdentifierInfo* for the class name.
906
Ted Kremenekc8395602008-05-06 21:26:51 +0000907 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek553cf182008-06-25 21:21:56 +0000908 ObjCMethodSummariesTy::iterator I = ObjCClassMethodSummaries.find(ClsName, S);
Ted Kremenekc8395602008-05-06 21:26:51 +0000909
Ted Kremenek1f180c32008-06-23 22:21:20 +0000910 if (I != ObjCClassMethodSummaries.end())
Ted Kremenekc8395602008-05-06 21:26:51 +0000911 return I->second;
912
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000913 return 0;
Ted Kremenekc8395602008-05-06 21:26:51 +0000914}
915
Ted Kremenek1f180c32008-06-23 22:21:20 +0000916void RetainSummaryManager::InitializeClassMethodSummaries() {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000917
918 assert (ScratchArgs.empty());
919
Ted Kremeneka7344702008-06-23 18:02:52 +0000920 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
921 : RetEffect::MakeOwned(true);
922
Ted Kremenek9c32d082008-05-06 00:30:21 +0000923 RetainSummary* Summ = getPersistentSummary(E);
924
Ted Kremenek553cf182008-06-25 21:21:56 +0000925 // Create the summaries for "alloc", "new", and "allocWithZone:" for
926 // NSObject and its derivatives.
927 addNSObjectClsMethSummary(GetNullarySelector("alloc", Ctx), Summ);
928 addNSObjectClsMethSummary(GetNullarySelector("new", Ctx), Summ);
929 addNSObjectClsMethSummary(GetUnarySelector("allocWithZone", Ctx), Summ);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000930}
931
Ted Kremenek1f180c32008-06-23 22:21:20 +0000932void RetainSummaryManager::InitializeMethodSummaries() {
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000933
934 assert (ScratchArgs.empty());
935
Ted Kremenekc8395602008-05-06 21:26:51 +0000936 // Create the "init" selector. It just acts as a pass-through for the
937 // receiver.
Ted Kremenek179064e2008-07-01 17:21:27 +0000938 RetainSummary* InitSumm = getPersistentSummary(RetEffect::MakeReceiverAlias());
939 addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
Ted Kremenekc8395602008-05-06 21:26:51 +0000940
941 // The next methods are allocators.
Ted Kremeneka7344702008-06-23 18:02:52 +0000942 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
943 : RetEffect::MakeOwned(true);
944
Ted Kremenek179064e2008-07-01 17:21:27 +0000945 RetainSummary* Summ = getPersistentSummary(E);
Ted Kremenekc8395602008-05-06 21:26:51 +0000946
947 // Create the "copy" selector.
Ted Kremenek553cf182008-06-25 21:21:56 +0000948 addNSObjectMethSummary(GetNullarySelector("copy", Ctx), Summ);
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000949
950 // Create the "mutableCopy" selector.
Ted Kremenek553cf182008-06-25 21:21:56 +0000951 addNSObjectMethSummary(GetNullarySelector("mutableCopy", Ctx), Summ);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000952
953 // Create the "retain" selector.
954 E = RetEffect::MakeReceiverAlias();
955 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
Ted Kremenek553cf182008-06-25 21:21:56 +0000956 addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000957
958 // Create the "release" selector.
959 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
Ted Kremenek553cf182008-06-25 21:21:56 +0000960 addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
Ted Kremenek299e8152008-05-07 21:17:39 +0000961
962 // Create the "drain" selector.
963 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
Ted Kremenek553cf182008-06-25 21:21:56 +0000964 addNSObjectMethSummary(GetNullarySelector("drain", Ctx), Summ);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000965
966 // Create the "autorelease" selector.
Ted Kremeneke19f4492008-06-30 16:57:41 +0000967 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : Autorelease);
Ted Kremenek553cf182008-06-25 21:21:56 +0000968 addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
969
970 // For NSWindow, allocated objects are (initially) self-owned.
Ted Kremenek179064e2008-07-01 17:21:27 +0000971 // For NSPanel (which subclasses NSWindow), allocated objects are not
972 // self-owned.
973
974 RetainSummary *NSWindowSumm =
975 getPersistentSummary(RetEffect::MakeReceiverAlias(), SelfOwn);
Ted Kremenek553cf182008-06-25 21:21:56 +0000976
977 // Create the "initWithContentRect:styleMask:backing:defer:" selector.
978 llvm::SmallVector<IdentifierInfo*, 5> II;
979 II.push_back(&Ctx.Idents.get("initWithContentRect"));
980 II.push_back(&Ctx.Idents.get("styleMask"));
981 II.push_back(&Ctx.Idents.get("backing"));
982 II.push_back(&Ctx.Idents.get("defer"));
983 Selector S = Ctx.Selectors.getSelector(II.size(), &II[0]);
Ted Kremenek179064e2008-07-01 17:21:27 +0000984 addNSWindowMethSummary(S, NSWindowSumm);
985 addNSPanelMethSummary(S, InitSumm);
986
Ted Kremenek553cf182008-06-25 21:21:56 +0000987 // Create the "initWithContentRect:styleMask:backing:defer:screen:" selector.
988 II.push_back(&Ctx.Idents.get("screen"));
989 S = Ctx.Selectors.getSelector(II.size(), &II[0]);
Ted Kremenek179064e2008-07-01 17:21:27 +0000990 addNSWindowMethSummary(S, NSWindowSumm);
991 addNSPanelMethSummary(S, InitSumm);
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000992}
993
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000994//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000995// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000996//===----------------------------------------------------------------------===//
997
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000998namespace {
999
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001000class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001001public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001002
Ted Kremenek4fd88972008-04-17 18:12:53 +00001003 enum Kind {
1004 Owned = 0, // Owning reference.
1005 NotOwned, // Reference is not owned by still valid (not freed).
1006 Released, // Object has been released.
1007 ReturnedOwned, // Returned object passes ownership to caller.
1008 ReturnedNotOwned, // Return object does not pass ownership to caller.
1009 ErrorUseAfterRelease, // Object used after released.
1010 ErrorReleaseNotOwned, // Release of an object that was not owned.
1011 ErrorLeak // A memory leak due to excessive reference counts.
1012 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001013
Ted Kremenek4fd88972008-04-17 18:12:53 +00001014private:
1015
1016 Kind kind;
1017 unsigned Cnt;
Ted Kremenek553cf182008-06-25 21:21:56 +00001018 QualType T;
1019
1020 RefVal(Kind k, unsigned cnt, QualType t) : kind(k), Cnt(cnt), T(t) {}
1021 RefVal(Kind k, unsigned cnt = 0) : kind(k), Cnt(cnt) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001022
1023public:
Ted Kremenekdb863712008-04-16 22:32:20 +00001024
Ted Kremenek4fd88972008-04-17 18:12:53 +00001025 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001026
Ted Kremenek553cf182008-06-25 21:21:56 +00001027 unsigned getCount() const { return Cnt; }
1028 QualType getType() const { return T; }
Ted Kremenek4fd88972008-04-17 18:12:53 +00001029
1030 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001031
Ted Kremenek73c750b2008-03-11 18:14:09 +00001032 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
1033
Ted Kremenekdb863712008-04-16 22:32:20 +00001034 static bool isLeak(Kind k) { return k == ErrorLeak; }
1035
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001036 bool isOwned() const {
1037 return getKind() == Owned;
1038 }
1039
Ted Kremenekdb863712008-04-16 22:32:20 +00001040 bool isNotOwned() const {
1041 return getKind() == NotOwned;
1042 }
1043
Ted Kremenek4fd88972008-04-17 18:12:53 +00001044 bool isReturnedOwned() const {
1045 return getKind() == ReturnedOwned;
1046 }
1047
1048 bool isReturnedNotOwned() const {
1049 return getKind() == ReturnedNotOwned;
1050 }
1051
1052 bool isNonLeakError() const {
1053 Kind k = getKind();
1054 return isError(k) && !isLeak(k);
1055 }
1056
1057 // State creation: normal state.
1058
Ted Kremenek553cf182008-06-25 21:21:56 +00001059 static RefVal makeOwned(QualType t, unsigned Count = 1) {
1060 return RefVal(Owned, Count, t);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001061 }
1062
Ted Kremenek553cf182008-06-25 21:21:56 +00001063 static RefVal makeNotOwned(QualType t, unsigned Count = 0) {
1064 return RefVal(NotOwned, Count, t);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001065 }
Ted Kremenek4fd88972008-04-17 18:12:53 +00001066
1067 static RefVal makeReturnedOwned(unsigned Count) {
1068 return RefVal(ReturnedOwned, Count);
1069 }
1070
1071 static RefVal makeReturnedNotOwned() {
1072 return RefVal(ReturnedNotOwned);
1073 }
1074
1075 // State creation: errors.
Ted Kremenek553cf182008-06-25 21:21:56 +00001076
1077#if 0
Ted Kremenekce48e002008-05-05 17:53:17 +00001078 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001079 static RefVal makeReleased() { return RefVal(Released); }
1080 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
1081 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek553cf182008-06-25 21:21:56 +00001082#endif
1083
Ted Kremenek4fd88972008-04-17 18:12:53 +00001084 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001085
Ted Kremenek4fd88972008-04-17 18:12:53 +00001086 bool operator==(const RefVal& X) const {
Ted Kremenek553cf182008-06-25 21:21:56 +00001087 return kind == X.kind && Cnt == X.Cnt && T == X.T;
Ted Kremenek4fd88972008-04-17 18:12:53 +00001088 }
Ted Kremenekf3948042008-03-11 19:44:10 +00001089
Ted Kremenek553cf182008-06-25 21:21:56 +00001090 RefVal operator-(size_t i) const {
1091 return RefVal(getKind(), getCount() - i, getType());
1092 }
1093
1094 RefVal operator+(size_t i) const {
1095 return RefVal(getKind(), getCount() + i, getType());
1096 }
1097
1098 RefVal operator^(Kind k) const {
1099 return RefVal(k, getCount(), getType());
1100 }
1101
1102
Ted Kremenek4fd88972008-04-17 18:12:53 +00001103 void Profile(llvm::FoldingSetNodeID& ID) const {
1104 ID.AddInteger((unsigned) kind);
1105 ID.AddInteger(Cnt);
Ted Kremenek553cf182008-06-25 21:21:56 +00001106 ID.Add(T);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001107 }
1108
Ted Kremenekf3948042008-03-11 19:44:10 +00001109 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001110};
Ted Kremenekf3948042008-03-11 19:44:10 +00001111
1112void RefVal::print(std::ostream& Out) const {
Ted Kremenek553cf182008-06-25 21:21:56 +00001113 if (!T.isNull())
1114 Out << "Tracked Type:" << T.getAsString() << '\n';
1115
Ted Kremenekf3948042008-03-11 19:44:10 +00001116 switch (getKind()) {
1117 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001118 case Owned: {
1119 Out << "Owned";
1120 unsigned cnt = getCount();
1121 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +00001122 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001123 }
Ted Kremenekf3948042008-03-11 19:44:10 +00001124
Ted Kremenek61b9f872008-04-10 23:09:18 +00001125 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001126 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +00001127 unsigned cnt = getCount();
1128 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +00001129 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001130 }
Ted Kremenekf3948042008-03-11 19:44:10 +00001131
Ted Kremenek4fd88972008-04-17 18:12:53 +00001132 case ReturnedOwned: {
1133 Out << "ReturnedOwned";
1134 unsigned cnt = getCount();
1135 if (cnt) Out << " (+ " << cnt << ")";
1136 break;
1137 }
1138
1139 case ReturnedNotOwned: {
1140 Out << "ReturnedNotOwned";
1141 unsigned cnt = getCount();
1142 if (cnt) Out << " (+ " << cnt << ")";
1143 break;
1144 }
1145
Ted Kremenekf3948042008-03-11 19:44:10 +00001146 case Released:
1147 Out << "Released";
1148 break;
1149
Ted Kremenekdb863712008-04-16 22:32:20 +00001150 case ErrorLeak:
1151 Out << "Leaked";
1152 break;
1153
Ted Kremenekf3948042008-03-11 19:44:10 +00001154 case ErrorUseAfterRelease:
1155 Out << "Use-After-Release [ERROR]";
1156 break;
1157
1158 case ErrorReleaseNotOwned:
1159 Out << "Release of Not-Owned [ERROR]";
1160 break;
1161 }
1162}
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001163
Ted Kremenek13922612008-04-16 20:40:59 +00001164//===----------------------------------------------------------------------===//
1165// Transfer functions.
1166//===----------------------------------------------------------------------===//
1167
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001168class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001169public:
Ted Kremenek553cf182008-06-25 21:21:56 +00001170 // Type definitions.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001171 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek553cf182008-06-25 21:21:56 +00001172
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001173 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +00001174
Ted Kremenek8dd56462008-04-18 03:39:05 +00001175 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
1176 ReleasesNotOwnedTy;
1177
1178 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
1179
1180 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +00001181 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001182
Ted Kremenekf3948042008-03-11 19:44:10 +00001183 class BindingsPrinter : public ValueState::CheckerStatePrinter {
1184 public:
1185 virtual void PrintCheckerState(std::ostream& Out, void* State,
1186 const char* nl, const char* sep);
1187 };
Ted Kremenek8dd56462008-04-18 03:39:05 +00001188
1189private:
Ted Kremenekf3948042008-03-11 19:44:10 +00001190 // Instance variables.
1191
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001192 RetainSummaryManager Summaries;
1193 const bool EmitStandardWarnings;
1194 const LangOptions& LOpts;
1195 RefBFactoryTy RefBFactory;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001196
Ted Kremenek73c750b2008-03-11 18:14:09 +00001197 UseAfterReleasesTy UseAfterReleases;
1198 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +00001199 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +00001200
Ted Kremenekf3948042008-03-11 19:44:10 +00001201 BindingsPrinter Printer;
1202
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001203 Selector RetainSelector;
1204 Selector ReleaseSelector;
Ted Kremenek5934cee2008-05-01 02:18:37 +00001205 Selector AutoreleaseSelector;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001206
Ted Kremenek8dd56462008-04-18 03:39:05 +00001207public:
1208
Ted Kremenek4323a572008-07-10 22:03:41 +00001209 static RefBindings GetRefBindings(const ValueState& StImpl) {
1210 return RefBindings((const RefBindings::TreeTy*) StImpl.CheckerState);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001211 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001212
Ted Kremenek8dd56462008-04-18 03:39:05 +00001213private:
1214
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001215 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
1216 StImpl.CheckerState = B.getRoot();
1217 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001218
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001219 RefBindings Remove(RefBindings B, SymbolID sym) {
1220 return RefBFactory.Remove(B, sym);
1221 }
1222
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001223 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001224 RefVal::Kind& hasErr);
1225
Ted Kremenekdb863712008-04-16 22:32:20 +00001226 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
1227 GRStmtNodeBuilder<ValueState>& Builder,
1228 Expr* NodeExpr, Expr* ErrorExpr,
1229 ExplodedNode<ValueState>* Pred,
Ted Kremenek4323a572008-07-10 22:03:41 +00001230 const ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001231 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +00001232
Ted Kremenek4323a572008-07-10 22:03:41 +00001233 const ValueState* HandleSymbolDeath(ValueStateManager& VMgr,
1234 const ValueState* St,
1235 SymbolID sid, RefVal V, bool& hasLeak);
Ted Kremenekdb863712008-04-16 22:32:20 +00001236
Ted Kremenek4323a572008-07-10 22:03:41 +00001237 const ValueState* NukeBinding(ValueStateManager& VMgr, const ValueState* St,
1238 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001239
1240public:
Ted Kremenek13922612008-04-16 20:40:59 +00001241
Ted Kremenek9f741612008-05-02 18:01:49 +00001242 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
1243 const LangOptions& lopts)
Ted Kremenek377e2302008-04-29 05:33:51 +00001244 : Summaries(Ctx, gcenabled),
Ted Kremenek9f741612008-05-02 18:01:49 +00001245 EmitStandardWarnings(StandardWarnings),
Ted Kremenek072192b2008-04-30 23:47:44 +00001246 LOpts(lopts),
Ted Kremenekb83e02e2008-05-01 18:31:44 +00001247 RetainSelector(GetNullarySelector("retain", Ctx)),
1248 ReleaseSelector(GetNullarySelector("release", Ctx)),
1249 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001250
Ted Kremenek8dd56462008-04-18 03:39:05 +00001251 virtual ~CFRefCount() {
1252 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
1253 delete I->second;
1254 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001255
1256 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +00001257
1258 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
1259 return &Printer;
1260 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001261
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001262 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenek072192b2008-04-30 23:47:44 +00001263 const LangOptions& getLangOptions() const { return LOpts; }
1264
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001265 // Calls.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001266
1267 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1268 GRExprEngine& Eng,
1269 GRStmtNodeBuilder<ValueState>& Builder,
1270 Expr* Ex,
1271 Expr* Receiver,
1272 RetainSummary* Summ,
Ted Kremenek55499762008-06-17 02:43:46 +00001273 ExprIterator arg_beg, ExprIterator arg_end,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001274 ExplodedNode<ValueState>* Pred);
1275
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001276 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +00001277 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001278 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +00001279 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001280 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001281
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001282
Ted Kremenek85348202008-04-15 23:44:31 +00001283 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1284 GRExprEngine& Engine,
1285 GRStmtNodeBuilder<ValueState>& Builder,
1286 ObjCMessageExpr* ME,
1287 ExplodedNode<ValueState>* Pred);
1288
1289 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1290 GRExprEngine& Engine,
1291 GRStmtNodeBuilder<ValueState>& Builder,
1292 ObjCMessageExpr* ME,
1293 ExplodedNode<ValueState>* Pred);
1294
Ted Kremenek13922612008-04-16 20:40:59 +00001295 // Stores.
1296
1297 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
1298 GRExprEngine& Engine,
1299 GRStmtNodeBuilder<ValueState>& Builder,
1300 Expr* E, ExplodedNode<ValueState>* Pred,
Ted Kremenek4323a572008-07-10 22:03:41 +00001301 const ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001302 // End-of-path.
1303
1304 virtual void EvalEndPath(GRExprEngine& Engine,
1305 GREndPathNodeBuilder<ValueState>& Builder);
1306
Ted Kremenek652adc62008-04-24 23:57:27 +00001307 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1308 GRExprEngine& Engine,
1309 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001310 ExplodedNode<ValueState>* Pred,
1311 Stmt* S,
Ted Kremenek4323a572008-07-10 22:03:41 +00001312 const ValueState* St,
Ted Kremenek652adc62008-04-24 23:57:27 +00001313 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001314 // Return statements.
1315
1316 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1317 GRExprEngine& Engine,
1318 GRStmtNodeBuilder<ValueState>& Builder,
1319 ReturnStmt* S,
1320 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +00001321
1322 // Assumptions.
1323
Ted Kremenek4323a572008-07-10 22:03:41 +00001324 virtual const ValueState* EvalAssume(GRExprEngine& Engine,
1325 const ValueState* St, RVal Cond,
1326 bool Assumption, bool& isFeasible);
Ted Kremenekcb612922008-04-18 19:23:43 +00001327
Ted Kremenekfa34b332008-04-09 01:10:13 +00001328 // Error iterators.
1329
1330 typedef UseAfterReleasesTy::iterator use_after_iterator;
1331 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +00001332 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +00001333
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001334 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
1335 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +00001336
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001337 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
1338 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +00001339
1340 leaks_iterator leaks_begin() { return Leaks.begin(); }
1341 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001342};
1343
1344} // end anonymous namespace
1345
Ted Kremenek8dd56462008-04-18 03:39:05 +00001346
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001347
1348
Ted Kremenekf3948042008-03-11 19:44:10 +00001349void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
1350 void* State, const char* nl,
1351 const char* sep) {
1352 RefBindings B((RefBindings::TreeTy*) State);
1353
1354 if (State)
1355 Out << sep << nl;
1356
1357 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1358 Out << (*I).first << " : ";
1359 (*I).second.print(Out);
1360 Out << nl;
1361 }
1362}
1363
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001364static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00001365 return Summ ? Summ->getArg(idx) : MayEscape;
Ted Kremenekf9561e52008-04-11 20:23:24 +00001366}
1367
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001368static inline RetEffect GetRetEffect(RetainSummary* Summ) {
1369 return Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001370}
1371
Ted Kremenek14993892008-05-06 02:41:27 +00001372static inline ArgEffect GetReceiverE(RetainSummary* Summ) {
1373 return Summ ? Summ->getReceiverEffect() : DoNothing;
1374}
1375
Ted Kremenekdb863712008-04-16 22:32:20 +00001376void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
1377 GRStmtNodeBuilder<ValueState>& Builder,
1378 Expr* NodeExpr, Expr* ErrorExpr,
1379 ExplodedNode<ValueState>* Pred,
Ted Kremenek4323a572008-07-10 22:03:41 +00001380 const ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001381 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001382 Builder.BuildSinks = true;
1383 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
1384
1385 if (!N) return;
1386
1387 switch (hasErr) {
1388 default: assert(false);
1389 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001390 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001391 break;
1392
1393 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001394 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001395 break;
1396 }
1397}
1398
Ted Kremenek553cf182008-06-25 21:21:56 +00001399/// GetReturnType - Used to get the return type of a message expression or
1400/// function call with the intention of affixing that type to a tracked symbol.
1401/// While the the return type can be queried directly from RetEx, when
1402/// invoking class methods we augment to the return type to be that of
1403/// a pointer to the class (as opposed it just being id).
1404static QualType GetReturnType(Expr* RetE, ASTContext& Ctx) {
1405
1406 QualType RetTy = RetE->getType();
1407
1408 // FIXME: We aren't handling id<...>.
1409 const PointerType* PT = RetTy.getCanonicalType()->getAsPointerType();
1410
1411 if (!PT)
1412 return RetTy;
1413
1414 // If RetEx is not a message expression just return its type.
1415 // If RetEx is a message expression, return its types if it is something
1416 /// more specific than id.
1417
1418 ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(RetE);
1419
1420 if (!ME || !Ctx.isObjCIdType(PT->getPointeeType()))
1421 return RetTy;
1422
1423 ObjCInterfaceDecl* D = ME->getClassInfo().first;
1424
1425 // At this point we know the return type of the message expression is id.
1426 // If we have an ObjCInterceDecl, we know this is a call to a class method
1427 // whose type we can resolve. In such cases, promote the return type to
1428 // Class*.
1429 return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D));
1430}
1431
1432
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001433void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1434 GRExprEngine& Eng,
1435 GRStmtNodeBuilder<ValueState>& Builder,
1436 Expr* Ex,
1437 Expr* Receiver,
1438 RetainSummary* Summ,
Ted Kremenek55499762008-06-17 02:43:46 +00001439 ExprIterator arg_beg, ExprIterator arg_end,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001440 ExplodedNode<ValueState>* Pred) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001441
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001442 // Get the state.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001443 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek4323a572008-07-10 22:03:41 +00001444 const ValueState* St = Builder.GetState(Pred);
Ted Kremenek14993892008-05-06 02:41:27 +00001445
1446 // Evaluate the effect of the arguments.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001447 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001448 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001449 unsigned idx = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001450 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001451 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001452
Ted Kremenek55499762008-06-17 02:43:46 +00001453 for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001454
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001455 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001456
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001457 if (isa<lval::SymbolVal>(V)) {
1458 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001459 RefBindings B = GetRefBindings(StVals);
1460
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001461 if (RefBindings::data_type* T = B.lookup(Sym)) {
1462 B = Update(B, Sym, *T, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001463 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001464
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001465 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001466 ErrorExpr = *I;
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001467 ErrorSym = Sym;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001468 break;
1469 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001470 }
Ted Kremenekb8873552008-04-11 20:51:02 +00001471 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001472 else if (isa<LVal>(V)) {
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001473#if 0
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001474 // Nuke all arguments passed by reference.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001475 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001476#else
Ted Kremenek070a8252008-07-09 18:11:16 +00001477 if (lval::DeclVal* DV = dyn_cast<lval::DeclVal>(&V)) {
1478
1479 if (GetArgE(Summ, idx) == DoNothingByRef)
1480 continue;
1481
1482 // Invalidate the value of the variable passed by reference.
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001483
1484 // FIXME: Either this logic should also be replicated in GRSimpleVals
1485 // or should be pulled into a separate "constraint engine."
Ted Kremenek070a8252008-07-09 18:11:16 +00001486
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001487 // FIXME: We can have collisions on the conjured symbol if the
1488 // expression *I also creates conjured symbols. We probably want
1489 // to identify conjured symbols by an expression pair: the enclosing
1490 // expression (the context) and the expression itself. This should
Ted Kremenek070a8252008-07-09 18:11:16 +00001491 // disambiguate conjured symbols.
1492
1493 // Is the invalidated variable something that we were tracking?
1494 RVal X = StateMgr.GetRVal(&StVals, *DV);
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001495
Ted Kremenek070a8252008-07-09 18:11:16 +00001496 if (isa<lval::SymbolVal>(X)) {
1497 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
1498 SetRefBindings(StVals,RefBFactory.Remove(GetRefBindings(StVals),Sym));
1499 }
1500
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001501 // Set the value of the variable to be a conjured symbol.
1502 unsigned Count = Builder.getCurrentBlockCount();
1503 SymbolID NewSym = Eng.getSymbolManager().getConjuredSymbol(*I, Count);
1504
Ted Kremenek4323a572008-07-10 22:03:41 +00001505 StateMgr.SetRVal(StVals, *DV,
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001506 LVal::IsLValType(DV->getDecl()->getType())
1507 ? cast<RVal>(lval::SymbolVal(NewSym))
1508 : cast<RVal>(nonlval::SymbolVal(NewSym)));
1509 }
1510 else {
1511 // Nuke all other arguments passed by reference.
1512 StateMgr.Unbind(StVals, cast<LVal>(V));
1513 }
1514#endif
Ted Kremenekb8873552008-04-11 20:51:02 +00001515 }
Ted Kremeneka5488462008-04-22 21:39:21 +00001516 else if (isa<nonlval::LValAsInteger>(V))
1517 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001518 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001519
Ted Kremenek553cf182008-06-25 21:21:56 +00001520 // Evaluate the effect on the message receiver.
Ted Kremenek14993892008-05-06 02:41:27 +00001521 if (!ErrorExpr && Receiver) {
1522 RVal V = StateMgr.GetRVal(St, Receiver);
1523
1524 if (isa<lval::SymbolVal>(V)) {
1525 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1526 RefBindings B = GetRefBindings(StVals);
1527
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001528 if (const RefVal* T = B.lookup(Sym)) {
1529 B = Update(B, Sym, *T, GetReceiverE(Summ), hasErr);
Ted Kremenek14993892008-05-06 02:41:27 +00001530 SetRefBindings(StVals, B);
1531
1532 if (hasErr) {
1533 ErrorExpr = Receiver;
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001534 ErrorSym = Sym;
Ted Kremenek14993892008-05-06 02:41:27 +00001535 }
1536 }
1537 }
1538 }
1539
Ted Kremenek553cf182008-06-25 21:21:56 +00001540 // Get the persistent state.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001541 St = StateMgr.getPersistentState(StVals);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001542
Ted Kremenek553cf182008-06-25 21:21:56 +00001543 // Process any errors.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001544 if (hasErr) {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001545 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001546 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001547 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001548 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001549
Ted Kremenek553cf182008-06-25 21:21:56 +00001550 // Finally, consult the summary for the return value.
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001551 RetEffect RE = GetRetEffect(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001552
1553 switch (RE.getKind()) {
1554 default:
1555 assert (false && "Unhandled RetEffect."); break;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001556
Ted Kremenek940b1d82008-04-10 23:44:06 +00001557 case RetEffect::NoRet:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001558
Ted Kremenekf9561e52008-04-11 20:23:24 +00001559 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +00001560 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1561 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001562
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001563 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001564 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001565 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001566
Ted Kremenek0e470a52008-05-09 23:45:33 +00001567 RVal X = LVal::IsLValType(Ex->getType())
1568 ? cast<RVal>(lval::SymbolVal(Sym))
1569 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenekf9561e52008-04-11 20:23:24 +00001570
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001571 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001572 }
1573
Ted Kremenek940b1d82008-04-10 23:44:06 +00001574 break;
1575
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001576 case RetEffect::Alias: {
Ted Kremenek553cf182008-06-25 21:21:56 +00001577 unsigned idx = RE.getIndex();
Ted Kremenek55499762008-06-17 02:43:46 +00001578 assert (arg_end >= arg_beg);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001579 assert (idx < (unsigned) (arg_end - arg_beg));
Ted Kremenek55499762008-06-17 02:43:46 +00001580 RVal V = StateMgr.GetRVal(St, *(arg_beg+idx));
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001581 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001582 break;
1583 }
1584
Ted Kremenek14993892008-05-06 02:41:27 +00001585 case RetEffect::ReceiverAlias: {
1586 assert (Receiver);
1587 RVal V = StateMgr.GetRVal(St, Receiver);
1588 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
1589 break;
1590 }
1591
Ted Kremeneka7344702008-06-23 18:02:52 +00001592 case RetEffect::OwnedAllocatedSymbol:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001593 case RetEffect::OwnedSymbol: {
1594 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001595 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek553cf182008-06-25 21:21:56 +00001596 QualType RetT = GetReturnType(Ex, Eng.getContext());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001597
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001598 ValueState StImpl = *St;
1599 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek553cf182008-06-25 21:21:56 +00001600 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned(RetT)));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001601
1602 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001603 Ex, lval::SymbolVal(Sym),
1604 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001605
Ted Kremeneka7344702008-06-23 18:02:52 +00001606 // FIXME: Add a flag to the checker where allocations are allowed to fail.
1607 if (RE.getKind() == RetEffect::OwnedAllocatedSymbol)
1608 St = StateMgr.AddNE(St, Sym, Eng.getBasicVals().getZeroWithPtrWidth());
1609
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001610 break;
1611 }
1612
1613 case RetEffect::NotOwnedSymbol: {
1614 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001615 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek553cf182008-06-25 21:21:56 +00001616 QualType RetT = GetReturnType(Ex, Eng.getContext());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001617
1618 ValueState StImpl = *St;
1619 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek553cf182008-06-25 21:21:56 +00001620 SetRefBindings(StImpl, RefBFactory.Add(B, Sym,
1621 RefVal::makeNotOwned(RetT)));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001622
1623 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001624 Ex, lval::SymbolVal(Sym),
1625 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001626
1627 break;
1628 }
1629 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001630
1631 Builder.MakeNode(Dst, Ex, Pred, St);
1632}
1633
1634
1635void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1636 GRExprEngine& Eng,
1637 GRStmtNodeBuilder<ValueState>& Builder,
1638 CallExpr* CE, RVal L,
1639 ExplodedNode<ValueState>* Pred) {
1640
1641
1642 RetainSummary* Summ = NULL;
1643
1644 // Get the summary.
1645
1646 if (isa<lval::FuncVal>(L)) {
1647 lval::FuncVal FV = cast<lval::FuncVal>(L);
1648 FunctionDecl* FD = FV.getDecl();
Ted Kremenekab592272008-06-24 03:56:45 +00001649 Summ = Summaries.getSummary(FD);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001650 }
1651
1652 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1653 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001654}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001655
Ted Kremenek85348202008-04-15 23:44:31 +00001656
1657void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1658 GRExprEngine& Eng,
1659 GRStmtNodeBuilder<ValueState>& Builder,
1660 ObjCMessageExpr* ME,
1661 ExplodedNode<ValueState>* Pred) {
1662
Ted Kremenekb3095252008-05-06 04:20:12 +00001663 RetainSummary* Summ;
Ted Kremenek9040c652008-05-01 21:31:50 +00001664
Ted Kremenek553cf182008-06-25 21:21:56 +00001665 if (Expr* Receiver = ME->getReceiver()) {
1666 // We need the type-information of the tracked receiver object
1667 // Retrieve it from the state.
1668 ObjCInterfaceDecl* ID = 0;
1669
1670 // FIXME: Wouldn't it be great if this code could be reduced? It's just
1671 // a chain of lookups.
Ted Kremenek4323a572008-07-10 22:03:41 +00001672 const ValueState* St = Builder.GetState(Pred);
Ted Kremenek553cf182008-06-25 21:21:56 +00001673 RVal V = Eng.getStateManager().GetRVal(St, Receiver );
1674
1675 if (isa<lval::SymbolVal>(V)) {
1676 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1677
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001678 if (const RefVal* T = GetRefBindings(*St).lookup(Sym)) {
1679 QualType Ty = T->getType();
Ted Kremenek553cf182008-06-25 21:21:56 +00001680
1681 if (const PointerType* PT = Ty->getAsPointerType()) {
1682 QualType PointeeTy = PT->getPointeeType();
1683
1684 if (ObjCInterfaceType* IT = dyn_cast<ObjCInterfaceType>(PointeeTy))
1685 ID = IT->getDecl();
1686 }
1687 }
1688 }
1689
1690 Summ = Summaries.getMethodSummary(ME, ID);
1691 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001692 else
Ted Kremenek1f180c32008-06-23 22:21:20 +00001693 Summ = Summaries.getClassMethodSummary(ME->getClassName(),
1694 ME->getSelector());
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001695
Ted Kremenekb3095252008-05-06 04:20:12 +00001696 EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
1697 ME->arg_begin(), ME->arg_end(), Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001698}
Ted Kremenekb3095252008-05-06 04:20:12 +00001699
Ted Kremenek13922612008-04-16 20:40:59 +00001700// Stores.
1701
1702void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1703 GRExprEngine& Eng,
1704 GRStmtNodeBuilder<ValueState>& Builder,
1705 Expr* E, ExplodedNode<ValueState>* Pred,
Ted Kremenek4323a572008-07-10 22:03:41 +00001706 const ValueState* St, RVal TargetLV, RVal Val) {
Ted Kremenek13922612008-04-16 20:40:59 +00001707
1708 // Check if we have a binding for "Val" and if we are storing it to something
1709 // we don't understand or otherwise the value "escapes" the function.
1710
1711 if (!isa<lval::SymbolVal>(Val))
1712 return;
1713
1714 // Are we storing to something that causes the value to "escape"?
1715
1716 bool escapes = false;
1717
1718 if (!isa<lval::DeclVal>(TargetLV))
1719 escapes = true;
1720 else
1721 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1722
1723 if (!escapes)
1724 return;
1725
1726 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
Ted Kremenek13922612008-04-16 20:40:59 +00001727
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001728 if (!GetRefBindings(*St).lookup(Sym))
Ted Kremenek13922612008-04-16 20:40:59 +00001729 return;
1730
Ted Kremenekdb863712008-04-16 22:32:20 +00001731 // Nuke the binding.
1732 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001733
1734 // Hand of the remaining logic to the parent implementation.
1735 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1736}
1737
Ted Kremenekdb863712008-04-16 22:32:20 +00001738
Ted Kremenek4323a572008-07-10 22:03:41 +00001739const ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr,
1740 const ValueState* St,
1741 SymbolID sid) {
Ted Kremenekdb863712008-04-16 22:32:20 +00001742 ValueState StImpl = *St;
1743 RefBindings B = GetRefBindings(StImpl);
1744 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1745 return VMgr.getPersistentState(StImpl);
1746}
1747
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001748// End-of-path.
1749
Ted Kremenek4323a572008-07-10 22:03:41 +00001750const ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1751 const ValueState* St, SymbolID sid,
Ted Kremenekdb863712008-04-16 22:32:20 +00001752 RefVal V, bool& hasLeak) {
1753
Ted Kremenek4fd88972008-04-17 18:12:53 +00001754 hasLeak = V.isOwned() ||
1755 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001756
1757 if (!hasLeak)
1758 return NukeBinding(VMgr, St, sid);
1759
1760 RefBindings B = GetRefBindings(*St);
Ted Kremenek553cf182008-06-25 21:21:56 +00001761 ValueState StImpl = *St;
1762 StImpl.CheckerState = RefBFactory.Add(B, sid, V^RefVal::ErrorLeak).getRoot();
Ted Kremenekce48e002008-05-05 17:53:17 +00001763
Ted Kremenekdb863712008-04-16 22:32:20 +00001764 return VMgr.getPersistentState(StImpl);
1765}
1766
1767void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001768 GREndPathNodeBuilder<ValueState>& Builder) {
1769
Ted Kremenek4323a572008-07-10 22:03:41 +00001770 const ValueState* St = Builder.getState();
Ted Kremenekdb863712008-04-16 22:32:20 +00001771 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001772
Ted Kremenekdb863712008-04-16 22:32:20 +00001773 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001774
Ted Kremenekdb863712008-04-16 22:32:20 +00001775 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1776 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001777
Ted Kremenekdb863712008-04-16 22:32:20 +00001778 St = HandleSymbolDeath(Eng.getStateManager(), St,
1779 (*I).first, (*I).second, hasLeak);
1780
1781 if (hasLeak) Leaked.push_back((*I).first);
1782 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001783
1784 if (Leaked.empty())
1785 return;
1786
Ted Kremenek8dd56462008-04-18 03:39:05 +00001787 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001788
Ted Kremenek652adc62008-04-24 23:57:27 +00001789 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001790 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001791
Ted Kremenek8dd56462008-04-18 03:39:05 +00001792 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1793 assert (!LeaksAtNode);
1794 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001795
1796 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1797 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001798 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001799}
1800
Ted Kremenek652adc62008-04-24 23:57:27 +00001801// Dead symbols.
1802
1803void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1804 GRExprEngine& Eng,
1805 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001806 ExplodedNode<ValueState>* Pred,
1807 Stmt* S,
Ted Kremenek4323a572008-07-10 22:03:41 +00001808 const ValueState* St,
Ted Kremenek652adc62008-04-24 23:57:27 +00001809 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001810
Ted Kremenek652adc62008-04-24 23:57:27 +00001811 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1812
1813 RefBindings B = GetRefBindings(*St);
1814 llvm::SmallVector<SymbolID, 10> Leaked;
1815
1816 for (ValueStateManager::DeadSymbolsTy::const_iterator
1817 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1818
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001819 const RefVal* T = B.lookup(*I);
Ted Kremenek652adc62008-04-24 23:57:27 +00001820
1821 if (!T)
1822 continue;
1823
1824 bool hasLeak = false;
1825
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001826 St = HandleSymbolDeath(Eng.getStateManager(), St, *I, *T, hasLeak);
Ted Kremenek652adc62008-04-24 23:57:27 +00001827
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001828 if (hasLeak)
1829 Leaked.push_back(*I);
Ted Kremenek652adc62008-04-24 23:57:27 +00001830 }
1831
1832 if (Leaked.empty())
1833 return;
1834
1835 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1836
1837 if (!N)
1838 return;
1839
1840 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1841 assert (!LeaksAtNode);
1842 LeaksAtNode = new std::vector<SymbolID>();
1843
1844 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1845 E = Leaked.end(); I != E; ++I)
1846 (*LeaksAtNode).push_back(*I);
1847}
1848
Ted Kremenek4fd88972008-04-17 18:12:53 +00001849 // Return statements.
1850
1851void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1852 GRExprEngine& Eng,
1853 GRStmtNodeBuilder<ValueState>& Builder,
1854 ReturnStmt* S,
1855 ExplodedNode<ValueState>* Pred) {
1856
1857 Expr* RetE = S->getRetValue();
1858 if (!RetE) return;
1859
1860 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek4323a572008-07-10 22:03:41 +00001861 const ValueState* St = Builder.GetState(Pred);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001862 RVal V = StateMgr.GetRVal(St, RetE);
1863
1864 if (!isa<lval::SymbolVal>(V))
1865 return;
1866
1867 // Get the reference count binding (if any).
1868 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1869 RefBindings B = GetRefBindings(*St);
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001870 const RefVal* T = B.lookup(Sym);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001871
1872 if (!T)
1873 return;
1874
1875 // Change the reference count.
1876
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001877 RefVal X = *T;
Ted Kremenek4fd88972008-04-17 18:12:53 +00001878
1879 switch (X.getKind()) {
1880
1881 case RefVal::Owned: {
1882 unsigned cnt = X.getCount();
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00001883 assert (cnt > 0);
1884 X = RefVal::makeReturnedOwned(cnt - 1);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001885 break;
1886 }
1887
1888 case RefVal::NotOwned: {
1889 unsigned cnt = X.getCount();
1890 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1891 : RefVal::makeReturnedNotOwned();
1892 break;
1893 }
1894
1895 default:
Ted Kremenek4fd88972008-04-17 18:12:53 +00001896 return;
1897 }
1898
1899 // Update the binding.
1900
1901 ValueState StImpl = *St;
1902 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1903 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1904}
1905
Ted Kremenekcb612922008-04-18 19:23:43 +00001906// Assumptions.
1907
Ted Kremenek4323a572008-07-10 22:03:41 +00001908const ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng,
1909 const ValueState* St,
1910 RVal Cond, bool Assumption,
1911 bool& isFeasible) {
Ted Kremenekcb612922008-04-18 19:23:43 +00001912
1913 // FIXME: We may add to the interface of EvalAssume the list of symbols
1914 // whose assumptions have changed. For now we just iterate through the
1915 // bindings and check if any of the tracked symbols are NULL. This isn't
1916 // too bad since the number of symbols we will track in practice are
1917 // probably small and EvalAssume is only called at branches and a few
1918 // other places.
1919
1920 RefBindings B = GetRefBindings(*St);
1921
1922 if (B.isEmpty())
1923 return St;
1924
1925 bool changed = false;
1926
1927 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1928
1929 // Check if the symbol is null (or equal to any constant).
1930 // If this is the case, stop tracking the symbol.
1931
1932 if (St->getSymVal(I.getKey())) {
1933 changed = true;
1934 B = RefBFactory.Remove(B, I.getKey());
1935 }
1936 }
1937
1938 if (!changed)
1939 return St;
1940
1941 ValueState StImpl = *St;
1942 StImpl.CheckerState = B.getRoot();
1943 return Eng.getStateManager().getPersistentState(StImpl);
1944}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001945
1946CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001947 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001948 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001949
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001950 // FIXME: This dispatch can potentially be sped up by unifiying it into
1951 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001952
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001953 switch (E) {
1954 default:
1955 assert (false && "Unhandled CFRef transition.");
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00001956
1957 case MayEscape:
1958 if (V.getKind() == RefVal::Owned) {
Ted Kremenek553cf182008-06-25 21:21:56 +00001959 V = V ^ RefVal::NotOwned;
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00001960 break;
1961 }
1962
1963 // Fall-through.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001964
Ted Kremenek070a8252008-07-09 18:11:16 +00001965 case DoNothingByRef:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001966 case DoNothing:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001967 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenek553cf182008-06-25 21:21:56 +00001968 V = V ^ RefVal::ErrorUseAfterRelease;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001969 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001970 break;
1971 }
1972
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001973 return B;
Ted Kremeneke19f4492008-06-30 16:57:41 +00001974
Ted Kremenek80d753f2008-07-01 00:01:02 +00001975 case Autorelease:
Ted Kremenek14993892008-05-06 02:41:27 +00001976 case StopTracking:
1977 return RefBFactory.Remove(B, sym);
1978
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001979 case IncRef:
1980 switch (V.getKind()) {
1981 default:
1982 assert(false);
1983
1984 case RefVal::Owned:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001985 case RefVal::NotOwned:
Ted Kremenek553cf182008-06-25 21:21:56 +00001986 V = V + 1;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001987 break;
1988
1989 case RefVal::Released:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001990 if (isGCEnabled())
Ted Kremenek553cf182008-06-25 21:21:56 +00001991 V = V ^ RefVal::Owned;
Ted Kremenek65c91652008-04-29 05:44:10 +00001992 else {
Ted Kremenek553cf182008-06-25 21:21:56 +00001993 V = V ^ RefVal::ErrorUseAfterRelease;
Ted Kremenek65c91652008-04-29 05:44:10 +00001994 hasErr = V.getKind();
1995 }
1996
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001997 break;
1998 }
1999
Ted Kremenek940b1d82008-04-10 23:44:06 +00002000 break;
2001
Ted Kremenek553cf182008-06-25 21:21:56 +00002002 case SelfOwn:
2003 V = V ^ RefVal::NotOwned;
2004
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002005 case DecRef:
2006 switch (V.getKind()) {
2007 default:
2008 assert (false);
2009
Ted Kremenek553cf182008-06-25 21:21:56 +00002010 case RefVal::Owned:
2011 V = V.getCount() > 1 ? V - 1 : V ^ RefVal::Released;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002012 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002013
Ted Kremenek553cf182008-06-25 21:21:56 +00002014 case RefVal::NotOwned:
2015 if (V.getCount() > 0)
2016 V = V - 1;
Ted Kremenek61b9f872008-04-10 23:09:18 +00002017 else {
Ted Kremenek553cf182008-06-25 21:21:56 +00002018 V = V ^ RefVal::ErrorReleaseNotOwned;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00002019 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00002020 }
2021
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002022 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002023
2024 case RefVal::Released:
Ted Kremenek553cf182008-06-25 21:21:56 +00002025 V = V ^ RefVal::ErrorUseAfterRelease;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00002026 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002027 break;
2028 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00002029
2030 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002031 }
2032
2033 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002034}
2035
Ted Kremenekfa34b332008-04-09 01:10:13 +00002036
2037//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002038// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00002039//===----------------------------------------------------------------------===//
2040
Ted Kremenek8dd56462008-04-18 03:39:05 +00002041namespace {
2042
2043 //===-------------===//
2044 // Bug Descriptions. //
2045 //===-------------===//
2046
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00002047 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00002048 protected:
2049 CFRefCount& TF;
2050
2051 public:
2052 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenek072192b2008-04-30 23:47:44 +00002053
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002054 CFRefCount& getTF() { return TF; }
Ted Kremenek789deac2008-05-05 23:16:31 +00002055 const CFRefCount& getTF() const { return TF; }
2056
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002057 virtual bool isLeak() const { return false; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00002058 };
2059
2060 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
2061 public:
2062 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
2063
2064 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00002065 return "Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002066 }
2067 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002068 return "Reference-counted object is used"
2069 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002070 }
2071
2072 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002073 };
2074
2075 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
2076 public:
2077 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
2078
2079 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00002080 return "Bad Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002081 }
2082 virtual const char* getDescription() const {
2083 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002084 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00002085 "The object is not owned at this point by the caller.";
2086 }
2087
2088 virtual void EmitWarnings(BugReporter& BR);
2089 };
2090
2091 class VISIBILITY_HIDDEN Leak : public CFRefBug {
2092 public:
2093 Leak(CFRefCount& tf) : CFRefBug(tf) {}
2094
2095 virtual const char* getName() const {
Ted Kremenek432af592008-05-06 18:11:36 +00002096
2097 if (getTF().isGCEnabled())
2098 return "Memory Leak (GC)";
2099
2100 if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
2101 return "Memory Leak (Hybrid MM, non-GC)";
2102
2103 assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
2104 return "Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002105 }
2106
2107 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002108 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002109 }
2110
2111 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002112 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002113 virtual bool isLeak() const { return true; }
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002114 virtual bool isCached(BugReport& R);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002115 };
2116
2117 //===---------===//
2118 // Bug Reports. //
2119 //===---------===//
2120
2121 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
2122 SymbolID Sym;
2123 public:
Ted Kremenek072192b2008-04-30 23:47:44 +00002124 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00002125 : RangedBugReport(D, n), Sym(sym) {}
2126
2127 virtual ~CFRefReport() {}
2128
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002129 CFRefBug& getBugType() {
2130 return (CFRefBug&) RangedBugReport::getBugType();
2131 }
2132 const CFRefBug& getBugType() const {
2133 return (const CFRefBug&) RangedBugReport::getBugType();
2134 }
2135
2136 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
2137 const SourceRange*& end) {
2138
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002139 if (!getBugType().isLeak())
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002140 RangedBugReport::getRanges(BR, beg, end);
2141 else {
2142 beg = 0;
2143 end = 0;
2144 }
2145 }
2146
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002147 SymbolID getSymbol() const { return Sym; }
2148
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002149 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
2150 ExplodedNode<ValueState>* N);
2151
Ted Kremenek072192b2008-04-30 23:47:44 +00002152 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek8dd56462008-04-18 03:39:05 +00002153
2154 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
2155 ExplodedNode<ValueState>* PrevN,
2156 ExplodedGraph<ValueState>& G,
2157 BugReporter& BR);
2158 };
2159
2160
2161} // end anonymous namespace
2162
2163void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek9f741612008-05-02 18:01:49 +00002164 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002165 Eng.Register(new UseAfterRelease(*this));
2166 Eng.Register(new BadRelease(*this));
2167 Eng.Register(new Leak(*this));
2168}
2169
Ted Kremenek072192b2008-04-30 23:47:44 +00002170
2171static const char* Msgs[] = {
2172 "Code is compiled in garbage collection only mode" // GC only
2173 " (the bug occurs with garbage collection enabled).",
2174
2175 "Code is compiled without garbage collection.", // No GC.
2176
2177 "Code is compiled for use with and without garbage collection (GC)."
2178 " The bug occurs with GC enabled.", // Hybrid, with GC.
2179
2180 "Code is compiled for use with and without garbage collection (GC)."
2181 " The bug occurs in non-GC mode." // Hyrbird, without GC/
2182};
2183
2184std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
2185 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
2186
2187 switch (TF.getLangOptions().getGCMode()) {
2188 default:
2189 assert(false);
Ted Kremenek31593ac2008-05-01 04:02:04 +00002190
2191 case LangOptions::GCOnly:
2192 assert (TF.isGCEnabled());
2193 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenek072192b2008-04-30 23:47:44 +00002194
2195 case LangOptions::NonGC:
2196 assert (!TF.isGCEnabled());
Ted Kremenek072192b2008-04-30 23:47:44 +00002197 return std::make_pair(&Msgs[1], &Msgs[1]+1);
2198
2199 case LangOptions::HybridGC:
2200 if (TF.isGCEnabled())
2201 return std::make_pair(&Msgs[2], &Msgs[2]+1);
2202 else
2203 return std::make_pair(&Msgs[3], &Msgs[3]+1);
2204 }
2205}
2206
Ted Kremenek8dd56462008-04-18 03:39:05 +00002207PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
2208 ExplodedNode<ValueState>* PrevN,
2209 ExplodedGraph<ValueState>& G,
2210 BugReporter& BR) {
2211
2212 // Check if the type state has changed.
2213
Ted Kremenek4323a572008-07-10 22:03:41 +00002214 const ValueState* PrevSt = PrevN->getState();
2215 const ValueState* CurrSt = N->getState();
Ted Kremenek8dd56462008-04-18 03:39:05 +00002216
2217 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
2218 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
2219
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002220 const RefVal* PrevT = PrevB.lookup(Sym);
2221 const RefVal* CurrT = CurrB.lookup(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002222
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002223 if (!CurrT)
2224 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00002225
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002226 const char* Msg = NULL;
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002227 const RefVal& CurrV = *CurrB.lookup(Sym);
Ted Kremenekce48e002008-05-05 17:53:17 +00002228
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002229 if (!PrevT) {
2230
Ted Kremenekce48e002008-05-05 17:53:17 +00002231 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2232
2233 if (CurrV.isOwned()) {
2234
2235 if (isa<CallExpr>(S))
2236 Msg = "Function call returns an object with a +1 retain count"
2237 " (owning reference).";
2238 else {
2239 assert (isa<ObjCMessageExpr>(S));
2240 Msg = "Method returns an object with a +1 retain count"
2241 " (owning reference).";
2242 }
2243 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002244 else {
2245 assert (CurrV.isNotOwned());
Ted Kremenekce48e002008-05-05 17:53:17 +00002246
2247 if (isa<CallExpr>(S))
2248 Msg = "Function call returns an object with a +0 retain count"
2249 " (non-owning reference).";
2250 else {
2251 assert (isa<ObjCMessageExpr>(S));
2252 Msg = "Method returns an object with a +0 retain count"
2253 " (non-owning reference).";
2254 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002255 }
Ted Kremenekce48e002008-05-05 17:53:17 +00002256
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002257 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
2258 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
2259
2260 if (Expr* Exp = dyn_cast<Expr>(S))
2261 P->addRange(Exp->getSourceRange());
2262
2263 return P;
2264 }
2265
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002266 // Determine if the typestate has changed.
2267 RefVal PrevV = *PrevB.lookup(Sym);
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002268
2269 if (PrevV == CurrV)
2270 return NULL;
2271
2272 // The typestate has changed.
2273
2274 std::ostringstream os;
2275
2276 switch (CurrV.getKind()) {
2277 case RefVal::Owned:
2278 case RefVal::NotOwned:
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002279
2280 if (PrevV.getCount() == CurrV.getCount())
2281 return 0;
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002282
2283 if (PrevV.getCount() > CurrV.getCount())
2284 os << "Reference count decremented.";
2285 else
2286 os << "Reference count incremented.";
2287
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002288 if (unsigned Count = CurrV.getCount()) {
Ted Kremenekce48e002008-05-05 17:53:17 +00002289
2290 os << " Object has +" << Count;
Ted Kremenek79c140b2008-04-18 05:32:44 +00002291
Ted Kremenekce48e002008-05-05 17:53:17 +00002292 if (Count > 1)
2293 os << " retain counts.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00002294 else
Ted Kremenekce48e002008-05-05 17:53:17 +00002295 os << " retain count.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00002296 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002297
2298 Msg = os.str().c_str();
2299
2300 break;
2301
2302 case RefVal::Released:
2303 Msg = "Object released.";
2304 break;
2305
2306 case RefVal::ReturnedOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00002307 Msg = "Object returned to caller as owning reference (single retain count"
2308 " transferred to caller).";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002309 break;
2310
2311 case RefVal::ReturnedNotOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00002312 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002313 break;
2314
2315 default:
2316 return NULL;
2317 }
2318
2319 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2320 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
2321 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
2322
2323 // Add the range by scanning the children of the statement for any bindings
2324 // to Sym.
2325
Ted Kremenekc0959972008-07-02 21:24:01 +00002326 ValueStateManager& VSM = cast<GRBugReporter>(BR).getStateManager();
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002327
2328 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
2329 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
2330 RVal X = VSM.GetRVal(CurrSt, Exp);
2331
2332 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
2333 if (SV->getSymbol() == Sym) {
2334 P->addRange(Exp->getSourceRange()); break;
2335 }
2336 }
2337
2338 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00002339}
2340
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002341static std::pair<ExplodedNode<ValueState>*,VarDecl*>
2342GetAllocationSite(ExplodedNode<ValueState>* N, SymbolID Sym) {
2343
2344 typedef CFRefCount::RefBindings RefBindings;
2345 ExplodedNode<ValueState>* Last = N;
2346
2347 // Find the first node that referred to the tracked symbol. We also
2348 // try and find the first VarDecl the value was stored to.
2349
2350 VarDecl* FirstDecl = 0;
2351
2352 while (N) {
Ted Kremenek4323a572008-07-10 22:03:41 +00002353 const ValueState* St = N->getState();
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002354 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002355
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002356 if (!B.lookup(Sym))
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002357 break;
2358
2359 VarDecl* VD = 0;
2360
2361 // Determine if there is an LVal binding to the symbol.
2362 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
2363 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
2364 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
2365 continue;
2366
2367 if (VD) { // Multiple decls map to this symbol.
2368 VD = 0;
2369 break;
2370 }
2371
2372 VD = I->first;
2373 }
2374
2375 if (VD) FirstDecl = VD;
2376
2377 Last = N;
2378 N = N->pred_empty() ? NULL : *(N->pred_begin());
2379 }
2380
2381 return std::make_pair(Last, FirstDecl);
2382}
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002383
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002384PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremeneke28565b2008-05-05 18:50:19 +00002385 ExplodedNode<ValueState>* EndN) {
Ted Kremenek1aa44c72008-05-22 23:45:19 +00002386
2387 // Tell the BugReporter to report cases when the tracked symbol is
2388 // assigned to different variables, etc.
Ted Kremenekc0959972008-07-02 21:24:01 +00002389 cast<GRBugReporter>(BR).addNotableSymbol(Sym);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002390
2391 if (!getBugType().isLeak())
Ted Kremeneke28565b2008-05-05 18:50:19 +00002392 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002393
Ted Kremenekce48e002008-05-05 17:53:17 +00002394 typedef CFRefCount::RefBindings RefBindings;
2395
2396 // Get the retain count.
Ted Kremenekce48e002008-05-05 17:53:17 +00002397
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002398 unsigned long RetCount =
2399 CFRefCount::GetRefBindings(*EndN->getState()).lookup(Sym)->getCount();
2400
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002401 // We are a leak. Walk up the graph to get to the first node where the
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002402 // symbol appeared, and also get the first VarDecl that tracked object
2403 // is stored to.
2404
2405 ExplodedNode<ValueState>* AllocNode = 0;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002406 VarDecl* FirstDecl = 0;
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002407 llvm::tie(AllocNode, FirstDecl) = GetAllocationSite(EndN, Sym);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002408
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002409 // Get the allocate site.
2410 assert (AllocNode);
2411 Stmt* FirstStmt = cast<PostStmt>(AllocNode->getLocation()).getStmt();
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002412
Ted Kremeneke28565b2008-05-05 18:50:19 +00002413 SourceManager& SMgr = BR.getContext().getSourceManager();
2414 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002415
Ted Kremeneke28565b2008-05-05 18:50:19 +00002416 // Get the leak site. We may have multiple ExplodedNodes (one with the
2417 // leak) that occur on the same line number; if the node with the leak
2418 // has any immediate predecessor nodes with the same line number, find
2419 // any transitive-successors that have a different statement and use that
2420 // line number instead. This avoids emiting a diagnostic like:
2421 //
2422 // // 'y' is leaked.
2423 // int x = foo(y);
2424 //
2425 // instead we want:
2426 //
2427 // int x = foo(y);
2428 // // 'y' is leaked.
2429
2430 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
2431 assert (S);
2432 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
2433
2434 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
2435 // it occur on the same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002436
2437 PathDiagnosticPiece::DisplayHint Hint = PathDiagnosticPiece::Above;
Ted Kremeneke28565b2008-05-05 18:50:19 +00002438
2439 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002440 ExplodedNode<ValueState> *Pred = *(EndN->pred_begin());
2441 ProgramPoint PredPos = Pred->getLocation();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002442
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002443 if (PostStmt* PredPS = dyn_cast<PostStmt>(&PredPos)) {
Ted Kremeneke28565b2008-05-05 18:50:19 +00002444
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002445 Stmt* SPred = PredPS->getStmt();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002446
2447 // Predecessor at same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002448 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine) {
2449 Hint = PathDiagnosticPiece::Below;
2450 S = SPred;
2451 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002452 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002453
2454 // Generate the diagnostic.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002455 FullSourceLoc L( S->getLocStart(), SMgr);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002456 std::ostringstream os;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002457
Ted Kremeneke28565b2008-05-05 18:50:19 +00002458 os << "Object allocated on line " << AllocLine;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002459
2460 if (FirstDecl)
2461 os << " and stored into '" << FirstDecl->getName() << '\'';
2462
Ted Kremenekce48e002008-05-05 17:53:17 +00002463 os << " is no longer referenced after this point and has a retain count of +"
2464 << RetCount << " (object leaked).";
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002465
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002466 return new PathDiagnosticPiece(L, os.str(), Hint);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002467}
2468
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002469void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002470
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002471 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2472 E = TF.use_after_end(); I != E; ++I) {
2473
Ted Kremenek8dd56462008-04-18 03:39:05 +00002474 CFRefReport report(*this, I->first, I->second.second);
2475 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00002476 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00002477 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002478}
2479
2480void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002481
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002482 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2483 E = TF.bad_release_end(); I != E; ++I) {
2484
Ted Kremenek8dd56462008-04-18 03:39:05 +00002485 CFRefReport report(*this, I->first, I->second.second);
2486 report.addRange(I->second.first->getSourceRange());
2487 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002488 }
2489}
Ted Kremenekfa34b332008-04-09 01:10:13 +00002490
Ted Kremenek989d5192008-04-17 23:43:50 +00002491void Leak::EmitWarnings(BugReporter& BR) {
2492
2493 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2494 E = TF.leaks_end(); I != E; ++I) {
2495
Ted Kremenek8dd56462008-04-18 03:39:05 +00002496 std::vector<SymbolID>& SymV = *(I->second);
2497 unsigned n = SymV.size();
2498
2499 for (unsigned i = 0; i < n; ++i) {
2500 CFRefReport report(*this, I->first, SymV[i]);
2501 BR.EmitWarning(report);
2502 }
Ted Kremenek989d5192008-04-17 23:43:50 +00002503 }
2504}
2505
Ted Kremenekcb612922008-04-18 19:23:43 +00002506void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2507 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2508 I!=E; ++I)
2509 Nodes.push_back(I->first);
2510}
2511
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002512bool Leak::isCached(BugReport& R) {
2513
2514 // Most bug reports are cached at the location where they occured.
2515 // With leaks, we want to unique them by the location where they were
2516 // allocated, and only report only a single path.
2517
2518 SymbolID Sym = static_cast<CFRefReport&>(R).getSymbol();
2519
2520 ExplodedNode<ValueState>* AllocNode =
2521 GetAllocationSite(R.getEndNode(), Sym).first;
2522
2523 if (!AllocNode)
2524 return false;
2525
2526 return BugTypeCacheLocation::isCached(AllocNode->getLocation());
2527}
2528
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002529//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00002530// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002531//===----------------------------------------------------------------------===//
2532
Ted Kremenek072192b2008-04-30 23:47:44 +00002533GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek9f741612008-05-02 18:01:49 +00002534 bool StandardWarnings,
Ted Kremenek072192b2008-04-30 23:47:44 +00002535 const LangOptions& lopts) {
Ted Kremenek9f741612008-05-02 18:01:49 +00002536 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00002537}