blob: c72d2a3070b47b415e6b51fdd00f2196247dc5b4 [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 Kremenek4adc81e2008-08-13 04:27:00 +000018#include "clang/Analysis/PathSensitive/GRState.h"
Ted Kremenekb9d17f92008-08-17 03:20:02 +000019#include "clang/Analysis/PathSensitive/GRStateTrait.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000020#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000021#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000022#include "clang/Analysis/PathDiagnostic.h"
23#include "clang/Analysis/PathSensitive/BugReporter.h"
Daniel Dunbarc4a1dea2008-08-11 05:35:13 +000024#include "clang/AST/DeclObjC.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000025#include "llvm/ADT/DenseMap.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek6d348932008-10-21 15:53:15 +000028#include "llvm/ADT/ImmutableList.h"
Ted Kremenek900a2d72008-05-07 18:36:45 +000029#include "llvm/ADT/StringExtras.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000030#include "llvm/Support/Compiler.h"
Ted Kremenek6ed9afc2008-05-16 18:33:44 +000031#include "llvm/ADT/STLExtras.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000032#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000033#include <sstream>
Ted Kremenek98530452008-08-12 20:41:56 +000034#include <stdarg.h>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000035
36using namespace clang;
Ted Kremenek5c74d502008-10-24 21:18:08 +000037
38//===----------------------------------------------------------------------===//
39// Utility functions.
40//===----------------------------------------------------------------------===//
41
Ted Kremenek900a2d72008-05-07 18:36:45 +000042using llvm::CStrInCStrNoCase;
Ted Kremenek2fff37e2008-03-06 00:08:09 +000043
Ted Kremenek5c74d502008-10-24 21:18:08 +000044// The "fundamental rule" for naming conventions of methods:
45// (url broken into two lines)
46// http://developer.apple.com/documentation/Cocoa/Conceptual/
47// MemoryMgmt/Tasks/MemoryManagementRules.html
48//
49// "You take ownership of an object if you create it using a method whose name
50// begins with “alloc” or “new” or contains “copy” (for example, alloc,
51// newObject, or mutableCopy), or if you send it a retain message. You are
52// responsible for relinquishing ownership of objects you own using release
53// or autorelease. Any other time you receive an object, you must
54// not release it."
55//
56static bool followsFundamentalRule(const char* s) {
Ted Kremeneke1e91af2008-10-30 23:14:58 +000057 while (*s == '_') ++s;
Ted Kremenek234a4c22009-01-07 00:39:56 +000058 return CStrInCStrNoCase(s, "copy")
59 || CStrInCStrNoCase(s, "new") == s
60 || CStrInCStrNoCase(s, "alloc") == s;
Ted Kremenek4c79e552008-11-05 16:54:44 +000061}
62
63static bool followsReturnRule(const char* s) {
64 while (*s == '_') ++s;
65 return followsFundamentalRule(s) || CStrInCStrNoCase(s, "init") == s;
66}
Ted Kremenek5c74d502008-10-24 21:18:08 +000067
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000068//===----------------------------------------------------------------------===//
Ted Kremenek553cf182008-06-25 21:21:56 +000069// Selector creation functions.
Ted Kremenek4fd88972008-04-17 18:12:53 +000070//===----------------------------------------------------------------------===//
71
Ted Kremenekb83e02e2008-05-01 18:31:44 +000072static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenek4fd88972008-04-17 18:12:53 +000073 IdentifierInfo* II = &Ctx.Idents.get(name);
74 return Ctx.Selectors.getSelector(0, &II);
75}
76
Ted Kremenek9c32d082008-05-06 00:30:21 +000077static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
78 IdentifierInfo* II = &Ctx.Idents.get(name);
79 return Ctx.Selectors.getSelector(1, &II);
80}
81
Ted Kremenek553cf182008-06-25 21:21:56 +000082//===----------------------------------------------------------------------===//
83// Type querying functions.
84//===----------------------------------------------------------------------===//
85
Ted Kremenek12619382009-01-12 21:45:02 +000086static bool hasPrefix(const char* s, const char* prefix) {
87 if (!prefix)
88 return true;
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000089
Ted Kremenek12619382009-01-12 21:45:02 +000090 char c = *s;
91 char cP = *prefix;
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000092
Ted Kremenek12619382009-01-12 21:45:02 +000093 while (c != '\0' && cP != '\0') {
94 if (c != cP) break;
95 c = *(++s);
96 cP = *(++prefix);
97 }
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000098
Ted Kremenek12619382009-01-12 21:45:02 +000099 return cP == '\0';
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000100}
101
Ted Kremenek12619382009-01-12 21:45:02 +0000102static bool hasSuffix(const char* s, const char* suffix) {
103 const char* loc = strstr(s, suffix);
104 return loc && strcmp(suffix, loc) == 0;
105}
106
107static bool isRefType(QualType RetTy, const char* prefix,
108 ASTContext* Ctx = 0, const char* name = 0) {
Ted Kremenek37d785b2008-07-15 16:50:12 +0000109
Ted Kremenek12619382009-01-12 21:45:02 +0000110 if (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
111 const char* TDName = TD->getDecl()->getIdentifier()->getName();
112 return hasPrefix(TDName, prefix) && hasSuffix(TDName, "Ref");
113 }
114
115 if (!Ctx || !name)
Ted Kremenek37d785b2008-07-15 16:50:12 +0000116 return false;
Ted Kremenek12619382009-01-12 21:45:02 +0000117
118 // Is the type void*?
119 const PointerType* PT = RetTy->getAsPointerType();
120 if (!(PT->getPointeeType().getUnqualifiedType() == Ctx->VoidTy))
Ted Kremenek37d785b2008-07-15 16:50:12 +0000121 return false;
Ted Kremenek12619382009-01-12 21:45:02 +0000122
123 // Does the name start with the prefix?
124 return hasPrefix(name, prefix);
Ted Kremenek37d785b2008-07-15 16:50:12 +0000125}
126
Ted Kremenek4fd88972008-04-17 18:12:53 +0000127//===----------------------------------------------------------------------===//
Ted Kremenek553cf182008-06-25 21:21:56 +0000128// Primitives used for constructing summaries for function/method calls.
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000129//===----------------------------------------------------------------------===//
130
Ted Kremenek553cf182008-06-25 21:21:56 +0000131namespace {
132/// ArgEffect is used to summarize a function/method call's effect on a
133/// particular argument.
Ted Kremenek070a8252008-07-09 18:11:16 +0000134enum ArgEffect { IncRef, DecRef, DoNothing, DoNothingByRef,
135 StopTracking, MayEscape, SelfOwn, Autorelease };
Ted Kremenek553cf182008-06-25 21:21:56 +0000136
137/// ArgEffects summarizes the effects of a function/method call on all of
138/// its arguments.
139typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000140}
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000141
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000142namespace llvm {
Ted Kremenek553cf182008-06-25 21:21:56 +0000143template <> struct FoldingSetTrait<ArgEffects> {
144 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
145 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
146 ID.AddInteger(I->first);
147 ID.AddInteger((unsigned) I->second);
148 }
149 }
150};
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000151} // end llvm namespace
152
153namespace {
Ted Kremenek553cf182008-06-25 21:21:56 +0000154
155/// RetEffect is used to summarize a function/method call's behavior with
156/// respect to its return value.
157class VISIBILITY_HIDDEN RetEffect {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000158public:
Ted Kremeneka7344702008-06-23 18:02:52 +0000159 enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
160 NotOwnedSymbol, ReceiverAlias };
Ted Kremenek553cf182008-06-25 21:21:56 +0000161
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000162private:
163 unsigned Data;
Ted Kremenek553cf182008-06-25 21:21:56 +0000164 RetEffect(Kind k, unsigned D = 0) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000165
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000166public:
Ted Kremenek553cf182008-06-25 21:21:56 +0000167
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000168 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremenek553cf182008-06-25 21:21:56 +0000169
170 unsigned getIndex() const {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000171 assert(getKind() == Alias);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000172 return Data >> 3;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000173 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000174
Ted Kremenek553cf182008-06-25 21:21:56 +0000175 static RetEffect MakeAlias(unsigned Idx) {
176 return RetEffect(Alias, Idx);
177 }
178 static RetEffect MakeReceiverAlias() {
179 return RetEffect(ReceiverAlias);
180 }
Ted Kremeneka7344702008-06-23 18:02:52 +0000181 static RetEffect MakeOwned(bool isAllocated = false) {
Ted Kremenek553cf182008-06-25 21:21:56 +0000182 return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol);
183 }
184 static RetEffect MakeNotOwned() {
185 return RetEffect(NotOwnedSymbol);
186 }
187 static RetEffect MakeNoRet() {
188 return RetEffect(NoRet);
Ted Kremeneka7344702008-06-23 18:02:52 +0000189 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000190
Ted Kremenek553cf182008-06-25 21:21:56 +0000191 operator Kind() const {
192 return getKind();
193 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000194
Ted Kremenek553cf182008-06-25 21:21:56 +0000195 void Profile(llvm::FoldingSetNodeID& ID) const {
196 ID.AddInteger(Data);
197 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000198};
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000199
Ted Kremenek553cf182008-06-25 21:21:56 +0000200
201class VISIBILITY_HIDDEN RetainSummary : public llvm::FoldingSetNode {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000202 /// Args - an ordered vector of (index, ArgEffect) pairs, where index
203 /// specifies the argument (starting from 0). This can be sparsely
204 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000205 ArgEffects* Args;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000206
207 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
208 /// do not have an entry in Args.
209 ArgEffect DefaultArgEffect;
210
Ted Kremenek553cf182008-06-25 21:21:56 +0000211 /// Receiver - If this summary applies to an Objective-C message expression,
212 /// this is the effect applied to the state of the receiver.
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000213 ArgEffect Receiver;
Ted Kremenek553cf182008-06-25 21:21:56 +0000214
215 /// Ret - The effect on the return value. Used to indicate if the
216 /// function/method call returns a new tracked symbol, returns an
217 /// alias of one of the arguments in the call, and so on.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000218 RetEffect Ret;
Ted Kremenek553cf182008-06-25 21:21:56 +0000219
Ted Kremenek70a733e2008-07-18 17:24:20 +0000220 /// EndPath - Indicates that execution of this method/function should
221 /// terminate the simulation of a path.
222 bool EndPath;
223
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000224public:
225
Ted Kremenek1bffd742008-05-06 15:44:25 +0000226 RetainSummary(ArgEffects* A, RetEffect R, ArgEffect defaultEff,
Ted Kremenek70a733e2008-07-18 17:24:20 +0000227 ArgEffect ReceiverEff, bool endpath = false)
228 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R),
229 EndPath(endpath) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000230
Ted Kremenek553cf182008-06-25 21:21:56 +0000231 /// getArg - Return the argument effect on the argument specified by
232 /// idx (starting from 0).
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000233 ArgEffect getArg(unsigned idx) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000234
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000235 if (!Args)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000236 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000237
238 // If Args is present, it is likely to contain only 1 element.
239 // Just do a linear search. Do it from the back because functions with
240 // large numbers of arguments will be tail heavy with respect to which
Ted Kremenek553cf182008-06-25 21:21:56 +0000241 // argument they actually modify with respect to the reference count.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000242 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
243 I!=E; ++I) {
244
245 if (idx > I->first)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000246 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000247
248 if (idx == I->first)
249 return I->second;
250 }
251
Ted Kremenek1bffd742008-05-06 15:44:25 +0000252 return DefaultArgEffect;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000253 }
254
Ted Kremenek553cf182008-06-25 21:21:56 +0000255 /// getRetEffect - Returns the effect on the return value of the call.
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000256 RetEffect getRetEffect() const {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000257 return Ret;
258 }
259
Ted Kremenek70a733e2008-07-18 17:24:20 +0000260 /// isEndPath - Returns true if executing the given method/function should
261 /// terminate the path.
262 bool isEndPath() const { return EndPath; }
263
Ted Kremenek553cf182008-06-25 21:21:56 +0000264 /// getReceiverEffect - Returns the effect on the receiver of the call.
265 /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000266 ArgEffect getReceiverEffect() const {
267 return Receiver;
268 }
269
Ted Kremenek55499762008-06-17 02:43:46 +0000270 typedef ArgEffects::const_iterator ExprIterator;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000271
Ted Kremenek55499762008-06-17 02:43:46 +0000272 ExprIterator begin_args() const { return Args->begin(); }
273 ExprIterator end_args() const { return Args->end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000274
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000275 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000276 RetEffect RetEff, ArgEffect DefaultEff,
Ted Kremenek2d1086c2008-07-18 17:39:56 +0000277 ArgEffect ReceiverEff, bool EndPath) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000278 ID.AddPointer(A);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000279 ID.Add(RetEff);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000280 ID.AddInteger((unsigned) DefaultEff);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000281 ID.AddInteger((unsigned) ReceiverEff);
Ted Kremenek2d1086c2008-07-18 17:39:56 +0000282 ID.AddInteger((unsigned) EndPath);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000283 }
284
285 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek2d1086c2008-07-18 17:39:56 +0000286 Profile(ID, Args, Ret, DefaultArgEffect, Receiver, EndPath);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000287 }
288};
Ted Kremenek4f22a782008-06-23 23:30:29 +0000289} // end anonymous namespace
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000290
Ted Kremenek553cf182008-06-25 21:21:56 +0000291//===----------------------------------------------------------------------===//
292// Data structures for constructing summaries.
293//===----------------------------------------------------------------------===//
Ted Kremenek53301ba2008-06-24 03:49:48 +0000294
Ted Kremenek553cf182008-06-25 21:21:56 +0000295namespace {
296class VISIBILITY_HIDDEN ObjCSummaryKey {
297 IdentifierInfo* II;
298 Selector S;
299public:
300 ObjCSummaryKey(IdentifierInfo* ii, Selector s)
301 : II(ii), S(s) {}
302
303 ObjCSummaryKey(ObjCInterfaceDecl* d, Selector s)
304 : II(d ? d->getIdentifier() : 0), S(s) {}
305
306 ObjCSummaryKey(Selector s)
307 : II(0), S(s) {}
308
309 IdentifierInfo* getIdentifier() const { return II; }
310 Selector getSelector() const { return S; }
311};
Ted Kremenek4f22a782008-06-23 23:30:29 +0000312}
313
314namespace llvm {
Ted Kremenek553cf182008-06-25 21:21:56 +0000315template <> struct DenseMapInfo<ObjCSummaryKey> {
316 static inline ObjCSummaryKey getEmptyKey() {
317 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
318 DenseMapInfo<Selector>::getEmptyKey());
319 }
Ted Kremenek4f22a782008-06-23 23:30:29 +0000320
Ted Kremenek553cf182008-06-25 21:21:56 +0000321 static inline ObjCSummaryKey getTombstoneKey() {
322 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
323 DenseMapInfo<Selector>::getTombstoneKey());
324 }
325
326 static unsigned getHashValue(const ObjCSummaryKey &V) {
327 return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
328 & 0x88888888)
329 | (DenseMapInfo<Selector>::getHashValue(V.getSelector())
330 & 0x55555555);
331 }
332
333 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
334 return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
335 RHS.getIdentifier()) &&
336 DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
337 RHS.getSelector());
338 }
339
340 static bool isPod() {
341 return DenseMapInfo<ObjCInterfaceDecl*>::isPod() &&
342 DenseMapInfo<Selector>::isPod();
343 }
344};
Ted Kremenek4f22a782008-06-23 23:30:29 +0000345} // end llvm namespace
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000346
Ted Kremenek4f22a782008-06-23 23:30:29 +0000347namespace {
Ted Kremenek553cf182008-06-25 21:21:56 +0000348class VISIBILITY_HIDDEN ObjCSummaryCache {
349 typedef llvm::DenseMap<ObjCSummaryKey, RetainSummary*> MapTy;
350 MapTy M;
351public:
352 ObjCSummaryCache() {}
353
354 typedef MapTy::iterator iterator;
355
356 iterator find(ObjCInterfaceDecl* D, Selector S) {
357
358 // Do a lookup with the (D,S) pair. If we find a match return
359 // the iterator.
360 ObjCSummaryKey K(D, S);
361 MapTy::iterator I = M.find(K);
362
363 if (I != M.end() || !D)
364 return I;
365
366 // Walk the super chain. If we find a hit with a parent, we'll end
367 // up returning that summary. We actually allow that key (null,S), as
368 // we cache summaries for the null ObjCInterfaceDecl* to allow us to
369 // generate initial summaries without having to worry about NSObject
370 // being declared.
371 // FIXME: We may change this at some point.
372 for (ObjCInterfaceDecl* C=D->getSuperClass() ;; C=C->getSuperClass()) {
373 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
374 break;
375
376 if (!C)
377 return I;
378 }
379
380 // Cache the summary with original key to make the next lookup faster
381 // and return the iterator.
382 M[K] = I->second;
383 return I;
384 }
385
Ted Kremenek98530452008-08-12 20:41:56 +0000386
Ted Kremenek553cf182008-06-25 21:21:56 +0000387 iterator find(Expr* Receiver, Selector S) {
388 return find(getReceiverDecl(Receiver), S);
389 }
390
391 iterator find(IdentifierInfo* II, Selector S) {
392 // FIXME: Class method lookup. Right now we dont' have a good way
393 // of going between IdentifierInfo* and the class hierarchy.
394 iterator I = M.find(ObjCSummaryKey(II, S));
395 return I == M.end() ? M.find(ObjCSummaryKey(S)) : I;
396 }
397
398 ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
399
400 const PointerType* PT = E->getType()->getAsPointerType();
401 if (!PT) return 0;
402
403 ObjCInterfaceType* OI = dyn_cast<ObjCInterfaceType>(PT->getPointeeType());
404 if (!OI) return 0;
405
406 return OI ? OI->getDecl() : 0;
407 }
408
409 iterator end() { return M.end(); }
410
411 RetainSummary*& operator[](ObjCMessageExpr* ME) {
412
413 Selector S = ME->getSelector();
414
415 if (Expr* Receiver = ME->getReceiver()) {
416 ObjCInterfaceDecl* OD = getReceiverDecl(Receiver);
417 return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
418 }
419
420 return M[ObjCSummaryKey(ME->getClassName(), S)];
421 }
422
423 RetainSummary*& operator[](ObjCSummaryKey K) {
424 return M[K];
425 }
426
427 RetainSummary*& operator[](Selector S) {
428 return M[ ObjCSummaryKey(S) ];
429 }
430};
431} // end anonymous namespace
432
433//===----------------------------------------------------------------------===//
434// Data structures for managing collections of summaries.
435//===----------------------------------------------------------------------===//
436
437namespace {
438class VISIBILITY_HIDDEN RetainSummaryManager {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000439
440 //==-----------------------------------------------------------------==//
441 // Typedefs.
442 //==-----------------------------------------------------------------==//
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000443
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000444 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
445 ArgEffectsSetTy;
446
447 typedef llvm::FoldingSet<RetainSummary>
448 SummarySetTy;
449
450 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
451 FuncSummariesTy;
452
Ted Kremenek4f22a782008-06-23 23:30:29 +0000453 typedef ObjCSummaryCache ObjCMethodSummariesTy;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000454
455 //==-----------------------------------------------------------------==//
456 // Data.
457 //==-----------------------------------------------------------------==//
458
Ted Kremenek553cf182008-06-25 21:21:56 +0000459 /// Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek377e2302008-04-29 05:33:51 +0000460 ASTContext& Ctx;
Ted Kremenek179064e2008-07-01 17:21:27 +0000461
Ted Kremenek070a8252008-07-09 18:11:16 +0000462 /// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
463 /// "CFDictionaryCreate".
464 IdentifierInfo* CFDictionaryCreateII;
465
Ted Kremenek553cf182008-06-25 21:21:56 +0000466 /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek377e2302008-04-29 05:33:51 +0000467 const bool GCEnabled;
468
Ted Kremenek553cf182008-06-25 21:21:56 +0000469 /// SummarySet - A FoldingSet of uniqued summaries.
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000470 SummarySetTy SummarySet;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000471
Ted Kremenek553cf182008-06-25 21:21:56 +0000472 /// FuncSummaries - A map from FunctionDecls to summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000473 FuncSummariesTy FuncSummaries;
474
Ted Kremenek553cf182008-06-25 21:21:56 +0000475 /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
476 /// to summaries.
Ted Kremenek1f180c32008-06-23 22:21:20 +0000477 ObjCMethodSummariesTy ObjCClassMethodSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000478
Ted Kremenek553cf182008-06-25 21:21:56 +0000479 /// ObjCMethodSummaries - A map from selectors to summaries.
Ted Kremenek1f180c32008-06-23 22:21:20 +0000480 ObjCMethodSummariesTy ObjCMethodSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000481
Ted Kremenek553cf182008-06-25 21:21:56 +0000482 /// ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000483 ArgEffectsSetTy ArgEffectsSet;
484
Ted Kremenek553cf182008-06-25 21:21:56 +0000485 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
486 /// and all other data used by the checker.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000487 llvm::BumpPtrAllocator BPAlloc;
488
Ted Kremenek553cf182008-06-25 21:21:56 +0000489 /// ScratchArgs - A holding buffer for construct ArgEffects.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000490 ArgEffects ScratchArgs;
491
Ted Kremenek432af592008-05-06 18:11:36 +0000492 RetainSummary* StopSummary;
493
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000494 //==-----------------------------------------------------------------==//
495 // Methods.
496 //==-----------------------------------------------------------------==//
497
Ted Kremenek553cf182008-06-25 21:21:56 +0000498 /// getArgEffects - Returns a persistent ArgEffects object based on the
499 /// data in ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000500 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000501
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000502 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremenek896cd9d2008-10-23 01:56:15 +0000503
504public:
Ted Kremenek12619382009-01-12 21:45:02 +0000505 RetainSummary* getUnarySummary(FunctionType* FT, UnaryFuncKind func);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000506
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000507 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
508 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenek12619382009-01-12 21:45:02 +0000509 RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000510
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000511 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000512 ArgEffect ReceiverEff = DoNothing,
Ted Kremenek70a733e2008-07-18 17:24:20 +0000513 ArgEffect DefaultEff = MayEscape,
514 bool isEndPath = false);
Ted Kremenek706522f2008-10-29 04:07:07 +0000515
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000516 RetainSummary* getPersistentSummary(RetEffect RE,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000517 ArgEffect ReceiverEff = DoNothing,
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000518 ArgEffect DefaultEff = MayEscape) {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000519 return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000520 }
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000521
Ted Kremenek1bffd742008-05-06 15:44:25 +0000522 RetainSummary* getPersistentStopSummary() {
Ted Kremenek432af592008-05-06 18:11:36 +0000523 if (StopSummary)
524 return StopSummary;
525
526 StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
527 StopTracking, StopTracking);
Ted Kremenek706522f2008-10-29 04:07:07 +0000528
Ted Kremenek432af592008-05-06 18:11:36 +0000529 return StopSummary;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000530 }
Ted Kremenekb3095252008-05-06 04:20:12 +0000531
Ted Kremenek553cf182008-06-25 21:21:56 +0000532 RetainSummary* getInitMethodSummary(ObjCMessageExpr* ME);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000533
Ted Kremenek1f180c32008-06-23 22:21:20 +0000534 void InitializeClassMethodSummaries();
535 void InitializeMethodSummaries();
Ted Kremenek896cd9d2008-10-23 01:56:15 +0000536
Ted Kremenek234a4c22009-01-07 00:39:56 +0000537 bool isTrackedObjectType(QualType T);
538
Ted Kremenek896cd9d2008-10-23 01:56:15 +0000539private:
540
Ted Kremenek70a733e2008-07-18 17:24:20 +0000541 void addClsMethSummary(IdentifierInfo* ClsII, Selector S,
542 RetainSummary* Summ) {
543 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
544 }
545
Ted Kremenek553cf182008-06-25 21:21:56 +0000546 void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
547 ObjCClassMethodSummaries[S] = Summ;
548 }
549
550 void addNSObjectMethSummary(Selector S, RetainSummary *Summ) {
551 ObjCMethodSummaries[S] = Summ;
552 }
553
Ted Kremenekaf9dc272008-08-12 18:48:50 +0000554 void addInstMethSummary(const char* Cls, RetainSummary* Summ, va_list argp) {
Ted Kremenek70a733e2008-07-18 17:24:20 +0000555
Ted Kremenek9e476de2008-08-12 18:30:56 +0000556 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
557 llvm::SmallVector<IdentifierInfo*, 10> II;
558
559 while (const char* s = va_arg(argp, const char*))
560 II.push_back(&Ctx.Idents.get(s));
561
562 Selector S = Ctx.Selectors.getSelector(II.size(), &II[0]);
Ted Kremenek70a733e2008-07-18 17:24:20 +0000563 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
564 }
Ted Kremenekaf9dc272008-08-12 18:48:50 +0000565
566 void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) {
567 va_list argp;
568 va_start(argp, Summ);
569 addInstMethSummary(Cls, Summ, argp);
570 va_end(argp);
571 }
Ted Kremenek9e476de2008-08-12 18:30:56 +0000572
573 void addPanicSummary(const char* Cls, ...) {
574 RetainSummary* Summ = getPersistentSummary(0, RetEffect::MakeNoRet(),
575 DoNothing, DoNothing, true);
576 va_list argp;
577 va_start (argp, Cls);
Ted Kremenekaf9dc272008-08-12 18:48:50 +0000578 addInstMethSummary(Cls, Summ, argp);
Ted Kremenek9e476de2008-08-12 18:30:56 +0000579 va_end(argp);
580 }
Ted Kremenek70a733e2008-07-18 17:24:20 +0000581
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000582public:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000583
584 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek179064e2008-07-01 17:21:27 +0000585 : Ctx(ctx),
Ted Kremenek070a8252008-07-09 18:11:16 +0000586 CFDictionaryCreateII(&ctx.Idents.get("CFDictionaryCreate")),
Ted Kremenek553cf182008-06-25 21:21:56 +0000587 GCEnabled(gcenabled), StopSummary(0) {
588
589 InitializeClassMethodSummaries();
590 InitializeMethodSummaries();
591 }
Ted Kremenek377e2302008-04-29 05:33:51 +0000592
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000593 ~RetainSummaryManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000594
Ted Kremenekab592272008-06-24 03:56:45 +0000595 RetainSummary* getSummary(FunctionDecl* FD);
Ted Kremenek553cf182008-06-25 21:21:56 +0000596 RetainSummary* getMethodSummary(ObjCMessageExpr* ME, ObjCInterfaceDecl* ID);
Ted Kremenek1f180c32008-06-23 22:21:20 +0000597 RetainSummary* getClassMethodSummary(IdentifierInfo* ClsName, Selector S);
Ted Kremenekb3095252008-05-06 04:20:12 +0000598
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000599 bool isGCEnabled() const { return GCEnabled; }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000600};
601
602} // end anonymous namespace
603
Ted Kremenek234a4c22009-01-07 00:39:56 +0000604
605
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000606//===----------------------------------------------------------------------===//
607// Implementation of checker data structures.
608//===----------------------------------------------------------------------===//
609
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000610RetainSummaryManager::~RetainSummaryManager() {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000611
612 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
613 // mitigating the need to do explicit cleanup of the
614 // Argument-Effect summaries.
615
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000616 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
617 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000618 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000619}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000620
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000621ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000622
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000623 if (ScratchArgs.empty())
624 return NULL;
625
626 // Compute a profile for a non-empty ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000627 llvm::FoldingSetNodeID profile;
628 profile.Add(ScratchArgs);
629 void* InsertPos;
630
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000631 // Look up the uniqued copy, or create a new one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000632 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000633 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000634
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000635 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000636 ScratchArgs.clear();
637 return &E->getValue();
638 }
639
640 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
Ted Kremenek553cf182008-06-25 21:21:56 +0000641 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000642
643 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000644 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000645
646 ScratchArgs.clear();
647 return &E->getValue();
648}
649
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000650RetainSummary*
651RetainSummaryManager::getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000652 ArgEffect ReceiverEff,
Ted Kremenek70a733e2008-07-18 17:24:20 +0000653 ArgEffect DefaultEff,
654 bool isEndPath) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000655
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000656 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000657 llvm::FoldingSetNodeID profile;
Ted Kremenek2d1086c2008-07-18 17:39:56 +0000658 RetainSummary::Profile(profile, AE, RetEff, DefaultEff, ReceiverEff,
659 isEndPath);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000660
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000661 // Look up the uniqued summary, or create one if it doesn't exist.
662 void* InsertPos;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000663 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000664
665 if (Summ)
666 return Summ;
667
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000668 // Create the summary and return it.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000669 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
Ted Kremenek70a733e2008-07-18 17:24:20 +0000670 new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff, isEndPath);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000671 SummarySet.InsertNode(Summ, InsertPos);
672
673 return Summ;
674}
675
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000676//===----------------------------------------------------------------------===//
Ted Kremenek234a4c22009-01-07 00:39:56 +0000677// Predicates.
678//===----------------------------------------------------------------------===//
679
680bool RetainSummaryManager::isTrackedObjectType(QualType T) {
681 if (!Ctx.isObjCObjectPointerType(T))
682 return false;
683
684 // Does it subclass NSObject?
685 ObjCInterfaceType* OT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
686
687 // We assume that id<..>, id, and "Class" all represent tracked objects.
688 if (!OT)
689 return true;
690
691 // Does the object type subclass NSObject?
692 // FIXME: We can memoize here if this gets too expensive.
693 IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
694 ObjCInterfaceDecl* ID = OT->getDecl();
695
696 for ( ; ID ; ID = ID->getSuperClass())
697 if (ID->getIdentifier() == NSObjectII)
698 return true;
699
700 return false;
701}
702
703//===----------------------------------------------------------------------===//
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000704// Summary creation for functions (largely uses of Core Foundation).
705//===----------------------------------------------------------------------===//
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000706
Ted Kremenek12619382009-01-12 21:45:02 +0000707static bool isRetain(FunctionDecl* FD, const char* FName) {
708 const char* loc = strstr(FName, "Retain");
709 return loc && loc[sizeof("Retain")-1] == '\0';
710}
711
712static bool isRelease(FunctionDecl* FD, const char* FName) {
713 const char* loc = strstr(FName, "Release");
714 return loc && loc[sizeof("Release")-1] == '\0';
715}
716
Ted Kremenekab592272008-06-24 03:56:45 +0000717RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000718
719 SourceLocation Loc = FD->getLocation();
720
721 if (!Loc.isFileID())
722 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000723
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000724 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000725 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000726
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000727 if (I != FuncSummaries.end())
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000728 return I->second;
729
730 // No summary. Generate one.
Ted Kremenek12619382009-01-12 21:45:02 +0000731 RetainSummary *S = 0;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000732
Ted Kremenek37d785b2008-07-15 16:50:12 +0000733 do {
Ted Kremenek12619382009-01-12 21:45:02 +0000734 // We generate "stop" summaries for implicitly defined functions.
735 if (FD->isImplicit()) {
736 S = getPersistentStopSummary();
737 break;
Ted Kremenek37d785b2008-07-15 16:50:12 +0000738 }
Ted Kremenek6ca31912008-11-04 00:36:12 +0000739
Ted Kremenek99890652009-01-16 18:40:33 +0000740 // [PR 3337] Use 'getDesugaredType' to strip away any typedefs on the
741 // function's type.
742 FunctionType* FT = cast<FunctionType>(FD->getType()->getDesugaredType());
Ted Kremenek12619382009-01-12 21:45:02 +0000743 const char* FName = FD->getIdentifier()->getName();
744
745 // Inspect the result type.
746 QualType RetTy = FT->getResultType();
747
748 // FIXME: This should all be refactored into a chain of "summary lookup"
749 // filters.
750 if (strcmp(FName, "IOServiceGetMatchingServices") == 0) {
751 // FIXES: <rdar://problem/6326900>
752 // This should be addressed using a API table. This strcmp is also
753 // a little gross, but there is no need to super optimize here.
754 assert (ScratchArgs.empty());
755 ScratchArgs.push_back(std::make_pair(1, DecRef));
756 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
757 break;
Ted Kremenek64e859a2008-10-22 20:54:52 +0000758 }
Ted Kremenek12619382009-01-12 21:45:02 +0000759
760 // Handle: id NSMakeCollectable(CFTypeRef)
761 if (strcmp(FName, "NSMakeCollectable") == 0) {
762 S = (RetTy == Ctx.getObjCIdType())
763 ? getUnarySummary(FT, cfmakecollectable)
764 : getPersistentStopSummary();
765
766 break;
767 }
768
769 if (RetTy->isPointerType()) {
770 // For CoreFoundation ('CF') types.
771 if (isRefType(RetTy, "CF", &Ctx, FName)) {
772 if (isRetain(FD, FName))
773 S = getUnarySummary(FT, cfretain);
774 else if (strstr(FName, "MakeCollectable"))
775 S = getUnarySummary(FT, cfmakecollectable);
776 else
777 S = getCFCreateGetRuleSummary(FD, FName);
778
779 break;
780 }
781
782 // For CoreGraphics ('CG') types.
783 if (isRefType(RetTy, "CG", &Ctx, FName)) {
784 if (isRetain(FD, FName))
785 S = getUnarySummary(FT, cfretain);
786 else
787 S = getCFCreateGetRuleSummary(FD, FName);
788
789 break;
790 }
791
792 // For the Disk Arbitration API (DiskArbitration/DADisk.h)
793 if (isRefType(RetTy, "DADisk") ||
794 isRefType(RetTy, "DADissenter") ||
795 isRefType(RetTy, "DASessionRef")) {
796 S = getCFCreateGetRuleSummary(FD, FName);
797 break;
798 }
799
800 break;
801 }
802
803 // Check for release functions, the only kind of functions that we care
804 // about that don't return a pointer type.
805 if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
806 if (isRelease(FD, FName+2))
807 S = getUnarySummary(FT, cfrelease);
808 else {
809 // For CoreFoundation and CoreGraphics functions we assume they
810 // follow the ownership idiom strictly and thus do not cause
811 // ownership to "escape".
812 assert (ScratchArgs.empty());
813 S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
814 DoNothing);
815 }
816 }
Ted Kremenek37d785b2008-07-15 16:50:12 +0000817 }
818 while (0);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000819
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000820 FuncSummaries[FD] = S;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000821 return S;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000822}
823
Ted Kremenek37d785b2008-07-15 16:50:12 +0000824RetainSummary*
825RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
826 const char* FName) {
827
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000828 if (strstr(FName, "Create") || strstr(FName, "Copy"))
829 return getCFSummaryCreateRule(FD);
Ted Kremenek37d785b2008-07-15 16:50:12 +0000830
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000831 if (strstr(FName, "Get"))
832 return getCFSummaryGetRule(FD);
833
834 return 0;
835}
836
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000837RetainSummary*
Ted Kremenek12619382009-01-12 21:45:02 +0000838RetainSummaryManager::getUnarySummary(FunctionType* FT, UnaryFuncKind func) {
839 // Sanity check that this is *really* a unary function. This can
840 // happen if people do weird things.
841 FunctionTypeProto* FTP = dyn_cast<FunctionTypeProto>(FT);
842 if (!FTP || FTP->getNumArgs() != 1)
843 return getPersistentStopSummary();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000844
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000845 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000846
Ted Kremenek377e2302008-04-29 05:33:51 +0000847 switch (func) {
Ted Kremenek12619382009-01-12 21:45:02 +0000848 case cfretain: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000849 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000850 return getPersistentSummary(RetEffect::MakeAlias(0),
851 DoNothing, DoNothing);
Ted Kremenek377e2302008-04-29 05:33:51 +0000852 }
853
854 case cfrelease: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000855 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000856 return getPersistentSummary(RetEffect::MakeNoRet(),
857 DoNothing, DoNothing);
Ted Kremenek377e2302008-04-29 05:33:51 +0000858 }
859
860 case cfmakecollectable: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000861 if (GCEnabled)
862 ScratchArgs.push_back(std::make_pair(0, DecRef));
863
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000864 return getPersistentSummary(RetEffect::MakeAlias(0),
865 DoNothing, DoNothing);
Ted Kremenek377e2302008-04-29 05:33:51 +0000866 }
867
868 default:
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000869 assert (false && "Not a supported unary function.");
Ted Kremenek98530452008-08-12 20:41:56 +0000870 return 0;
Ted Kremenek940b1d82008-04-10 23:44:06 +0000871 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000872}
873
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000874RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000875 assert (ScratchArgs.empty());
Ted Kremenek070a8252008-07-09 18:11:16 +0000876
877 if (FD->getIdentifier() == CFDictionaryCreateII) {
878 ScratchArgs.push_back(std::make_pair(1, DoNothingByRef));
879 ScratchArgs.push_back(std::make_pair(2, DoNothingByRef));
880 }
881
Ted Kremeneka7344702008-06-23 18:02:52 +0000882 return getPersistentSummary(RetEffect::MakeOwned(true));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000883}
884
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000885RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000886 assert (ScratchArgs.empty());
Ted Kremenek3eabf1c2008-05-22 17:31:13 +0000887 return getPersistentSummary(RetEffect::MakeNotOwned(), DoNothing, DoNothing);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000888}
889
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000890//===----------------------------------------------------------------------===//
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000891// Summary creation for Selectors.
892//===----------------------------------------------------------------------===//
893
Ted Kremenek1bffd742008-05-06 15:44:25 +0000894RetainSummary*
Ted Kremenek553cf182008-06-25 21:21:56 +0000895RetainSummaryManager::getInitMethodSummary(ObjCMessageExpr* ME) {
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000896 assert(ScratchArgs.empty());
897
898 RetainSummary* Summ =
Ted Kremenek9c32d082008-05-06 00:30:21 +0000899 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000900
Ted Kremenek553cf182008-06-25 21:21:56 +0000901 ObjCMethodSummaries[ME] = Summ;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000902 return Summ;
903}
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000904
Ted Kremenek553cf182008-06-25 21:21:56 +0000905
Ted Kremenek1bffd742008-05-06 15:44:25 +0000906RetainSummary*
Ted Kremenek553cf182008-06-25 21:21:56 +0000907RetainSummaryManager::getMethodSummary(ObjCMessageExpr* ME,
908 ObjCInterfaceDecl* ID) {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000909
910 Selector S = ME->getSelector();
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000911
Ted Kremenek553cf182008-06-25 21:21:56 +0000912 // Look up a summary in our summary cache.
913 ObjCMethodSummariesTy::iterator I = ObjCMethodSummaries.find(ID, S);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000914
Ted Kremenek1f180c32008-06-23 22:21:20 +0000915 if (I != ObjCMethodSummaries.end())
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000916 return I->second;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000917
Ted Kremenek234a4c22009-01-07 00:39:56 +0000918 // "initXXX": pass-through for receiver.
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000919 const char* s = S.getIdentifierInfoForSlot(0)->getName();
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000920 assert (ScratchArgs.empty());
Ted Kremenekaee9e572008-05-06 06:09:09 +0000921
Ted Kremenek0327f772008-06-02 17:14:13 +0000922 if (strncmp(s, "init", 4) == 0 || strncmp(s, "_init", 5) == 0)
Ted Kremenek234a4c22009-01-07 00:39:56 +0000923 return getInitMethodSummary(ME);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000924
Ted Kremenek234a4c22009-01-07 00:39:56 +0000925 // Look for methods that return an owned object.
926 if (!isTrackedObjectType(Ctx.getCanonicalType(ME->getType())))
Ted Kremenek84060db2008-05-07 04:25:59 +0000927 return 0;
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000928
Ted Kremenek234a4c22009-01-07 00:39:56 +0000929 if (followsFundamentalRule(s)) {
930 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
931 : RetEffect::MakeOwned(true);
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000932 RetainSummary* Summ = getPersistentSummary(E);
Ted Kremenek553cf182008-06-25 21:21:56 +0000933 ObjCMethodSummaries[ME] = Summ;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000934 return Summ;
935 }
Ted Kremenek1bffd742008-05-06 15:44:25 +0000936
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000937 return 0;
938}
939
Ted Kremenekc8395602008-05-06 21:26:51 +0000940RetainSummary*
Ted Kremenek1f180c32008-06-23 22:21:20 +0000941RetainSummaryManager::getClassMethodSummary(IdentifierInfo* ClsName,
942 Selector S) {
Ted Kremenekc8395602008-05-06 21:26:51 +0000943
Ted Kremenek553cf182008-06-25 21:21:56 +0000944 // FIXME: Eventually we should properly do class method summaries, but
945 // it requires us being able to walk the type hierarchy. Unfortunately,
946 // we cannot do this with just an IdentifierInfo* for the class name.
947
Ted Kremenekc8395602008-05-06 21:26:51 +0000948 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek553cf182008-06-25 21:21:56 +0000949 ObjCMethodSummariesTy::iterator I = ObjCClassMethodSummaries.find(ClsName, S);
Ted Kremenekc8395602008-05-06 21:26:51 +0000950
Ted Kremenek1f180c32008-06-23 22:21:20 +0000951 if (I != ObjCClassMethodSummaries.end())
Ted Kremenekc8395602008-05-06 21:26:51 +0000952 return I->second;
953
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000954 return 0;
Ted Kremenekc8395602008-05-06 21:26:51 +0000955}
956
Ted Kremenek1f180c32008-06-23 22:21:20 +0000957void RetainSummaryManager::InitializeClassMethodSummaries() {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000958
959 assert (ScratchArgs.empty());
960
Ted Kremeneka7344702008-06-23 18:02:52 +0000961 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
962 : RetEffect::MakeOwned(true);
963
Ted Kremenek9c32d082008-05-06 00:30:21 +0000964 RetainSummary* Summ = getPersistentSummary(E);
965
Ted Kremenek553cf182008-06-25 21:21:56 +0000966 // Create the summaries for "alloc", "new", and "allocWithZone:" for
967 // NSObject and its derivatives.
968 addNSObjectClsMethSummary(GetNullarySelector("alloc", Ctx), Summ);
969 addNSObjectClsMethSummary(GetNullarySelector("new", Ctx), Summ);
970 addNSObjectClsMethSummary(GetUnarySelector("allocWithZone", Ctx), Summ);
Ted Kremenek70a733e2008-07-18 17:24:20 +0000971
972 // Create the [NSAssertionHandler currentHander] summary.
Ted Kremenek9e476de2008-08-12 18:30:56 +0000973 addClsMethSummary(&Ctx.Idents.get("NSAssertionHandler"),
Ted Kremenek1a804482008-07-18 18:14:26 +0000974 GetNullarySelector("currentHandler", Ctx),
Ted Kremenek6d348932008-10-21 15:53:15 +0000975 getPersistentSummary(RetEffect::MakeNotOwned()));
976
977 // Create the [NSAutoreleasePool addObject:] summary.
978 if (!isGCEnabled()) {
979 ScratchArgs.push_back(std::make_pair(0, Autorelease));
980 addClsMethSummary(&Ctx.Idents.get("NSAutoreleasePool"),
981 GetUnarySelector("addObject", Ctx),
982 getPersistentSummary(RetEffect::MakeNoRet(),
983 DoNothing, DoNothing));
984 }
Ted Kremenek9c32d082008-05-06 00:30:21 +0000985}
986
Ted Kremenek1f180c32008-06-23 22:21:20 +0000987void RetainSummaryManager::InitializeMethodSummaries() {
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000988
989 assert (ScratchArgs.empty());
990
Ted Kremenekc8395602008-05-06 21:26:51 +0000991 // Create the "init" selector. It just acts as a pass-through for the
992 // receiver.
Ted Kremenek179064e2008-07-01 17:21:27 +0000993 RetainSummary* InitSumm = getPersistentSummary(RetEffect::MakeReceiverAlias());
994 addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
Ted Kremenekc8395602008-05-06 21:26:51 +0000995
996 // The next methods are allocators.
Ted Kremeneka7344702008-06-23 18:02:52 +0000997 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
998 : RetEffect::MakeOwned(true);
999
Ted Kremenek179064e2008-07-01 17:21:27 +00001000 RetainSummary* Summ = getPersistentSummary(E);
Ted Kremenekc8395602008-05-06 21:26:51 +00001001
1002 // Create the "copy" selector.
Ted Kremenek98530452008-08-12 20:41:56 +00001003 addNSObjectMethSummary(GetNullarySelector("copy", Ctx), Summ);
1004
Ted Kremenekb3c3c282008-05-06 00:38:54 +00001005 // Create the "mutableCopy" selector.
Ted Kremenek553cf182008-06-25 21:21:56 +00001006 addNSObjectMethSummary(GetNullarySelector("mutableCopy", Ctx), Summ);
Ted Kremenek98530452008-08-12 20:41:56 +00001007
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001008 // Create the "retain" selector.
1009 E = RetEffect::MakeReceiverAlias();
1010 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
Ted Kremenek553cf182008-06-25 21:21:56 +00001011 addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001012
1013 // Create the "release" selector.
1014 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
Ted Kremenek553cf182008-06-25 21:21:56 +00001015 addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
Ted Kremenek299e8152008-05-07 21:17:39 +00001016
1017 // Create the "drain" selector.
1018 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
Ted Kremenek553cf182008-06-25 21:21:56 +00001019 addNSObjectMethSummary(GetNullarySelector("drain", Ctx), Summ);
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001020
1021 // Create the "autorelease" selector.
Ted Kremeneke19f4492008-06-30 16:57:41 +00001022 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : Autorelease);
Ted Kremenek553cf182008-06-25 21:21:56 +00001023 addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
Ted Kremenek98530452008-08-12 20:41:56 +00001024
Ted Kremenekaf9dc272008-08-12 18:48:50 +00001025 // For NSWindow, allocated objects are (initially) self-owned.
Ted Kremenek179064e2008-07-01 17:21:27 +00001026 RetainSummary *NSWindowSumm =
1027 getPersistentSummary(RetEffect::MakeReceiverAlias(), SelfOwn);
Ted Kremenekaf9dc272008-08-12 18:48:50 +00001028
1029 addInstMethSummary("NSWindow", NSWindowSumm, "initWithContentRect",
1030 "styleMask", "backing", "defer", NULL);
1031
1032 addInstMethSummary("NSWindow", NSWindowSumm, "initWithContentRect",
1033 "styleMask", "backing", "defer", "screen", NULL);
1034
1035 // For NSPanel (which subclasses NSWindow), allocated objects are not
1036 // self-owned.
1037 addInstMethSummary("NSPanel", InitSumm, "initWithContentRect",
1038 "styleMask", "backing", "defer", NULL);
1039
1040 addInstMethSummary("NSPanel", InitSumm, "initWithContentRect",
1041 "styleMask", "backing", "defer", "screen", NULL);
Ted Kremenek553cf182008-06-25 21:21:56 +00001042
Ted Kremenek70a733e2008-07-18 17:24:20 +00001043 // Create NSAssertionHandler summaries.
Ted Kremenek9e476de2008-08-12 18:30:56 +00001044 addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
1045 "lineNumber", "description", NULL);
Ted Kremenek70a733e2008-07-18 17:24:20 +00001046
Ted Kremenek9e476de2008-08-12 18:30:56 +00001047 addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
1048 "file", "lineNumber", "description", NULL);
Ted Kremenekb3c3c282008-05-06 00:38:54 +00001049}
1050
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001051//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +00001052// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001053//===----------------------------------------------------------------------===//
1054
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001055namespace {
1056
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001057class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001058public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001059
Ted Kremenek4fd88972008-04-17 18:12:53 +00001060 enum Kind {
1061 Owned = 0, // Owning reference.
1062 NotOwned, // Reference is not owned by still valid (not freed).
1063 Released, // Object has been released.
1064 ReturnedOwned, // Returned object passes ownership to caller.
1065 ReturnedNotOwned, // Return object does not pass ownership to caller.
1066 ErrorUseAfterRelease, // Object used after released.
1067 ErrorReleaseNotOwned, // Release of an object that was not owned.
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001068 ErrorLeak, // A memory leak due to excessive reference counts.
1069 ErrorLeakReturned // A memory leak due to the returning method not having
1070 // the correct naming conventions.
Ted Kremenek4fd88972008-04-17 18:12:53 +00001071 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001072
Ted Kremenek4fd88972008-04-17 18:12:53 +00001073private:
1074
1075 Kind kind;
1076 unsigned Cnt;
Ted Kremenek553cf182008-06-25 21:21:56 +00001077 QualType T;
1078
1079 RefVal(Kind k, unsigned cnt, QualType t) : kind(k), Cnt(cnt), T(t) {}
1080 RefVal(Kind k, unsigned cnt = 0) : kind(k), Cnt(cnt) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001081
1082public:
Ted Kremenekdb863712008-04-16 22:32:20 +00001083
Ted Kremenek4fd88972008-04-17 18:12:53 +00001084 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001085
Ted Kremenek553cf182008-06-25 21:21:56 +00001086 unsigned getCount() const { return Cnt; }
1087 QualType getType() const { return T; }
Ted Kremenek4fd88972008-04-17 18:12:53 +00001088
1089 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001090
Ted Kremenek73c750b2008-03-11 18:14:09 +00001091 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
1092
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001093 static bool isLeak(Kind k) { return k >= ErrorLeak; }
Ted Kremenekdb863712008-04-16 22:32:20 +00001094
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001095 bool isOwned() const {
1096 return getKind() == Owned;
1097 }
1098
Ted Kremenekdb863712008-04-16 22:32:20 +00001099 bool isNotOwned() const {
1100 return getKind() == NotOwned;
1101 }
1102
Ted Kremenek4fd88972008-04-17 18:12:53 +00001103 bool isReturnedOwned() const {
1104 return getKind() == ReturnedOwned;
1105 }
1106
1107 bool isReturnedNotOwned() const {
1108 return getKind() == ReturnedNotOwned;
1109 }
1110
1111 bool isNonLeakError() const {
1112 Kind k = getKind();
1113 return isError(k) && !isLeak(k);
1114 }
1115
1116 // State creation: normal state.
1117
Ted Kremenek553cf182008-06-25 21:21:56 +00001118 static RefVal makeOwned(QualType t, unsigned Count = 1) {
1119 return RefVal(Owned, Count, t);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001120 }
1121
Ted Kremenek553cf182008-06-25 21:21:56 +00001122 static RefVal makeNotOwned(QualType t, unsigned Count = 0) {
1123 return RefVal(NotOwned, Count, t);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001124 }
Ted Kremenek4fd88972008-04-17 18:12:53 +00001125
1126 static RefVal makeReturnedOwned(unsigned Count) {
1127 return RefVal(ReturnedOwned, Count);
1128 }
1129
1130 static RefVal makeReturnedNotOwned() {
1131 return RefVal(ReturnedNotOwned);
1132 }
1133
Ted Kremenek4fd88972008-04-17 18:12:53 +00001134 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001135
Ted Kremenek4fd88972008-04-17 18:12:53 +00001136 bool operator==(const RefVal& X) const {
Ted Kremenek553cf182008-06-25 21:21:56 +00001137 return kind == X.kind && Cnt == X.Cnt && T == X.T;
Ted Kremenek4fd88972008-04-17 18:12:53 +00001138 }
Ted Kremenekf3948042008-03-11 19:44:10 +00001139
Ted Kremenek553cf182008-06-25 21:21:56 +00001140 RefVal operator-(size_t i) const {
1141 return RefVal(getKind(), getCount() - i, getType());
1142 }
1143
1144 RefVal operator+(size_t i) const {
1145 return RefVal(getKind(), getCount() + i, getType());
1146 }
1147
1148 RefVal operator^(Kind k) const {
1149 return RefVal(k, getCount(), getType());
1150 }
1151
1152
Ted Kremenek4fd88972008-04-17 18:12:53 +00001153 void Profile(llvm::FoldingSetNodeID& ID) const {
1154 ID.AddInteger((unsigned) kind);
1155 ID.AddInteger(Cnt);
Ted Kremenek553cf182008-06-25 21:21:56 +00001156 ID.Add(T);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001157 }
1158
Ted Kremenekf3948042008-03-11 19:44:10 +00001159 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001160};
Ted Kremenekf3948042008-03-11 19:44:10 +00001161
1162void RefVal::print(std::ostream& Out) const {
Ted Kremenek553cf182008-06-25 21:21:56 +00001163 if (!T.isNull())
1164 Out << "Tracked Type:" << T.getAsString() << '\n';
1165
Ted Kremenekf3948042008-03-11 19:44:10 +00001166 switch (getKind()) {
1167 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001168 case Owned: {
1169 Out << "Owned";
1170 unsigned cnt = getCount();
1171 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +00001172 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001173 }
Ted Kremenekf3948042008-03-11 19:44:10 +00001174
Ted Kremenek61b9f872008-04-10 23:09:18 +00001175 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001176 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +00001177 unsigned cnt = getCount();
1178 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +00001179 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001180 }
Ted Kremenekf3948042008-03-11 19:44:10 +00001181
Ted Kremenek4fd88972008-04-17 18:12:53 +00001182 case ReturnedOwned: {
1183 Out << "ReturnedOwned";
1184 unsigned cnt = getCount();
1185 if (cnt) Out << " (+ " << cnt << ")";
1186 break;
1187 }
1188
1189 case ReturnedNotOwned: {
1190 Out << "ReturnedNotOwned";
1191 unsigned cnt = getCount();
1192 if (cnt) Out << " (+ " << cnt << ")";
1193 break;
1194 }
1195
Ted Kremenekf3948042008-03-11 19:44:10 +00001196 case Released:
1197 Out << "Released";
1198 break;
1199
Ted Kremenekdb863712008-04-16 22:32:20 +00001200 case ErrorLeak:
1201 Out << "Leaked";
1202 break;
1203
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001204 case ErrorLeakReturned:
1205 Out << "Leaked (Bad naming)";
1206 break;
1207
Ted Kremenekf3948042008-03-11 19:44:10 +00001208 case ErrorUseAfterRelease:
1209 Out << "Use-After-Release [ERROR]";
1210 break;
1211
1212 case ErrorReleaseNotOwned:
1213 Out << "Release of Not-Owned [ERROR]";
1214 break;
1215 }
1216}
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001217
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001218} // end anonymous namespace
1219
1220//===----------------------------------------------------------------------===//
1221// RefBindings - State used to track object reference counts.
1222//===----------------------------------------------------------------------===//
1223
Ted Kremenek2dabd432008-12-05 02:27:51 +00001224typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001225static int RefBIndex = 0;
1226
1227namespace clang {
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001228 template<>
1229 struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
1230 static inline void* GDMIndex() { return &RefBIndex; }
1231 };
1232}
Ted Kremenek6d348932008-10-21 15:53:15 +00001233
1234//===----------------------------------------------------------------------===//
1235// ARBindings - State used to track objects in autorelease pools.
1236//===----------------------------------------------------------------------===//
1237
Ted Kremenek2dabd432008-12-05 02:27:51 +00001238typedef llvm::ImmutableSet<SymbolRef> ARPoolContents;
1239typedef llvm::ImmutableList< std::pair<SymbolRef, ARPoolContents*> > ARBindings;
Ted Kremenek6d348932008-10-21 15:53:15 +00001240static int AutoRBIndex = 0;
1241
1242namespace clang {
1243 template<>
1244 struct GRStateTrait<ARBindings> : public GRStatePartialTrait<ARBindings> {
1245 static inline void* GDMIndex() { return &AutoRBIndex; }
1246 };
1247}
1248
Ted Kremenek13922612008-04-16 20:40:59 +00001249//===----------------------------------------------------------------------===//
1250// Transfer functions.
1251//===----------------------------------------------------------------------===//
1252
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001253namespace {
1254
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001255class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001256public:
Ted Kremenek553cf182008-06-25 21:21:56 +00001257 // Type definitions.
Ted Kremenek2dabd432008-12-05 02:27:51 +00001258 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolRef> >
Ted Kremenek8dd56462008-04-18 03:39:05 +00001259 ReleasesNotOwnedTy;
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001260
Ted Kremenek8dd56462008-04-18 03:39:05 +00001261 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
1262
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001263 typedef llvm::DenseMap<GRExprEngine::NodeTy*,
Ted Kremenek2dabd432008-12-05 02:27:51 +00001264 std::vector<std::pair<SymbolRef,bool> >*>
Ted Kremenekdb863712008-04-16 22:32:20 +00001265 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001266
Ted Kremenekae6814e2008-08-13 21:24:49 +00001267 class BindingsPrinter : public GRState::Printer {
Ted Kremenekf3948042008-03-11 19:44:10 +00001268 public:
Ted Kremenekae6814e2008-08-13 21:24:49 +00001269 virtual void Print(std::ostream& Out, const GRState* state,
1270 const char* nl, const char* sep);
Ted Kremenekf3948042008-03-11 19:44:10 +00001271 };
Ted Kremenek8dd56462008-04-18 03:39:05 +00001272
1273private:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001274 RetainSummaryManager Summaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001275 const LangOptions& LOpts;
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001276
Ted Kremenek9e476de2008-08-12 18:30:56 +00001277 UseAfterReleasesTy UseAfterReleases;
1278 ReleasesNotOwnedTy ReleasesNotOwned;
1279 LeaksTy Leaks;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001280
Ted Kremenek2dabd432008-12-05 02:27:51 +00001281 RefBindings Update(RefBindings B, SymbolRef sym, RefVal V, ArgEffect E,
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001282 RefVal::Kind& hasErr, RefBindings::Factory& RefBFactory);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001283
Ted Kremenek2dabd432008-12-05 02:27:51 +00001284 RefVal::Kind& Update(GRStateRef& state, SymbolRef sym, RefVal V,
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001285 ArgEffect E, RefVal::Kind& hasErr) {
1286
1287 state = state.set<RefBindings>(Update(state.get<RefBindings>(), sym, V,
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001288 E, hasErr,
1289 state.get_context<RefBindings>()));
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001290 return hasErr;
1291 }
1292
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001293 void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
1294 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenekdb863712008-04-16 22:32:20 +00001295 Expr* NodeExpr, Expr* ErrorExpr,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001296 ExplodedNode<GRState>* Pred,
1297 const GRState* St,
Ted Kremenek2dabd432008-12-05 02:27:51 +00001298 RefVal::Kind hasErr, SymbolRef Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +00001299
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001300 std::pair<GRStateRef, bool>
1301 HandleSymbolDeath(GRStateManager& VMgr, const GRState* St,
Ted Kremenek2dabd432008-12-05 02:27:51 +00001302 const Decl* CD, SymbolRef sid, RefVal V, bool& hasLeak);
Ted Kremenekdb863712008-04-16 22:32:20 +00001303
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001304public:
Ted Kremenek13922612008-04-16 20:40:59 +00001305
Ted Kremenek78d46242008-07-22 16:21:24 +00001306 CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
Ted Kremenek377e2302008-04-29 05:33:51 +00001307 : Summaries(Ctx, gcenabled),
Ted Kremenek9e476de2008-08-12 18:30:56 +00001308 LOpts(lopts) {}
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001309
Ted Kremenek8dd56462008-04-18 03:39:05 +00001310 virtual ~CFRefCount() {
1311 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
1312 delete I->second;
1313 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001314
1315 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +00001316
Ted Kremenek1c72ef02008-08-16 00:49:49 +00001317 virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
1318 Printers.push_back(new BindingsPrinter());
Ted Kremenekf3948042008-03-11 19:44:10 +00001319 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001320
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001321 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenek072192b2008-04-30 23:47:44 +00001322 const LangOptions& getLangOptions() const { return LOpts; }
1323
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001324 // Calls.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001325
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001326 void EvalSummary(ExplodedNodeSet<GRState>& Dst,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001327 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001328 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001329 Expr* Ex,
1330 Expr* Receiver,
1331 RetainSummary* Summ,
Ted Kremenek55499762008-06-17 02:43:46 +00001332 ExprIterator arg_beg, ExprIterator arg_end,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001333 ExplodedNode<GRState>* Pred);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001334
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001335 virtual void EvalCall(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +00001336 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001337 GRStmtNodeBuilder<GRState>& Builder,
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001338 CallExpr* CE, SVal L,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001339 ExplodedNode<GRState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001340
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001341
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001342 virtual void EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek85348202008-04-15 23:44:31 +00001343 GRExprEngine& Engine,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001344 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenek85348202008-04-15 23:44:31 +00001345 ObjCMessageExpr* ME,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001346 ExplodedNode<GRState>* Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001347
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001348 bool EvalObjCMessageExprAux(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek85348202008-04-15 23:44:31 +00001349 GRExprEngine& Engine,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001350 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenek85348202008-04-15 23:44:31 +00001351 ObjCMessageExpr* ME,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001352 ExplodedNode<GRState>* Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001353
Ted Kremenek13922612008-04-16 20:40:59 +00001354 // Stores.
1355
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001356 virtual void EvalStore(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek13922612008-04-16 20:40:59 +00001357 GRExprEngine& Engine,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001358 GRStmtNodeBuilder<GRState>& Builder,
1359 Expr* E, ExplodedNode<GRState>* Pred,
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001360 const GRState* St, SVal TargetLV, SVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001361 // End-of-path.
1362
1363 virtual void EvalEndPath(GRExprEngine& Engine,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001364 GREndPathNodeBuilder<GRState>& Builder);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001365
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001366 virtual void EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek652adc62008-04-24 23:57:27 +00001367 GRExprEngine& Engine,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001368 GRStmtNodeBuilder<GRState>& Builder,
1369 ExplodedNode<GRState>* Pred,
Ted Kremenek910e9992008-04-25 01:25:15 +00001370 Stmt* S,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001371 const GRState* St,
1372 const GRStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001373 // Return statements.
1374
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001375 virtual void EvalReturn(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek4fd88972008-04-17 18:12:53 +00001376 GRExprEngine& Engine,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001377 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenek4fd88972008-04-17 18:12:53 +00001378 ReturnStmt* S,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001379 ExplodedNode<GRState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +00001380
1381 // Assumptions.
1382
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001383 virtual const GRState* EvalAssume(GRStateManager& VMgr,
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001384 const GRState* St, SVal Cond,
Ted Kremenek4323a572008-07-10 22:03:41 +00001385 bool Assumption, bool& isFeasible);
Ted Kremenekcb612922008-04-18 19:23:43 +00001386
Ted Kremenekfa34b332008-04-09 01:10:13 +00001387 // Error iterators.
1388
1389 typedef UseAfterReleasesTy::iterator use_after_iterator;
1390 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +00001391 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +00001392
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001393 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
1394 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +00001395
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001396 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
1397 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +00001398
1399 leaks_iterator leaks_begin() { return Leaks.begin(); }
1400 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001401};
1402
1403} // end anonymous namespace
1404
Ted Kremenek8dd56462008-04-18 03:39:05 +00001405
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001406
1407
Ted Kremenekae6814e2008-08-13 21:24:49 +00001408void CFRefCount::BindingsPrinter::Print(std::ostream& Out, const GRState* state,
1409 const char* nl, const char* sep) {
1410
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001411 RefBindings B = state->get<RefBindings>();
Ted Kremenekf3948042008-03-11 19:44:10 +00001412
Ted Kremenekae6814e2008-08-13 21:24:49 +00001413 if (!B.isEmpty())
Ted Kremenekf3948042008-03-11 19:44:10 +00001414 Out << sep << nl;
1415
1416 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1417 Out << (*I).first << " : ";
1418 (*I).second.print(Out);
1419 Out << nl;
1420 }
1421}
1422
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001423static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00001424 return Summ ? Summ->getArg(idx) : MayEscape;
Ted Kremenekf9561e52008-04-11 20:23:24 +00001425}
1426
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001427static inline RetEffect GetRetEffect(RetainSummary* Summ) {
1428 return Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001429}
1430
Ted Kremenek14993892008-05-06 02:41:27 +00001431static inline ArgEffect GetReceiverE(RetainSummary* Summ) {
1432 return Summ ? Summ->getReceiverEffect() : DoNothing;
1433}
1434
Ted Kremenek70a733e2008-07-18 17:24:20 +00001435static inline bool IsEndPath(RetainSummary* Summ) {
1436 return Summ ? Summ->isEndPath() : false;
1437}
1438
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001439void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
1440 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenekdb863712008-04-16 22:32:20 +00001441 Expr* NodeExpr, Expr* ErrorExpr,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001442 ExplodedNode<GRState>* Pred,
1443 const GRState* St,
Ted Kremenek2dabd432008-12-05 02:27:51 +00001444 RefVal::Kind hasErr, SymbolRef Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001445 Builder.BuildSinks = true;
1446 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
1447
1448 if (!N) return;
1449
1450 switch (hasErr) {
1451 default: assert(false);
1452 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001453 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001454 break;
1455
1456 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001457 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001458 break;
1459 }
1460}
1461
Ted Kremenek553cf182008-06-25 21:21:56 +00001462/// GetReturnType - Used to get the return type of a message expression or
1463/// function call with the intention of affixing that type to a tracked symbol.
1464/// While the the return type can be queried directly from RetEx, when
1465/// invoking class methods we augment to the return type to be that of
1466/// a pointer to the class (as opposed it just being id).
1467static QualType GetReturnType(Expr* RetE, ASTContext& Ctx) {
1468
1469 QualType RetTy = RetE->getType();
1470
1471 // FIXME: We aren't handling id<...>.
Chris Lattner8b51fd72008-07-26 22:36:27 +00001472 const PointerType* PT = RetTy->getAsPointerType();
Ted Kremenek553cf182008-06-25 21:21:56 +00001473 if (!PT)
1474 return RetTy;
1475
1476 // If RetEx is not a message expression just return its type.
1477 // If RetEx is a message expression, return its types if it is something
1478 /// more specific than id.
1479
1480 ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(RetE);
1481
1482 if (!ME || !Ctx.isObjCIdType(PT->getPointeeType()))
1483 return RetTy;
1484
1485 ObjCInterfaceDecl* D = ME->getClassInfo().first;
1486
1487 // At this point we know the return type of the message expression is id.
1488 // If we have an ObjCInterceDecl, we know this is a call to a class method
1489 // whose type we can resolve. In such cases, promote the return type to
1490 // Class*.
1491 return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D));
1492}
1493
1494
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001495void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001496 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001497 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001498 Expr* Ex,
1499 Expr* Receiver,
1500 RetainSummary* Summ,
Ted Kremenek55499762008-06-17 02:43:46 +00001501 ExprIterator arg_beg, ExprIterator arg_end,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001502 ExplodedNode<GRState>* Pred) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001503
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001504 // Get the state.
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001505 GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001506 ASTContext& Ctx = Eng.getStateManager().getContext();
Ted Kremenek14993892008-05-06 02:41:27 +00001507
1508 // Evaluate the effect of the arguments.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001509 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001510 unsigned idx = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001511 Expr* ErrorExpr = NULL;
Ted Kremenek2dabd432008-12-05 02:27:51 +00001512 SymbolRef ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001513
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001514 for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001515 SVal V = state.GetSVal(*I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001516
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001517 if (isa<loc::SymbolVal>(V)) {
Ted Kremenek2dabd432008-12-05 02:27:51 +00001518 SymbolRef Sym = cast<loc::SymbolVal>(V).getSymbol();
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001519 if (RefBindings::data_type* T = state.get<RefBindings>(Sym))
1520 if (Update(state, Sym, *T, GetArgE(Summ, idx), hasErr)) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001521 ErrorExpr = *I;
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001522 ErrorSym = Sym;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001523 break;
1524 }
Ted Kremenekb8873552008-04-11 20:51:02 +00001525 }
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001526 else if (isa<Loc>(V)) {
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001527#if 0
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001528 // Nuke all arguments passed by reference.
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001529 StateMgr.Unbind(StVals, cast<Loc>(V));
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001530#else
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001531 if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(&V)) {
Ted Kremenek070a8252008-07-09 18:11:16 +00001532
1533 if (GetArgE(Summ, idx) == DoNothingByRef)
1534 continue;
1535
1536 // Invalidate the value of the variable passed by reference.
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001537
1538 // FIXME: Either this logic should also be replicated in GRSimpleVals
1539 // or should be pulled into a separate "constraint engine."
Ted Kremenek070a8252008-07-09 18:11:16 +00001540
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001541 // FIXME: We can have collisions on the conjured symbol if the
1542 // expression *I also creates conjured symbols. We probably want
1543 // to identify conjured symbols by an expression pair: the enclosing
1544 // expression (the context) and the expression itself. This should
Ted Kremenek070a8252008-07-09 18:11:16 +00001545 // disambiguate conjured symbols.
Ted Kremenek9e240492008-10-04 05:50:14 +00001546
Ted Kremenek993f1c72008-10-17 20:28:54 +00001547 const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
Ted Kremenek90b32362008-12-17 19:42:34 +00001548
1549 // Blast through AnonTypedRegions to get the original region type.
1550 while (R) {
1551 const AnonTypedRegion* ATR = dyn_cast<AnonTypedRegion>(R);
1552 if (!ATR) break;
1553 R = dyn_cast<TypedRegion>(ATR->getSuperRegion());
1554 }
1555
Ted Kremenek9e240492008-10-04 05:50:14 +00001556 if (R) {
Ted Kremenek40e86d92008-12-18 23:34:57 +00001557
1558 // Is the invalidated variable something that we were tracking?
1559 SVal X = state.GetSVal(Loc::MakeVal(R));
1560
1561 if (isa<loc::SymbolVal>(X)) {
1562 SymbolRef Sym = cast<loc::SymbolVal>(X).getSymbol();
1563 state = state.remove<RefBindings>(Sym);
1564 }
1565
Ted Kremenek9e240492008-10-04 05:50:14 +00001566 // Set the value of the variable to be a conjured symbol.
1567 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek6eddeb12008-12-13 21:49:13 +00001568 QualType T = R->getRValueType(Ctx);
Ted Kremenek9e240492008-10-04 05:50:14 +00001569
Ted Kremenekfd301942008-10-17 22:23:12 +00001570 // FIXME: handle structs.
Ted Kremenek062e2f92008-11-13 06:10:40 +00001571 if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
Ted Kremenek2dabd432008-12-05 02:27:51 +00001572 SymbolRef NewSym =
Ted Kremenekfd301942008-10-17 22:23:12 +00001573 Eng.getSymbolManager().getConjuredSymbol(*I, T, Count);
1574
Ted Kremenek90b32362008-12-17 19:42:34 +00001575 state = state.BindLoc(Loc::MakeVal(R),
Ted Kremenekfd301942008-10-17 22:23:12 +00001576 Loc::IsLocType(T)
1577 ? cast<SVal>(loc::SymbolVal(NewSym))
1578 : cast<SVal>(nonloc::SymbolVal(NewSym)));
1579 }
1580 else {
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001581 state = state.BindLoc(*MR, UnknownVal());
Ted Kremenekfd301942008-10-17 22:23:12 +00001582 }
Ted Kremenek9e240492008-10-04 05:50:14 +00001583 }
1584 else
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001585 state = state.BindLoc(*MR, UnknownVal());
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001586 }
1587 else {
1588 // Nuke all other arguments passed by reference.
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001589 state = state.Unbind(cast<Loc>(V));
Ted Kremenek8c5633e2008-07-03 23:26:32 +00001590 }
1591#endif
Ted Kremenekb8873552008-04-11 20:51:02 +00001592 }
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001593 else if (isa<nonloc::LocAsInteger>(V))
1594 state = state.Unbind(cast<nonloc::LocAsInteger>(V).getLoc());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001595 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001596
Ted Kremenek553cf182008-06-25 21:21:56 +00001597 // Evaluate the effect on the message receiver.
Ted Kremenek14993892008-05-06 02:41:27 +00001598 if (!ErrorExpr && Receiver) {
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001599 SVal V = state.GetSVal(Receiver);
1600 if (isa<loc::SymbolVal>(V)) {
Ted Kremenek2dabd432008-12-05 02:27:51 +00001601 SymbolRef Sym = cast<loc::SymbolVal>(V).getSymbol();
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001602 if (const RefVal* T = state.get<RefBindings>(Sym))
1603 if (Update(state, Sym, *T, GetReceiverE(Summ), hasErr)) {
Ted Kremenek14993892008-05-06 02:41:27 +00001604 ErrorExpr = Receiver;
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001605 ErrorSym = Sym;
Ted Kremenek14993892008-05-06 02:41:27 +00001606 }
Ted Kremenek14993892008-05-06 02:41:27 +00001607 }
1608 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001609
Ted Kremenek553cf182008-06-25 21:21:56 +00001610 // Process any errors.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001611 if (hasErr) {
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001612 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, state,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001613 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001614 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001615 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001616
Ted Kremenek70a733e2008-07-18 17:24:20 +00001617 // Consult the summary for the return value.
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001618 RetEffect RE = GetRetEffect(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001619
1620 switch (RE.getKind()) {
1621 default:
1622 assert (false && "Unhandled RetEffect."); break;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001623
Ted Kremenekfd301942008-10-17 22:23:12 +00001624 case RetEffect::NoRet: {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001625
Ted Kremenekf9561e52008-04-11 20:23:24 +00001626 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +00001627 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1628 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001629
Ted Kremenekfd301942008-10-17 22:23:12 +00001630 // FIXME: We eventually should handle structs and other compound types
1631 // that are returned by value.
1632
1633 QualType T = Ex->getType();
1634
Ted Kremenek062e2f92008-11-13 06:10:40 +00001635 if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001636 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek2dabd432008-12-05 02:27:51 +00001637 SymbolRef Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001638
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001639 SVal X = Loc::IsLocType(Ex->getType())
1640 ? cast<SVal>(loc::SymbolVal(Sym))
1641 : cast<SVal>(nonloc::SymbolVal(Sym));
Ted Kremenekf9561e52008-04-11 20:23:24 +00001642
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001643 state = state.BindExpr(Ex, X, false);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001644 }
1645
Ted Kremenek940b1d82008-04-10 23:44:06 +00001646 break;
Ted Kremenekfd301942008-10-17 22:23:12 +00001647 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001648
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001649 case RetEffect::Alias: {
Ted Kremenek553cf182008-06-25 21:21:56 +00001650 unsigned idx = RE.getIndex();
Ted Kremenek55499762008-06-17 02:43:46 +00001651 assert (arg_end >= arg_beg);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001652 assert (idx < (unsigned) (arg_end - arg_beg));
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001653 SVal V = state.GetSVal(*(arg_beg+idx));
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001654 state = state.BindExpr(Ex, V, false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001655 break;
1656 }
1657
Ted Kremenek14993892008-05-06 02:41:27 +00001658 case RetEffect::ReceiverAlias: {
1659 assert (Receiver);
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001660 SVal V = state.GetSVal(Receiver);
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001661 state = state.BindExpr(Ex, V, false);
Ted Kremenek14993892008-05-06 02:41:27 +00001662 break;
1663 }
1664
Ted Kremeneka7344702008-06-23 18:02:52 +00001665 case RetEffect::OwnedAllocatedSymbol:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001666 case RetEffect::OwnedSymbol: {
1667 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek2dabd432008-12-05 02:27:51 +00001668 SymbolRef Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek553cf182008-06-25 21:21:56 +00001669 QualType RetT = GetReturnType(Ex, Eng.getContext());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001670
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001671 state = state.set<RefBindings>(Sym, RefVal::makeOwned(RetT));
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001672 state = state.BindExpr(Ex, loc::SymbolVal(Sym), false);
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001673
1674#if 0
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001675 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek553cf182008-06-25 21:21:56 +00001676 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned(RetT)));
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001677#endif
1678
Ted Kremeneka7344702008-06-23 18:02:52 +00001679 // FIXME: Add a flag to the checker where allocations are allowed to fail.
1680 if (RE.getKind() == RetEffect::OwnedAllocatedSymbol)
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001681 state = state.AddNE(Sym, Eng.getBasicVals().getZeroWithPtrWidth());
Ted Kremeneka7344702008-06-23 18:02:52 +00001682
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001683 break;
1684 }
1685
1686 case RetEffect::NotOwnedSymbol: {
1687 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek2dabd432008-12-05 02:27:51 +00001688 SymbolRef Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek553cf182008-06-25 21:21:56 +00001689 QualType RetT = GetReturnType(Ex, Eng.getContext());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001690
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001691 state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RetT));
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001692 state = state.BindExpr(Ex, loc::SymbolVal(Sym), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001693 break;
1694 }
1695 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001696
Ted Kremenek70a733e2008-07-18 17:24:20 +00001697 // Is this a sink?
1698 if (IsEndPath(Summ))
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001699 Builder.MakeSinkNode(Dst, Ex, Pred, state);
Ted Kremenek70a733e2008-07-18 17:24:20 +00001700 else
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001701 Builder.MakeNode(Dst, Ex, Pred, state);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001702}
1703
1704
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001705void CFRefCount::EvalCall(ExplodedNodeSet<GRState>& Dst,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001706 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001707 GRStmtNodeBuilder<GRState>& Builder,
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001708 CallExpr* CE, SVal L,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001709 ExplodedNode<GRState>* Pred) {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001710
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001711 RetainSummary* Summ = !isa<loc::FuncVal>(L) ? 0
1712 : Summaries.getSummary(cast<loc::FuncVal>(L).getDecl());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001713
1714 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1715 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001716}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001717
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001718void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek85348202008-04-15 23:44:31 +00001719 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001720 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenek85348202008-04-15 23:44:31 +00001721 ObjCMessageExpr* ME,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001722 ExplodedNode<GRState>* Pred) {
Ted Kremenekb3095252008-05-06 04:20:12 +00001723 RetainSummary* Summ;
Ted Kremenek9040c652008-05-01 21:31:50 +00001724
Ted Kremenek553cf182008-06-25 21:21:56 +00001725 if (Expr* Receiver = ME->getReceiver()) {
1726 // We need the type-information of the tracked receiver object
1727 // Retrieve it from the state.
1728 ObjCInterfaceDecl* ID = 0;
1729
1730 // FIXME: Wouldn't it be great if this code could be reduced? It's just
1731 // a chain of lookups.
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001732 const GRState* St = Builder.GetState(Pred);
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001733 SVal V = Eng.getStateManager().GetSVal(St, Receiver );
Ted Kremenek553cf182008-06-25 21:21:56 +00001734
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001735 if (isa<loc::SymbolVal>(V)) {
Ted Kremenek2dabd432008-12-05 02:27:51 +00001736 SymbolRef Sym = cast<loc::SymbolVal>(V).getSymbol();
Ted Kremenek553cf182008-06-25 21:21:56 +00001737
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001738 if (const RefVal* T = St->get<RefBindings>(Sym)) {
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001739 QualType Ty = T->getType();
Ted Kremenek553cf182008-06-25 21:21:56 +00001740
1741 if (const PointerType* PT = Ty->getAsPointerType()) {
1742 QualType PointeeTy = PT->getPointeeType();
1743
1744 if (ObjCInterfaceType* IT = dyn_cast<ObjCInterfaceType>(PointeeTy))
1745 ID = IT->getDecl();
1746 }
1747 }
1748 }
1749
1750 Summ = Summaries.getMethodSummary(ME, ID);
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001751
Ted Kremenek896cd9d2008-10-23 01:56:15 +00001752 // Special-case: are we sending a mesage to "self"?
1753 // This is a hack. When we have full-IP this should be removed.
1754 if (!Summ) {
1755 ObjCMethodDecl* MD =
1756 dyn_cast<ObjCMethodDecl>(&Eng.getGraph().getCodeDecl());
1757
1758 if (MD) {
1759 if (Expr* Receiver = ME->getReceiver()) {
1760 SVal X = Eng.getStateManager().GetSVal(St, Receiver);
1761 if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X))
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001762 if (L->getRegion() == Eng.getStateManager().getSelfRegion(St)) {
1763 // Create a summmary where all of the arguments "StopTracking".
1764 Summ = Summaries.getPersistentSummary(RetEffect::MakeNoRet(),
1765 DoNothing,
1766 StopTracking);
1767 }
Ted Kremenek896cd9d2008-10-23 01:56:15 +00001768 }
1769 }
1770 }
Ted Kremenek553cf182008-06-25 21:21:56 +00001771 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001772 else
Ted Kremenek1f180c32008-06-23 22:21:20 +00001773 Summ = Summaries.getClassMethodSummary(ME->getClassName(),
1774 ME->getSelector());
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001775
Ted Kremenekb3095252008-05-06 04:20:12 +00001776 EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
1777 ME->arg_begin(), ME->arg_end(), Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001778}
Ted Kremenekb3095252008-05-06 04:20:12 +00001779
Ted Kremenek13922612008-04-16 20:40:59 +00001780// Stores.
1781
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001782void CFRefCount::EvalStore(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek13922612008-04-16 20:40:59 +00001783 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001784 GRStmtNodeBuilder<GRState>& Builder,
1785 Expr* E, ExplodedNode<GRState>* Pred,
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001786 const GRState* St, SVal TargetLV, SVal Val) {
Ted Kremenek13922612008-04-16 20:40:59 +00001787
1788 // Check if we have a binding for "Val" and if we are storing it to something
1789 // we don't understand or otherwise the value "escapes" the function.
1790
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001791 if (!isa<loc::SymbolVal>(Val))
Ted Kremenek13922612008-04-16 20:40:59 +00001792 return;
1793
1794 // Are we storing to something that causes the value to "escape"?
1795
1796 bool escapes = false;
1797
Ted Kremeneka496d162008-10-18 03:49:51 +00001798 // A value escapes in three possible cases (this may change):
1799 //
1800 // (1) we are binding to something that is not a memory region.
1801 // (2) we are binding to a memregion that does not have stack storage
1802 // (3) we are binding to a memregion with stack storage that the store
1803 // does not understand.
1804
Ted Kremenek2dabd432008-12-05 02:27:51 +00001805 SymbolRef Sym = cast<loc::SymbolVal>(Val).getSymbol();
Ted Kremeneka496d162008-10-18 03:49:51 +00001806 GRStateRef state(St, Eng.getStateManager());
1807
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001808 if (!isa<loc::MemRegionVal>(TargetLV))
Ted Kremenek13922612008-04-16 20:40:59 +00001809 escapes = true;
Ted Kremenek9e240492008-10-04 05:50:14 +00001810 else {
Ted Kremenek993f1c72008-10-17 20:28:54 +00001811 const MemRegion* R = cast<loc::MemRegionVal>(TargetLV).getRegion();
Ted Kremenek9e240492008-10-04 05:50:14 +00001812 escapes = !Eng.getStateManager().hasStackStorage(R);
Ted Kremeneka496d162008-10-18 03:49:51 +00001813
1814 if (!escapes) {
1815 // To test (3), generate a new state with the binding removed. If it is
1816 // the same state, then it escapes (since the store cannot represent
1817 // the binding).
Ted Kremeneka441b7e2008-11-12 19:22:09 +00001818 GRStateRef stateNew = state.BindLoc(cast<Loc>(TargetLV), Val);
Ted Kremeneka496d162008-10-18 03:49:51 +00001819 escapes = (stateNew == state);
1820 }
Ted Kremenek9e240492008-10-04 05:50:14 +00001821 }
Ted Kremenek13922612008-04-16 20:40:59 +00001822
1823 if (!escapes)
1824 return;
Ted Kremeneka496d162008-10-18 03:49:51 +00001825
1826 // Do we have a reference count binding?
1827 // FIXME: Is this step even needed? We do blow away the binding anyway.
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001828 if (!state.get<RefBindings>(Sym))
Ted Kremenek13922612008-04-16 20:40:59 +00001829 return;
1830
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001831 // Nuke the binding.
Ted Kremenekb9d17f92008-08-17 03:20:02 +00001832 state = state.remove<RefBindings>(Sym);
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001833
Ted Kremenek13922612008-04-16 20:40:59 +00001834 // Hand of the remaining logic to the parent implementation.
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001835 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, state, TargetLV, Val);
Ted Kremenekdb863712008-04-16 22:32:20 +00001836}
1837
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001838// End-of-path.
1839
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001840
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001841std::pair<GRStateRef,bool>
1842CFRefCount::HandleSymbolDeath(GRStateManager& VMgr,
1843 const GRState* St, const Decl* CD,
Ted Kremenek2dabd432008-12-05 02:27:51 +00001844 SymbolRef sid,
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001845 RefVal V, bool& hasLeak) {
Ted Kremenekdb863712008-04-16 22:32:20 +00001846
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001847 GRStateRef state(St, VMgr);
Sanjiv Gupta31fc07d2008-10-31 09:52:39 +00001848 assert ((!V.isReturnedOwned() || CD) &&
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001849 "CodeDecl must be available for reporting ReturnOwned errors.");
Ted Kremenek896cd9d2008-10-23 01:56:15 +00001850
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001851 if (V.isReturnedOwned() && V.getCount() == 0)
1852 if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
Chris Lattner077bf5e2008-11-24 03:33:13 +00001853 std::string s = MD->getSelector().getAsString();
Ted Kremenek4c79e552008-11-05 16:54:44 +00001854 if (!followsReturnRule(s.c_str())) {
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001855 hasLeak = true;
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001856 state = state.set<RefBindings>(sid, V ^ RefVal::ErrorLeakReturned);
1857 return std::make_pair(state, true);
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001858 }
1859 }
Ted Kremenek896cd9d2008-10-23 01:56:15 +00001860
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001861 // All other cases.
1862
1863 hasLeak = V.isOwned() ||
1864 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001865
Ted Kremenekdb863712008-04-16 22:32:20 +00001866 if (!hasLeak)
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001867 return std::make_pair(state.remove<RefBindings>(sid), false);
Ted Kremenekdb863712008-04-16 22:32:20 +00001868
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001869 return std::make_pair(state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak),
1870 false);
Ted Kremenekdb863712008-04-16 22:32:20 +00001871}
1872
1873void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001874 GREndPathNodeBuilder<GRState>& Builder) {
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001875
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001876 const GRState* St = Builder.getState();
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001877 RefBindings B = St->get<RefBindings>();
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001878
Ted Kremenek2dabd432008-12-05 02:27:51 +00001879 llvm::SmallVector<std::pair<SymbolRef, bool>, 10> Leaked;
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00001880 const Decl* CodeDecl = &Eng.getGraph().getCodeDecl();
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001881
Ted Kremenekdb863712008-04-16 22:32:20 +00001882 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1883 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001884
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001885 std::pair<GRStateRef, bool> X =
1886 HandleSymbolDeath(Eng.getStateManager(), St, CodeDecl,
1887 (*I).first, (*I).second, hasLeak);
Ted Kremenekdb863712008-04-16 22:32:20 +00001888
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001889 St = X.first;
1890 if (hasLeak) Leaked.push_back(std::make_pair((*I).first, X.second));
Ted Kremenekdb863712008-04-16 22:32:20 +00001891 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001892
1893 if (Leaked.empty())
1894 return;
1895
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001896 ExplodedNode<GRState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001897
Ted Kremenek652adc62008-04-24 23:57:27 +00001898 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001899 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001900
Ted Kremenek2dabd432008-12-05 02:27:51 +00001901 std::vector<std::pair<SymbolRef,bool> >*& LeaksAtNode = Leaks[N];
Ted Kremenek8dd56462008-04-18 03:39:05 +00001902 assert (!LeaksAtNode);
Ted Kremenek2dabd432008-12-05 02:27:51 +00001903 LeaksAtNode = new std::vector<std::pair<SymbolRef,bool> >();
Ted Kremenekdb863712008-04-16 22:32:20 +00001904
Ted Kremenek2dabd432008-12-05 02:27:51 +00001905 for (llvm::SmallVector<std::pair<SymbolRef,bool>, 10>::iterator
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001906 I = Leaked.begin(), E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001907 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001908}
1909
Ted Kremenek652adc62008-04-24 23:57:27 +00001910// Dead symbols.
1911
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001912void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek652adc62008-04-24 23:57:27 +00001913 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001914 GRStmtNodeBuilder<GRState>& Builder,
1915 ExplodedNode<GRState>* Pred,
Ted Kremenek910e9992008-04-25 01:25:15 +00001916 Stmt* S,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001917 const GRState* St,
1918 const GRStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001919
Ted Kremenek652adc62008-04-24 23:57:27 +00001920 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1921
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001922 RefBindings B = St->get<RefBindings>();
Ted Kremenek2dabd432008-12-05 02:27:51 +00001923 llvm::SmallVector<std::pair<SymbolRef,bool>, 10> Leaked;
Ted Kremenek652adc62008-04-24 23:57:27 +00001924
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001925 for (GRStateManager::DeadSymbolsTy::const_iterator
Ted Kremenek652adc62008-04-24 23:57:27 +00001926 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1927
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001928 const RefVal* T = B.lookup(*I);
Ted Kremenek652adc62008-04-24 23:57:27 +00001929
1930 if (!T)
1931 continue;
1932
1933 bool hasLeak = false;
1934
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001935 std::pair<GRStateRef, bool> X
1936 = HandleSymbolDeath(Eng.getStateManager(), St, 0, *I, *T, hasLeak);
1937
1938 St = X.first;
Ted Kremenek652adc62008-04-24 23:57:27 +00001939
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001940 if (hasLeak)
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001941 Leaked.push_back(std::make_pair(*I,X.second));
Ted Kremenek652adc62008-04-24 23:57:27 +00001942 }
1943
1944 if (Leaked.empty())
1945 return;
1946
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001947 ExplodedNode<GRState>* N = Builder.MakeNode(Dst, S, Pred, St);
Ted Kremenek652adc62008-04-24 23:57:27 +00001948
1949 if (!N)
1950 return;
1951
Ted Kremenek2dabd432008-12-05 02:27:51 +00001952 std::vector<std::pair<SymbolRef,bool> >*& LeaksAtNode = Leaks[N];
Ted Kremenek652adc62008-04-24 23:57:27 +00001953 assert (!LeaksAtNode);
Ted Kremenek2dabd432008-12-05 02:27:51 +00001954 LeaksAtNode = new std::vector<std::pair<SymbolRef,bool> >();
Ted Kremenek652adc62008-04-24 23:57:27 +00001955
Ted Kremenek2dabd432008-12-05 02:27:51 +00001956 for (llvm::SmallVector<std::pair<SymbolRef,bool>, 10>::iterator
Ted Kremenekf9790ae2008-10-24 20:32:50 +00001957 I = Leaked.begin(), E = Leaked.end(); I != E; ++I)
Ted Kremenek652adc62008-04-24 23:57:27 +00001958 (*LeaksAtNode).push_back(*I);
1959}
1960
Ted Kremenek4fd88972008-04-17 18:12:53 +00001961 // Return statements.
1962
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001963void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
Ted Kremenek4fd88972008-04-17 18:12:53 +00001964 GRExprEngine& Eng,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001965 GRStmtNodeBuilder<GRState>& Builder,
Ted Kremenek4fd88972008-04-17 18:12:53 +00001966 ReturnStmt* S,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00001967 ExplodedNode<GRState>* Pred) {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001968
1969 Expr* RetE = S->getRetValue();
1970 if (!RetE) return;
1971
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001972 GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001973 SVal V = state.GetSVal(RetE);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001974
Zhongxing Xu1c96b242008-10-17 05:57:07 +00001975 if (!isa<loc::SymbolVal>(V))
Ted Kremenek4fd88972008-04-17 18:12:53 +00001976 return;
1977
1978 // Get the reference count binding (if any).
Ted Kremenek2dabd432008-12-05 02:27:51 +00001979 SymbolRef Sym = cast<loc::SymbolVal>(V).getSymbol();
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001980 const RefVal* T = state.get<RefBindings>(Sym);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001981
1982 if (!T)
1983 return;
1984
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001985 // Change the reference count.
Ted Kremeneke8fdc832008-07-07 16:21:19 +00001986 RefVal X = *T;
Ted Kremenek4fd88972008-04-17 18:12:53 +00001987
Ted Kremenek72cd17f2008-08-14 21:16:54 +00001988 switch (X.getKind()) {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001989 case RefVal::Owned: {
1990 unsigned cnt = X.getCount();
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00001991 assert (cnt > 0);
1992 X = RefVal::makeReturnedOwned(cnt - 1);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001993 break;
1994 }
1995
1996 case RefVal::NotOwned: {
1997 unsigned cnt = X.getCount();
1998 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1999 : RefVal::makeReturnedNotOwned();
2000 break;
2001 }
2002
2003 default:
Ted Kremenek4fd88972008-04-17 18:12:53 +00002004 return;
2005 }
2006
2007 // Update the binding.
Ted Kremenekb9d17f92008-08-17 03:20:02 +00002008 state = state.set<RefBindings>(Sym, X);
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002009 Builder.MakeNode(Dst, S, Pred, state);
Ted Kremenek4fd88972008-04-17 18:12:53 +00002010}
2011
Ted Kremenekcb612922008-04-18 19:23:43 +00002012// Assumptions.
2013
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002014const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
2015 const GRState* St,
Zhongxing Xu1c96b242008-10-17 05:57:07 +00002016 SVal Cond, bool Assumption,
Ted Kremenek4323a572008-07-10 22:03:41 +00002017 bool& isFeasible) {
Ted Kremenekcb612922008-04-18 19:23:43 +00002018
2019 // FIXME: We may add to the interface of EvalAssume the list of symbols
2020 // whose assumptions have changed. For now we just iterate through the
2021 // bindings and check if any of the tracked symbols are NULL. This isn't
2022 // too bad since the number of symbols we will track in practice are
2023 // probably small and EvalAssume is only called at branches and a few
2024 // other places.
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002025 RefBindings B = St->get<RefBindings>();
Ted Kremenekcb612922008-04-18 19:23:43 +00002026
2027 if (B.isEmpty())
2028 return St;
2029
2030 bool changed = false;
Ted Kremenekb9d17f92008-08-17 03:20:02 +00002031
2032 GRStateRef state(St, VMgr);
2033 RefBindings::Factory& RefBFactory = state.get_context<RefBindings>();
Ted Kremenekcb612922008-04-18 19:23:43 +00002034
2035 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
Ted Kremenekcb612922008-04-18 19:23:43 +00002036 // Check if the symbol is null (or equal to any constant).
2037 // If this is the case, stop tracking the symbol.
Zhongxing Xu39cfed32008-08-29 14:52:36 +00002038 if (VMgr.getSymVal(St, I.getKey())) {
Ted Kremenekcb612922008-04-18 19:23:43 +00002039 changed = true;
2040 B = RefBFactory.Remove(B, I.getKey());
2041 }
2042 }
2043
Ted Kremenekb9d17f92008-08-17 03:20:02 +00002044 if (changed)
2045 state = state.set<RefBindings>(B);
Ted Kremenekcb612922008-04-18 19:23:43 +00002046
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002047 return state;
Ted Kremenekcb612922008-04-18 19:23:43 +00002048}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002049
Ted Kremenek2dabd432008-12-05 02:27:51 +00002050RefBindings CFRefCount::Update(RefBindings B, SymbolRef sym,
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002051 RefVal V, ArgEffect E,
Ted Kremenekb9d17f92008-08-17 03:20:02 +00002052 RefVal::Kind& hasErr,
2053 RefBindings::Factory& RefBFactory) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002054
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002055 // FIXME: This dispatch can potentially be sped up by unifiying it into
2056 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002057
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002058 switch (E) {
2059 default:
2060 assert (false && "Unhandled CFRef transition.");
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002061
2062 case MayEscape:
2063 if (V.getKind() == RefVal::Owned) {
Ted Kremenek553cf182008-06-25 21:21:56 +00002064 V = V ^ RefVal::NotOwned;
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002065 break;
2066 }
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002067 // Fall-through.
Ted Kremenek070a8252008-07-09 18:11:16 +00002068 case DoNothingByRef:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002069 case DoNothing:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00002070 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenek553cf182008-06-25 21:21:56 +00002071 V = V ^ RefVal::ErrorUseAfterRelease;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00002072 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00002073 break;
Ted Kremenek9e476de2008-08-12 18:30:56 +00002074 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002075 return B;
Ted Kremeneke19f4492008-06-30 16:57:41 +00002076
Ted Kremenek80d753f2008-07-01 00:01:02 +00002077 case Autorelease:
Ted Kremenek14993892008-05-06 02:41:27 +00002078 case StopTracking:
2079 return RefBFactory.Remove(B, sym);
Ted Kremenek9e476de2008-08-12 18:30:56 +00002080
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002081 case IncRef:
2082 switch (V.getKind()) {
2083 default:
2084 assert(false);
2085
2086 case RefVal::Owned:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002087 case RefVal::NotOwned:
Ted Kremenek553cf182008-06-25 21:21:56 +00002088 V = V + 1;
Ted Kremenek9e476de2008-08-12 18:30:56 +00002089 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002090 case RefVal::Released:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00002091 if (isGCEnabled())
Ted Kremenek553cf182008-06-25 21:21:56 +00002092 V = V ^ RefVal::Owned;
Ted Kremenek65c91652008-04-29 05:44:10 +00002093 else {
Ted Kremenek553cf182008-06-25 21:21:56 +00002094 V = V ^ RefVal::ErrorUseAfterRelease;
Ted Kremenek65c91652008-04-29 05:44:10 +00002095 hasErr = V.getKind();
2096 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002097 break;
Ted Kremenek9e476de2008-08-12 18:30:56 +00002098 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00002099 break;
2100
Ted Kremenek553cf182008-06-25 21:21:56 +00002101 case SelfOwn:
2102 V = V ^ RefVal::NotOwned;
Ted Kremenek9e476de2008-08-12 18:30:56 +00002103 // Fall-through.
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002104 case DecRef:
2105 switch (V.getKind()) {
2106 default:
2107 assert (false);
Ted Kremenek9e476de2008-08-12 18:30:56 +00002108
Ted Kremenek553cf182008-06-25 21:21:56 +00002109 case RefVal::Owned:
2110 V = V.getCount() > 1 ? V - 1 : V ^ RefVal::Released;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002111 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002112
Ted Kremenek553cf182008-06-25 21:21:56 +00002113 case RefVal::NotOwned:
2114 if (V.getCount() > 0)
2115 V = V - 1;
Ted Kremenek61b9f872008-04-10 23:09:18 +00002116 else {
Ted Kremenek553cf182008-06-25 21:21:56 +00002117 V = V ^ RefVal::ErrorReleaseNotOwned;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00002118 hasErr = V.getKind();
Ted Kremenek9e476de2008-08-12 18:30:56 +00002119 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002120 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002121
2122 case RefVal::Released:
Ted Kremenek553cf182008-06-25 21:21:56 +00002123 V = V ^ RefVal::ErrorUseAfterRelease;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00002124 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002125 break;
Ted Kremenek9e476de2008-08-12 18:30:56 +00002126 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00002127 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002128 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00002129 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002130}
2131
Ted Kremenekfa34b332008-04-09 01:10:13 +00002132//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002133// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00002134//===----------------------------------------------------------------------===//
2135
Ted Kremenek8dd56462008-04-18 03:39:05 +00002136namespace {
2137
2138 //===-------------===//
2139 // Bug Descriptions. //
2140 //===-------------===//
2141
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00002142 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00002143 protected:
2144 CFRefCount& TF;
2145
2146 public:
2147 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenek072192b2008-04-30 23:47:44 +00002148
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002149 CFRefCount& getTF() { return TF; }
Ted Kremenek789deac2008-05-05 23:16:31 +00002150 const CFRefCount& getTF() const { return TF; }
2151
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002152 virtual bool isLeak() const { return false; }
Ted Kremenek8c036c72008-09-20 04:23:38 +00002153
2154 const char* getCategory() const {
Ted Kremenek062bae02008-09-27 22:02:42 +00002155 return "Memory (Core Foundation/Objective-C)";
Ted Kremenek8c036c72008-09-20 04:23:38 +00002156 }
Ted Kremenek8dd56462008-04-18 03:39:05 +00002157 };
2158
2159 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
2160 public:
2161 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
2162
2163 virtual const char* getName() const {
Ted Kremenek8c036c72008-09-20 04:23:38 +00002164 return "use-after-release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002165 }
2166 virtual const char* getDescription() const {
Ted Kremenek9e476de2008-08-12 18:30:56 +00002167 return "Reference-counted object is used after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002168 }
2169
2170 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002171 };
2172
2173 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
2174 public:
2175 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
2176
2177 virtual const char* getName() const {
Ted Kremenek8c036c72008-09-20 04:23:38 +00002178 return "bad release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002179 }
2180 virtual const char* getDescription() const {
2181 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002182 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00002183 "The object is not owned at this point by the caller.";
2184 }
2185
2186 virtual void EmitWarnings(BugReporter& BR);
2187 };
2188
2189 class VISIBILITY_HIDDEN Leak : public CFRefBug {
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002190 bool isReturn;
Ted Kremenek8dd56462008-04-18 03:39:05 +00002191 public:
2192 Leak(CFRefCount& tf) : CFRefBug(tf) {}
2193
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002194 void setIsReturn(bool x) { isReturn = x; }
2195
Ted Kremenek8dd56462008-04-18 03:39:05 +00002196 virtual const char* getName() const {
Ted Kremenek432af592008-05-06 18:11:36 +00002197
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002198 if (!isReturn) {
2199 if (getTF().isGCEnabled())
2200 return "leak (GC)";
2201
2202 if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
2203 return "leak (hybrid MM, non-GC)";
2204
2205 assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
2206 return "leak";
2207 }
2208 else {
2209 if (getTF().isGCEnabled())
Ted Kremenek9d1d5702008-10-24 21:22:44 +00002210 return "[naming convention] leak of returned object (GC)";
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002211
2212 if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
Ted Kremenek9d1d5702008-10-24 21:22:44 +00002213 return "[naming convention] leak of returned object (hybrid MM, "
2214 "non-GC)";
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002215
2216 assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
Ted Kremenek9d1d5702008-10-24 21:22:44 +00002217 return "[naming convention] leak of returned object";
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002218 }
Ted Kremenek8dd56462008-04-18 03:39:05 +00002219 }
2220
2221 virtual const char* getDescription() const {
Ted Kremenek9e476de2008-08-12 18:30:56 +00002222 return "Object leaked";
Ted Kremenek8dd56462008-04-18 03:39:05 +00002223 }
2224
2225 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002226 virtual void GetErrorNodes(std::vector<ExplodedNode<GRState>*>& Nodes);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002227 virtual bool isLeak() const { return true; }
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002228 virtual bool isCached(BugReport& R);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002229 };
2230
2231 //===---------===//
2232 // Bug Reports. //
2233 //===---------===//
2234
2235 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
Ted Kremenek2dabd432008-12-05 02:27:51 +00002236 SymbolRef Sym;
Ted Kremenek8dd56462008-04-18 03:39:05 +00002237 public:
Ted Kremenek2dabd432008-12-05 02:27:51 +00002238 CFRefReport(CFRefBug& D, ExplodedNode<GRState> *n, SymbolRef sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00002239 : RangedBugReport(D, n), Sym(sym) {}
2240
2241 virtual ~CFRefReport() {}
2242
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002243 CFRefBug& getBugType() {
2244 return (CFRefBug&) RangedBugReport::getBugType();
2245 }
2246 const CFRefBug& getBugType() const {
2247 return (const CFRefBug&) RangedBugReport::getBugType();
2248 }
2249
2250 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
2251 const SourceRange*& end) {
2252
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002253 if (!getBugType().isLeak())
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002254 RangedBugReport::getRanges(BR, beg, end);
Ted Kremenek9e476de2008-08-12 18:30:56 +00002255 else
2256 beg = end = 0;
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00002257 }
2258
Ted Kremenek2dabd432008-12-05 02:27:51 +00002259 SymbolRef getSymbol() const { return Sym; }
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002260
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002261 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002262 ExplodedNode<GRState>* N);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002263
Ted Kremenek072192b2008-04-30 23:47:44 +00002264 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek8dd56462008-04-18 03:39:05 +00002265
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002266 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<GRState>* N,
2267 ExplodedNode<GRState>* PrevN,
2268 ExplodedGraph<GRState>& G,
Ted Kremenek8dd56462008-04-18 03:39:05 +00002269 BugReporter& BR);
2270 };
2271
2272
2273} // end anonymous namespace
2274
2275void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek8dd56462008-04-18 03:39:05 +00002276 Eng.Register(new UseAfterRelease(*this));
2277 Eng.Register(new BadRelease(*this));
2278 Eng.Register(new Leak(*this));
2279}
2280
Ted Kremenek072192b2008-04-30 23:47:44 +00002281
2282static const char* Msgs[] = {
2283 "Code is compiled in garbage collection only mode" // GC only
2284 " (the bug occurs with garbage collection enabled).",
2285
2286 "Code is compiled without garbage collection.", // No GC.
2287
2288 "Code is compiled for use with and without garbage collection (GC)."
2289 " The bug occurs with GC enabled.", // Hybrid, with GC.
2290
2291 "Code is compiled for use with and without garbage collection (GC)."
2292 " The bug occurs in non-GC mode." // Hyrbird, without GC/
2293};
2294
2295std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
2296 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
2297
2298 switch (TF.getLangOptions().getGCMode()) {
2299 default:
2300 assert(false);
Ted Kremenek31593ac2008-05-01 04:02:04 +00002301
2302 case LangOptions::GCOnly:
2303 assert (TF.isGCEnabled());
Ted Kremenek9e476de2008-08-12 18:30:56 +00002304 return std::make_pair(&Msgs[0], &Msgs[0]+1);
2305
Ted Kremenek072192b2008-04-30 23:47:44 +00002306 case LangOptions::NonGC:
2307 assert (!TF.isGCEnabled());
Ted Kremenek072192b2008-04-30 23:47:44 +00002308 return std::make_pair(&Msgs[1], &Msgs[1]+1);
2309
2310 case LangOptions::HybridGC:
2311 if (TF.isGCEnabled())
2312 return std::make_pair(&Msgs[2], &Msgs[2]+1);
2313 else
2314 return std::make_pair(&Msgs[3], &Msgs[3]+1);
2315 }
2316}
2317
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002318PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<GRState>* N,
2319 ExplodedNode<GRState>* PrevN,
2320 ExplodedGraph<GRState>& G,
Ted Kremenek8dd56462008-04-18 03:39:05 +00002321 BugReporter& BR) {
2322
2323 // Check if the type state has changed.
2324
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002325 const GRState* PrevSt = PrevN->getState();
2326 const GRState* CurrSt = N->getState();
Ted Kremenek8dd56462008-04-18 03:39:05 +00002327
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002328 RefBindings PrevB = PrevSt->get<RefBindings>();
2329 RefBindings CurrB = CurrSt->get<RefBindings>();
Ted Kremenek8dd56462008-04-18 03:39:05 +00002330
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002331 const RefVal* PrevT = PrevB.lookup(Sym);
2332 const RefVal* CurrT = CurrB.lookup(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002333
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002334 if (!CurrT)
2335 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00002336
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002337 const char* Msg = NULL;
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002338 const RefVal& CurrV = *CurrB.lookup(Sym);
Ted Kremenekce48e002008-05-05 17:53:17 +00002339
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002340 if (!PrevT) {
2341
Ted Kremenekce48e002008-05-05 17:53:17 +00002342 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2343
2344 if (CurrV.isOwned()) {
2345
2346 if (isa<CallExpr>(S))
2347 Msg = "Function call returns an object with a +1 retain count"
2348 " (owning reference).";
2349 else {
2350 assert (isa<ObjCMessageExpr>(S));
2351 Msg = "Method returns an object with a +1 retain count"
2352 " (owning reference).";
2353 }
2354 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002355 else {
2356 assert (CurrV.isNotOwned());
Ted Kremenekce48e002008-05-05 17:53:17 +00002357
2358 if (isa<CallExpr>(S))
2359 Msg = "Function call returns an object with a +0 retain count"
2360 " (non-owning reference).";
2361 else {
2362 assert (isa<ObjCMessageExpr>(S));
2363 Msg = "Method returns an object with a +0 retain count"
2364 " (non-owning reference).";
2365 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002366 }
Ted Kremenekce48e002008-05-05 17:53:17 +00002367
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002368 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
2369 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
2370
2371 if (Expr* Exp = dyn_cast<Expr>(S))
2372 P->addRange(Exp->getSourceRange());
2373
2374 return P;
2375 }
2376
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002377 // Determine if the typestate has changed.
2378 RefVal PrevV = *PrevB.lookup(Sym);
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002379
2380 if (PrevV == CurrV)
2381 return NULL;
2382
2383 // The typestate has changed.
2384
2385 std::ostringstream os;
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002386 std::string s;
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002387
2388 switch (CurrV.getKind()) {
2389 case RefVal::Owned:
2390 case RefVal::NotOwned:
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002391
2392 if (PrevV.getCount() == CurrV.getCount())
2393 return 0;
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002394
2395 if (PrevV.getCount() > CurrV.getCount())
2396 os << "Reference count decremented.";
2397 else
2398 os << "Reference count incremented.";
2399
Ted Kremenek3eabf1c2008-05-22 17:31:13 +00002400 if (unsigned Count = CurrV.getCount()) {
Ted Kremenekce48e002008-05-05 17:53:17 +00002401
2402 os << " Object has +" << Count;
Ted Kremenek79c140b2008-04-18 05:32:44 +00002403
Ted Kremenekce48e002008-05-05 17:53:17 +00002404 if (Count > 1)
2405 os << " retain counts.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00002406 else
Ted Kremenekce48e002008-05-05 17:53:17 +00002407 os << " retain count.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00002408 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002409
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002410 s = os.str();
2411 Msg = s.c_str();
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002412
2413 break;
2414
2415 case RefVal::Released:
2416 Msg = "Object released.";
2417 break;
2418
2419 case RefVal::ReturnedOwned:
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002420 Msg = "Object returned to caller as an owning reference (single retain "
2421 "count transferred to caller).";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002422 break;
2423
2424 case RefVal::ReturnedNotOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00002425 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002426 break;
2427
2428 default:
2429 return NULL;
2430 }
2431
2432 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
2433 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
2434 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
2435
2436 // Add the range by scanning the children of the statement for any bindings
2437 // to Sym.
2438
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002439 GRStateManager& VSM = cast<GRBugReporter>(BR).getStateManager();
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002440
2441 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
2442 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
Zhongxing Xu1c96b242008-10-17 05:57:07 +00002443 SVal X = VSM.GetSVal(CurrSt, Exp);
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002444
Zhongxing Xu1c96b242008-10-17 05:57:07 +00002445 if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&X))
Ted Kremenek2cf943a2008-04-18 04:55:01 +00002446 if (SV->getSymbol() == Sym) {
2447 P->addRange(Exp->getSourceRange()); break;
2448 }
2449 }
2450
2451 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00002452}
2453
Ted Kremenek9e240492008-10-04 05:50:14 +00002454namespace {
2455class VISIBILITY_HIDDEN FindUniqueBinding :
2456 public StoreManager::BindingsHandler {
Ted Kremenek2dabd432008-12-05 02:27:51 +00002457 SymbolRef Sym;
Ted Kremenek9e240492008-10-04 05:50:14 +00002458 MemRegion* Binding;
2459 bool First;
2460
2461 public:
Ted Kremenek2dabd432008-12-05 02:27:51 +00002462 FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {}
Ted Kremenek9e240492008-10-04 05:50:14 +00002463
Zhongxing Xu1c96b242008-10-17 05:57:07 +00002464 bool HandleBinding(StoreManager& SMgr, Store store, MemRegion* R, SVal val) {
2465 if (const loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&val)) {
Ted Kremenek9e240492008-10-04 05:50:14 +00002466 if (SV->getSymbol() != Sym)
2467 return true;
2468 }
Zhongxing Xu1c96b242008-10-17 05:57:07 +00002469 else if (const nonloc::SymbolVal* SV=dyn_cast<nonloc::SymbolVal>(&val)) {
Ted Kremenek9e240492008-10-04 05:50:14 +00002470 if (SV->getSymbol() != Sym)
2471 return true;
2472 }
2473 else
2474 return true;
2475
2476 if (Binding) {
2477 First = false;
2478 return false;
2479 }
2480 else
2481 Binding = R;
2482
2483 return true;
2484 }
2485
2486 operator bool() { return First && Binding; }
2487 MemRegion* getRegion() { return Binding; }
2488};
2489}
2490
2491static std::pair<ExplodedNode<GRState>*,MemRegion*>
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002492GetAllocationSite(GRStateManager* StateMgr, ExplodedNode<GRState>* N,
Ted Kremenek2dabd432008-12-05 02:27:51 +00002493 SymbolRef Sym) {
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002494
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002495 // Find both first node that referred to the tracked symbol and the
2496 // memory location that value was store to.
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002497 ExplodedNode<GRState>* Last = N;
Ted Kremenek9e240492008-10-04 05:50:14 +00002498 MemRegion* FirstBinding = 0;
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002499
2500 while (N) {
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002501 const GRState* St = N->getState();
Ted Kremenek72cd17f2008-08-14 21:16:54 +00002502 RefBindings B = St->get<RefBindings>();
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002503
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002504 if (!B.lookup(Sym))
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002505 break;
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002506
2507 if (StateMgr) {
Ted Kremenek9e240492008-10-04 05:50:14 +00002508 FindUniqueBinding FB(Sym);
2509 StateMgr->iterBindings(St, FB);
2510 if (FB) FirstBinding = FB.getRegion();
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002511 }
2512
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002513 Last = N;
2514 N = N->pred_empty() ? NULL : *(N->pred_begin());
2515 }
2516
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002517 return std::make_pair(Last, FirstBinding);
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002518}
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002519
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002520PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& br,
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002521 ExplodedNode<GRState>* EndN) {
Ted Kremenek1aa44c72008-05-22 23:45:19 +00002522
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002523 GRBugReporter& BR = cast<GRBugReporter>(br);
2524
Ted Kremenek1aa44c72008-05-22 23:45:19 +00002525 // Tell the BugReporter to report cases when the tracked symbol is
2526 // assigned to different variables, etc.
Ted Kremenekc0959972008-07-02 21:24:01 +00002527 cast<GRBugReporter>(BR).addNotableSymbol(Sym);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002528
2529 if (!getBugType().isLeak())
Ted Kremeneke28565b2008-05-05 18:50:19 +00002530 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremeneke8fdc832008-07-07 16:21:19 +00002531
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002532 // We are a leak. Walk up the graph to get to the first node where the
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002533 // symbol appeared, and also get the first VarDecl that tracked object
2534 // is stored to.
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002535 ExplodedNode<GRState>* AllocNode = 0;
Ted Kremenek9e240492008-10-04 05:50:14 +00002536 MemRegion* FirstBinding = 0;
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002537
2538 llvm::tie(AllocNode, FirstBinding) =
2539 GetAllocationSite(&BR.getStateManager(), EndN, Sym);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002540
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002541 // Get the allocate site.
2542 assert (AllocNode);
2543 Stmt* FirstStmt = cast<PostStmt>(AllocNode->getLocation()).getStmt();
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002544
Ted Kremeneke28565b2008-05-05 18:50:19 +00002545 SourceManager& SMgr = BR.getContext().getSourceManager();
Chris Lattnerf7cf85b2009-01-16 07:36:28 +00002546 unsigned AllocLine =SMgr.getInstantiationLineNumber(FirstStmt->getLocStart());
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002547
Ted Kremeneke28565b2008-05-05 18:50:19 +00002548 // Get the leak site. We may have multiple ExplodedNodes (one with the
2549 // leak) that occur on the same line number; if the node with the leak
2550 // has any immediate predecessor nodes with the same line number, find
2551 // any transitive-successors that have a different statement and use that
2552 // line number instead. This avoids emiting a diagnostic like:
2553 //
2554 // // 'y' is leaked.
2555 // int x = foo(y);
2556 //
2557 // instead we want:
2558 //
2559 // int x = foo(y);
2560 // // 'y' is leaked.
2561
2562 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
2563 assert (S);
Chris Lattnerf7cf85b2009-01-16 07:36:28 +00002564 unsigned EndLine = SMgr.getInstantiationLineNumber(S->getLocStart());
Ted Kremeneke28565b2008-05-05 18:50:19 +00002565
2566 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
2567 // it occur on the same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002568 PathDiagnosticPiece::DisplayHint Hint = PathDiagnosticPiece::Above;
Ted Kremeneke28565b2008-05-05 18:50:19 +00002569
2570 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002571 ExplodedNode<GRState> *Pred = *(EndN->pred_begin());
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002572 ProgramPoint PredPos = Pred->getLocation();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002573
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002574 if (PostStmt* PredPS = dyn_cast<PostStmt>(&PredPos)) {
Ted Kremeneke28565b2008-05-05 18:50:19 +00002575
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002576 Stmt* SPred = PredPS->getStmt();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002577
2578 // Predecessor at same line?
Chris Lattnerf7cf85b2009-01-16 07:36:28 +00002579 if (SMgr.getInstantiationLineNumber(SPred->getLocStart()) != EndLine) {
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002580 Hint = PathDiagnosticPiece::Below;
2581 S = SPred;
2582 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002583 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002584
2585 // Generate the diagnostic.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002586 FullSourceLoc L( S->getLocStart(), SMgr);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002587 std::ostringstream os;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002588
Ted Kremeneke28565b2008-05-05 18:50:19 +00002589 os << "Object allocated on line " << AllocLine;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002590
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002591 if (FirstBinding)
Ted Kremenek9e240492008-10-04 05:50:14 +00002592 os << " and stored into '" << FirstBinding->getString() << '\'';
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00002593
Ted Kremenek9e240492008-10-04 05:50:14 +00002594
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00002595 // Get the retain count.
2596 const RefVal* RV = EndN->getState()->get<RefBindings>(Sym);
2597
2598 if (RV->getKind() == RefVal::ErrorLeakReturned) {
Ted Kremenek04f9d462008-12-02 01:26:07 +00002599 // FIXME: Per comments in rdar://6320065, "create" only applies to CF
2600 // ojbects. Only "copy", "alloc", "retain" and "new" transfer ownership
2601 // to the caller for NS objects.
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00002602 ObjCMethodDecl& MD = cast<ObjCMethodDecl>(BR.getGraph().getCodeDecl());
2603 os << " is returned from a method whose name ('"
Chris Lattner077bf5e2008-11-24 03:33:13 +00002604 << MD.getSelector().getAsString()
Ted Kremenek234a4c22009-01-07 00:39:56 +00002605 << "') does not contain 'copy' or otherwise starts with"
Ted Kremenek9d1d5702008-10-24 21:22:44 +00002606 " 'new' or 'alloc'. This violates the naming convention rules given"
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00002607 " in the Memory Management Guide for Cocoa (object leaked).";
2608 }
2609 else
Ted Kremenek9d1d5702008-10-24 21:22:44 +00002610 os << " is no longer referenced after this point and has a retain count of"
2611 " +"
Ted Kremenek3ad2cc82008-10-22 23:56:21 +00002612 << RV->getCount() << " (object leaked).";
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002613
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002614 return new PathDiagnosticPiece(L, os.str(), Hint);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002615}
2616
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002617void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002618
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002619 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2620 E = TF.use_after_end(); I != E; ++I) {
2621
Ted Kremenek8dd56462008-04-18 03:39:05 +00002622 CFRefReport report(*this, I->first, I->second.second);
2623 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00002624 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00002625 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002626}
2627
2628void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002629
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002630 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2631 E = TF.bad_release_end(); I != E; ++I) {
2632
Ted Kremenek8dd56462008-04-18 03:39:05 +00002633 CFRefReport report(*this, I->first, I->second.second);
2634 report.addRange(I->second.first->getSourceRange());
2635 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002636 }
2637}
Ted Kremenekfa34b332008-04-09 01:10:13 +00002638
Ted Kremenek989d5192008-04-17 23:43:50 +00002639void Leak::EmitWarnings(BugReporter& BR) {
2640
2641 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2642 E = TF.leaks_end(); I != E; ++I) {
2643
Ted Kremenek2dabd432008-12-05 02:27:51 +00002644 std::vector<std::pair<SymbolRef, bool> >& SymV = *(I->second);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002645 unsigned n = SymV.size();
2646
2647 for (unsigned i = 0; i < n; ++i) {
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002648 setIsReturn(SymV[i].second);
2649 CFRefReport report(*this, I->first, SymV[i].first);
Ted Kremenek8dd56462008-04-18 03:39:05 +00002650 BR.EmitWarning(report);
2651 }
Ted Kremenek989d5192008-04-17 23:43:50 +00002652 }
2653}
2654
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002655void Leak::GetErrorNodes(std::vector<ExplodedNode<GRState>*>& Nodes) {
Ted Kremenekcb612922008-04-18 19:23:43 +00002656 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2657 I!=E; ++I)
2658 Nodes.push_back(I->first);
2659}
2660
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002661bool Leak::isCached(BugReport& R) {
2662
2663 // Most bug reports are cached at the location where they occured.
2664 // With leaks, we want to unique them by the location where they were
Ted Kremenekf9790ae2008-10-24 20:32:50 +00002665 // allocated, and only report a single path.
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002666
Ted Kremenek2dabd432008-12-05 02:27:51 +00002667 SymbolRef Sym = static_cast<CFRefReport&>(R).getSymbol();
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002668
Ted Kremenek4adc81e2008-08-13 04:27:00 +00002669 ExplodedNode<GRState>* AllocNode =
Ted Kremenek2bc39c62008-08-29 00:47:32 +00002670 GetAllocationSite(0, R.getEndNode(), Sym).first;
Ted Kremenek6ed9afc2008-05-16 18:33:44 +00002671
2672 if (!AllocNode)
2673 return false;
2674
2675 return BugTypeCacheLocation::isCached(AllocNode->getLocation());
2676}
2677
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002678//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00002679// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002680//===----------------------------------------------------------------------===//
2681
Ted Kremenek072192b2008-04-30 23:47:44 +00002682GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
2683 const LangOptions& lopts) {
Ted Kremenek78d46242008-07-22 16:21:24 +00002684 return new CFRefCount(Ctx, GCEnabled, lopts);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00002685}