blob: fd47f03d3e12da938fa7fb3b16d36ddc2ea3862a [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek072192b2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenekc9fa2f72008-05-01 23:13:35 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000020#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000021#include "clang/Analysis/PathDiagnostic.h"
22#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek900a2d72008-05-07 18:36:45 +000026#include "llvm/ADT/StringExtras.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000027#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000028#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000029#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000030
31using namespace clang;
Ted Kremenek900a2d72008-05-07 18:36:45 +000032using llvm::CStrInCStrNoCase;
Ted Kremenek2fff37e2008-03-06 00:08:09 +000033
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000034//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-04-17 18:12:53 +000035// Utility functions.
36//===----------------------------------------------------------------------===//
37
Ted Kremenekb83e02e2008-05-01 18:31:44 +000038static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenek4fd88972008-04-17 18:12:53 +000039 IdentifierInfo* II = &Ctx.Idents.get(name);
40 return Ctx.Selectors.getSelector(0, &II);
41}
42
Ted Kremenek9c32d082008-05-06 00:30:21 +000043static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
44 IdentifierInfo* II = &Ctx.Idents.get(name);
45 return Ctx.Selectors.getSelector(1, &II);
46}
47
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +000048static bool isCFRefType(QualType T) {
49
50 if (!T->isPointerType())
51 return false;
52
53 // Check the typedef for the name "CF" and the substring "Ref".
54
55 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
56
57 if (!TD)
58 return false;
59
60 const char* TDName = TD->getDecl()->getIdentifier()->getName();
61 assert (TDName);
62
63 if (TDName[0] != 'C' || TDName[1] != 'F')
64 return false;
65
66 if (strstr(TDName, "Ref") == 0)
67 return false;
68
69 return true;
70}
71
72static bool isNSType(QualType T) {
73
74 if (!T->isPointerType())
75 return false;
76
77 ObjCInterfaceType* OT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
78
79 if (!OT)
80 return false;
81
82 const char* ClsName = OT->getDecl()->getIdentifier()->getName();
83 assert (ClsName);
84
85 if (ClsName[0] != 'N' || ClsName[1] != 'S')
86 return false;
87
88 return true;
89}
90
Ted Kremenek4fd88972008-04-17 18:12:53 +000091//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000092// Symbolic Evaluation of Reference Counting Logic
93//===----------------------------------------------------------------------===//
94
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000095namespace {
Ted Kremenek14993892008-05-06 02:41:27 +000096 enum ArgEffect { IncRef, DecRef, DoNothing, StopTracking };
Ted Kremenek891d5cc2008-04-24 17:22:33 +000097 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000098}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000099
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000100namespace llvm {
101 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000102 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000103 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
104 ID.AddInteger(I->first);
105 ID.AddInteger((unsigned) I->second);
106 }
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000107 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000108 };
109} // end llvm namespace
110
111namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000112
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000113class RetEffect {
114public:
Ted Kremenek940b1d82008-04-10 23:44:06 +0000115 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000116 NotOwnedSymbol = 0x3, ReceiverAlias=0x4 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000117
118private:
119 unsigned Data;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000120 RetEffect(Kind k, unsigned D) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000121
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000122public:
123
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000124 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000125
126 unsigned getValue() const {
127 assert(getKind() == Alias);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000128 return Data >> 3;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000129 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000130
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000131 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000132
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000133 static RetEffect MakeReceiverAlias() { return RetEffect(ReceiverAlias, 0); }
134
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000135 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000136
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000137 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
138
Ted Kremenek940b1d82008-04-10 23:44:06 +0000139 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
140
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000141 operator Kind() const { return getKind(); }
142
143 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
144};
145
146
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000147class RetainSummary : public llvm::FoldingSetNode {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000148 /// Args - an ordered vector of (index, ArgEffect) pairs, where index
149 /// specifies the argument (starting from 0). This can be sparsely
150 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000151 ArgEffects* Args;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000152
153 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
154 /// do not have an entry in Args.
155 ArgEffect DefaultArgEffect;
156
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000157 ArgEffect Receiver;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000158 RetEffect Ret;
159public:
160
Ted Kremenek1bffd742008-05-06 15:44:25 +0000161 RetainSummary(ArgEffects* A, RetEffect R, ArgEffect defaultEff,
162 ArgEffect ReceiverEff)
163 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000164
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000165 ArgEffect getArg(unsigned idx) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000166
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000167 if (!Args)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000168 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000169
170 // If Args is present, it is likely to contain only 1 element.
171 // Just do a linear search. Do it from the back because functions with
172 // large numbers of arguments will be tail heavy with respect to which
173 // argument they actually modify with respect to the reference count.
174
175 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
176 I!=E; ++I) {
177
178 if (idx > I->first)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000179 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000180
181 if (idx == I->first)
182 return I->second;
183 }
184
Ted Kremenek1bffd742008-05-06 15:44:25 +0000185 return DefaultArgEffect;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000186 }
187
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000188 RetEffect getRetEffect() const {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000189 return Ret;
190 }
191
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000192 ArgEffect getReceiverEffect() const {
193 return Receiver;
194 }
195
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000196 typedef ArgEffects::const_iterator arg_iterator;
197
198 arg_iterator begin_args() const { return Args->begin(); }
199 arg_iterator end_args() const { return Args->end(); }
200
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000201 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000202 RetEffect RetEff, ArgEffect DefaultEff,
203 ArgEffect ReceiverEff) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000204 ID.AddPointer(A);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000205 ID.Add(RetEff);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000206 ID.AddInteger((unsigned) DefaultEff);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000207 ID.AddInteger((unsigned) ReceiverEff);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000208 }
209
210 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000211 Profile(ID, Args, Ret, DefaultArgEffect, Receiver);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000212 }
213};
214
215
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000216class RetainSummaryManager {
217
218 //==-----------------------------------------------------------------==//
219 // Typedefs.
220 //==-----------------------------------------------------------------==//
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000221
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000222 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
223 ArgEffectsSetTy;
224
225 typedef llvm::FoldingSet<RetainSummary>
226 SummarySetTy;
227
228 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
229 FuncSummariesTy;
230
231 typedef llvm::DenseMap<Selector, RetainSummary*>
Ted Kremenek9c32d082008-05-06 00:30:21 +0000232 ObjCMethSummariesTy;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000233
234 //==-----------------------------------------------------------------==//
235 // Data.
236 //==-----------------------------------------------------------------==//
237
238 // Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek377e2302008-04-29 05:33:51 +0000239 ASTContext& Ctx;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000240
241 // GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek377e2302008-04-29 05:33:51 +0000242 const bool GCEnabled;
243
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000244 // SummarySet - A FoldingSet of uniqued summaries.
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000245 SummarySetTy SummarySet;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000246
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000247 // FuncSummaries - A map from FunctionDecls to summaries.
248 FuncSummariesTy FuncSummaries;
249
Ted Kremenek9c32d082008-05-06 00:30:21 +0000250 // ObjCInstMethSummaries - A map from selectors (for instance methods)
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000251 // to summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000252 ObjCMethSummariesTy ObjCInstMethSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000253
Ted Kremenek9c32d082008-05-06 00:30:21 +0000254 // ObjCMethSummaries - A map from selectors to summaries.
255 ObjCMethSummariesTy ObjCMethSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000256
257 // ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
258 ArgEffectsSetTy ArgEffectsSet;
259
260 // BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
261 // and all other data used by the checker.
262 llvm::BumpPtrAllocator BPAlloc;
263
264 // ScratchArgs - A holding buffer for construct ArgEffects.
265 ArgEffects ScratchArgs;
266
Ted Kremenek432af592008-05-06 18:11:36 +0000267 RetainSummary* StopSummary;
268
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000269 //==-----------------------------------------------------------------==//
270 // Methods.
271 //==-----------------------------------------------------------------==//
272
273 // getArgEffects - Returns a persistent ArgEffects object based on the
274 // data in ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000275 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000276
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000277 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000278 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek377e2302008-04-29 05:33:51 +0000279
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000280 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
281 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000282
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000283 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
284 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000285
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000286 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000287 ArgEffect ReceiverEff = DoNothing,
288 ArgEffect DefaultEff = DoNothing);
289
Ted Kremenek9c32d082008-05-06 00:30:21 +0000290
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000291 RetainSummary* getPersistentSummary(RetEffect RE,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000292 ArgEffect ReceiverEff = DoNothing,
293 ArgEffect DefaultEff = DoNothing) {
294 return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000295 }
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000296
Ted Kremenek432af592008-05-06 18:11:36 +0000297
298
Ted Kremenek1bffd742008-05-06 15:44:25 +0000299 RetainSummary* getPersistentStopSummary() {
Ted Kremenek432af592008-05-06 18:11:36 +0000300 if (StopSummary)
301 return StopSummary;
302
303 StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
304 StopTracking, StopTracking);
305
306 return StopSummary;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000307 }
Ted Kremenekb3095252008-05-06 04:20:12 +0000308
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000309 RetainSummary* getInitMethodSummary(Selector S);
310
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000311 void InitializeInstMethSummaries();
312 void InitializeMethSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000313
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000314public:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000315
316 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek432af592008-05-06 18:11:36 +0000317 : Ctx(ctx), GCEnabled(gcenabled), StopSummary(0) {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000318
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000319 InitializeInstMethSummaries();
320 InitializeMethSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000321 }
Ted Kremenek377e2302008-04-29 05:33:51 +0000322
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000323 ~RetainSummaryManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000324
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000325 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
326
Ted Kremenek1bffd742008-05-06 15:44:25 +0000327 RetainSummary* getMethodSummary(ObjCMessageExpr* ME);
Ted Kremenekb3095252008-05-06 04:20:12 +0000328 RetainSummary* getInstanceMethodSummary(IdentifierInfo* ClsName, Selector S);
329
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000330 bool isGCEnabled() const { return GCEnabled; }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000331};
332
333} // end anonymous namespace
334
335//===----------------------------------------------------------------------===//
336// Implementation of checker data structures.
337//===----------------------------------------------------------------------===//
338
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000339RetainSummaryManager::~RetainSummaryManager() {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000340
341 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
342 // mitigating the need to do explicit cleanup of the
343 // Argument-Effect summaries.
344
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000345 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
346 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000347 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000348}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000349
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000350ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000351
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000352 if (ScratchArgs.empty())
353 return NULL;
354
355 // Compute a profile for a non-empty ScratchArgs.
356
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000357 llvm::FoldingSetNodeID profile;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000358
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000359 profile.Add(ScratchArgs);
360 void* InsertPos;
361
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000362 // Look up the uniqued copy, or create a new one.
363
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000364 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000365 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000366
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000367 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000368 ScratchArgs.clear();
369 return &E->getValue();
370 }
371
372 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
373 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
374
375 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000376 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000377
378 ScratchArgs.clear();
379 return &E->getValue();
380}
381
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000382RetainSummary*
383RetainSummaryManager::getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000384 ArgEffect ReceiverEff,
385 ArgEffect DefaultEff) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000386
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000387 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000388 llvm::FoldingSetNodeID profile;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000389 RetainSummary::Profile(profile, AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000390
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000391 // Look up the uniqued summary, or create one if it doesn't exist.
392 void* InsertPos;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000393 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000394
395 if (Summ)
396 return Summ;
397
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000398 // Create the summary and return it.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000399 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
Ted Kremenek1bffd742008-05-06 15:44:25 +0000400 new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000401 SummarySet.InsertNode(Summ, InsertPos);
402
403 return Summ;
404}
405
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000406//===----------------------------------------------------------------------===//
407// Summary creation for functions (largely uses of Core Foundation).
408//===----------------------------------------------------------------------===//
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000409
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000410RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000411 ASTContext& Ctx) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000412
413 SourceLocation Loc = FD->getLocation();
414
415 if (!Loc.isFileID())
416 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000417
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000418 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000419 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000420
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000421 if (I != FuncSummaries.end())
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000422 return I->second;
423
424 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000425 const char* FName = FD->getIdentifier()->getName();
426
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000427 RetainSummary *S = 0;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000428
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000429 FunctionType* FT = dyn_cast<FunctionType>(FD->getType());
430
431 if (FT && isCFRefType(FT->getResultType()))
432 S = getCFSummary(FD, FName);
433 else if (FName[0] == 'C' && FName[1] == 'F')
434 S = getCFSummary(FD, FName);
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000435 else if (FName[0] == 'N' && FName[1] == 'S')
436 S = getNSSummary(FD, FName);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000437
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000438 FuncSummaries[FD] = S;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000439 return S;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000440}
441
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000442RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000443 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000444 FName += 2;
445
446 if (strcmp(FName, "MakeCollectable") == 0)
447 return getUnarySummary(FD, cfmakecollectable);
448
449 return 0;
450}
451
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000452RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000453 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000454
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000455 if (FName[0] == 'C' && FName[1] == 'F')
456 FName += 2;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000457
458 if (strcmp(FName, "Retain") == 0)
459 return getUnarySummary(FD, cfretain);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000460
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000461 if (strcmp(FName, "Release") == 0)
462 return getUnarySummary(FD, cfrelease);
463
464 if (strcmp(FName, "MakeCollectable") == 0)
465 return getUnarySummary(FD, cfmakecollectable);
466
467 if (strstr(FName, "Create") || strstr(FName, "Copy"))
468 return getCFSummaryCreateRule(FD);
469
470 if (strstr(FName, "Get"))
471 return getCFSummaryGetRule(FD);
472
473 return 0;
474}
475
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000476RetainSummary*
477RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000478
479 FunctionTypeProto* FT =
480 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
481
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000482 if (FT) {
483
484 if (FT->getNumArgs() != 1)
485 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000486
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000487 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
488
489 if (!ArgT)
490 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000491
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000492 if (!ArgT->isPointerType())
493 return NULL;
494 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000495
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000496 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000497
Ted Kremenek377e2302008-04-29 05:33:51 +0000498 switch (func) {
499 case cfretain: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000500 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek9c32d082008-05-06 00:30:21 +0000501 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek377e2302008-04-29 05:33:51 +0000502 }
503
504 case cfrelease: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000505 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek9c32d082008-05-06 00:30:21 +0000506 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek377e2302008-04-29 05:33:51 +0000507 }
508
509 case cfmakecollectable: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000510 if (GCEnabled)
511 ScratchArgs.push_back(std::make_pair(0, DecRef));
512
Ted Kremenek9c32d082008-05-06 00:30:21 +0000513 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek377e2302008-04-29 05:33:51 +0000514 }
515
516 default:
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000517 assert (false && "Not a supported unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000518 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000519}
520
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000521RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000522
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000523 FunctionType* FT =
524 dyn_cast<FunctionType>(FD->getType().getTypePtr());
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000525
526 if (FT && !isCFRefType(FT->getResultType()))
527 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000528
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000529 // FIXME: Add special-cases for functions that retain/release. For now
530 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000531
532 assert (ScratchArgs.empty());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000533 return getPersistentSummary(RetEffect::MakeOwned());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000534}
535
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000536RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000537
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000538 FunctionType* FT =
539 dyn_cast<FunctionType>(FD->getType().getTypePtr());
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000540
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000541 if (FT) {
542 QualType RetTy = FT->getResultType();
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000543
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000544 // FIXME: For now we assume that all pointer types returned are referenced
545 // counted. Since this is the "Get" rule, we assume non-ownership, which
546 // works fine for things that are not reference counted. We do this because
547 // some generic data structures return "void*". We need something better
548 // in the future.
549
550 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
551 return 0;
552 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000553
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000554 // FIXME: Add special-cases for functions that retain/release. For now
555 // just handle the default case.
556
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000557 assert (ScratchArgs.empty());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000558 return getPersistentSummary(RetEffect::MakeNotOwned());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000559}
560
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000561//===----------------------------------------------------------------------===//
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000562// Summary creation for Selectors.
563//===----------------------------------------------------------------------===//
564
Ted Kremenek1bffd742008-05-06 15:44:25 +0000565RetainSummary*
566RetainSummaryManager::getInitMethodSummary(Selector S) {
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000567 assert(ScratchArgs.empty());
568
569 RetainSummary* Summ =
Ted Kremenek9c32d082008-05-06 00:30:21 +0000570 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000571
Ted Kremenek9c32d082008-05-06 00:30:21 +0000572 ObjCMethSummaries[S] = Summ;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000573 return Summ;
574}
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000575
Ted Kremenek1bffd742008-05-06 15:44:25 +0000576RetainSummary*
577RetainSummaryManager::getMethodSummary(ObjCMessageExpr* ME) {
578
579 Selector S = ME->getSelector();
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000580
581 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000582 ObjCMethSummariesTy::iterator I = ObjCMethSummaries.find(S);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000583
Ted Kremenek9c32d082008-05-06 00:30:21 +0000584 if (I != ObjCMethSummaries.end())
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000585 return I->second;
Ted Kremenekc8395602008-05-06 21:26:51 +0000586
587#if 0
Ted Kremenek1bffd742008-05-06 15:44:25 +0000588 // Only generate real summaries for methods involving
589 // NSxxxx objects.
Ted Kremenekc8395602008-05-06 21:26:51 +0000590
Ted Kremenek1bffd742008-05-06 15:44:25 +0000591 if (!isNSType(ME->getReceiver()->getType())) {
592 RetainSummary* Summ = getPersistentStopSummary();
593 ObjCMethSummaries[S] = Summ;
594 return Summ;
595 }
Ted Kremenekc8395602008-05-06 21:26:51 +0000596#endif
Ted Kremenek432af592008-05-06 18:11:36 +0000597
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000598 if (!ME->getType()->isPointerType())
599 return 0;
600
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000601 // "initXXX": pass-through for receiver.
602
603 const char* s = S.getIdentifierInfoForSlot(0)->getName();
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000604 assert (ScratchArgs.empty());
Ted Kremenekaee9e572008-05-06 06:09:09 +0000605
Ted Kremenek84548b82008-05-06 06:17:42 +0000606 if (strncmp(s, "init", 4) == 0)
Ted Kremenek432af592008-05-06 18:11:36 +0000607 return getInitMethodSummary(S);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000608
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000609 // "copyXXX", "createXXX", "newXXX": allocators.
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000610
Ted Kremenek84060db2008-05-07 04:25:59 +0000611 if (!isNSType(ME->getReceiver()->getType()))
612 return 0;
613
Ted Kremenek0fcbf8e2008-05-07 20:06:41 +0000614 if (CStrInCStrNoCase(s, "create") || CStrInCStrNoCase(s, "copy") ||
615 CStrInCStrNoCase(s, "new")) {
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000616
617 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
618 : RetEffect::MakeOwned();
619
620 RetainSummary* Summ = getPersistentSummary(E);
621 ObjCMethSummaries[S] = Summ;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000622 return Summ;
623 }
Ted Kremenek1bffd742008-05-06 15:44:25 +0000624
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000625 return 0;
626}
627
Ted Kremenekc8395602008-05-06 21:26:51 +0000628RetainSummary*
629RetainSummaryManager::getInstanceMethodSummary(IdentifierInfo* ClsName,
630 Selector S) {
631
632 // Look up a summary in our cache of Selectors -> Summaries.
633 ObjCMethSummariesTy::iterator I = ObjCInstMethSummaries.find(S);
634
635 if (I != ObjCInstMethSummaries.end())
636 return I->second;
637
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000638 return 0;
639
640#if 0
641 return 0;
642
Ted Kremenekc8395602008-05-06 21:26:51 +0000643 // Don't track anything if using GC.
644 if (isGCEnabled())
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000645 return 0;
646
Ted Kremenekc8395602008-05-06 21:26:51 +0000647 // Inspect the class name and selecrtor to determine if this method
648 // creates new objects.
649 const char* cls = ClsName->getName();
650
651 if (cls[0] == 'N' && cls[1] == 'S') // Ignore preceding "NS" (if present).
652 cls += 2;
653
654 // Heuristic: XXXwithYYY, where XXX is the class name with the "NS"
655 // stripped off is usually an allocation.
656
657 const char* s = S.getIdentifierInfoForSlot(0)->getName();
658
659 if (cls[0] == '\0' || s[0] == '\0' || tolower(cls[0]) != s[0])
660 return 0;
661
662 // Now look at the rest of the characters.
663 ++cls; ++s;
664 unsigned len = strlen(cls);
665
666 // If the prefix doesn't match, don't generate a special summary.
667 if (strncmp(cls, s, len) != 0)
668 return 0;
669
670 // Look at the text after the prefix.
671 s += len;
672
673 if (!(s[0] == '\0' || strncmp(s, "With", 4) == 0))
674 return 0;
675
676 // Generate and return the summary.
677 assert (ScratchArgs.empty());
678
679 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeOwned());
680 ObjCInstMethSummaries[S] = Summ;
681 return Summ;
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000682#endif
Ted Kremenekc8395602008-05-06 21:26:51 +0000683}
684
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000685void RetainSummaryManager::InitializeInstMethSummaries() {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000686
687 assert (ScratchArgs.empty());
688
689 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
690 RetainSummary* Summ = getPersistentSummary(E);
691
692 // Create the "alloc" selector.
693 ObjCInstMethSummaries[ GetNullarySelector("alloc", Ctx) ] = Summ;
694
695 // Create the "new" selector.
696 ObjCInstMethSummaries[ GetNullarySelector("new", Ctx) ] = Summ;
697
698 // Create the "allocWithZone:" selector.
Ted Kremenek05a7b0e2008-05-07 05:34:45 +0000699 ObjCInstMethSummaries[ GetUnarySelector("allocWithZone", Ctx) ] = Summ;
Ted Kremenek9c32d082008-05-06 00:30:21 +0000700}
701
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000702void RetainSummaryManager::InitializeMethSummaries() {
703
704 assert (ScratchArgs.empty());
705
Ted Kremenekc8395602008-05-06 21:26:51 +0000706 // Create the "init" selector. It just acts as a pass-through for the
707 // receiver.
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000708 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeReceiverAlias());
709 ObjCMethSummaries[ GetNullarySelector("init", Ctx) ] = Summ;
Ted Kremenekc8395602008-05-06 21:26:51 +0000710
711 // The next methods are allocators.
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000712 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
Ted Kremenekc8395602008-05-06 21:26:51 +0000713 Summ = getPersistentSummary(E);
714
715 // Create the "copy" selector.
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000716 ObjCMethSummaries[ GetNullarySelector("copy", Ctx) ] = Summ;
717
718 // Create the "mutableCopy" selector.
719 ObjCMethSummaries[ GetNullarySelector("mutableCopy", Ctx) ] = Summ;
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000720
721 // Create the "retain" selector.
722 E = RetEffect::MakeReceiverAlias();
723 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
724 ObjCMethSummaries[ GetNullarySelector("retain", Ctx) ] = Summ;
725
726 // Create the "release" selector.
727 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
728 ObjCMethSummaries[ GetNullarySelector("release", Ctx) ] = Summ;
Ted Kremenek299e8152008-05-07 21:17:39 +0000729
730 // Create the "drain" selector.
731 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
732 ObjCMethSummaries[ GetNullarySelector("drain", Ctx) ] = Summ;
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000733
734 // Create the "autorelease" selector.
Ted Kremenek14993892008-05-06 02:41:27 +0000735 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : StopTracking);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000736 ObjCMethSummaries[ GetNullarySelector("autorelease", Ctx) ] = Summ;
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000737}
738
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000739//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000740// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000741//===----------------------------------------------------------------------===//
742
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000743namespace {
744
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000745class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000746public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000747
Ted Kremenek4fd88972008-04-17 18:12:53 +0000748 enum Kind {
749 Owned = 0, // Owning reference.
750 NotOwned, // Reference is not owned by still valid (not freed).
751 Released, // Object has been released.
752 ReturnedOwned, // Returned object passes ownership to caller.
753 ReturnedNotOwned, // Return object does not pass ownership to caller.
754 ErrorUseAfterRelease, // Object used after released.
755 ErrorReleaseNotOwned, // Release of an object that was not owned.
756 ErrorLeak // A memory leak due to excessive reference counts.
757 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000758
Ted Kremenek4fd88972008-04-17 18:12:53 +0000759private:
760
761 Kind kind;
762 unsigned Cnt;
763
764 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
765
766 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000767
768public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000769
Ted Kremenek4fd88972008-04-17 18:12:53 +0000770 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000771
Ted Kremenek4fd88972008-04-17 18:12:53 +0000772 unsigned getCount() const { return Cnt; }
773
774 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000775
Ted Kremenek73c750b2008-03-11 18:14:09 +0000776 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
777
Ted Kremenekdb863712008-04-16 22:32:20 +0000778 static bool isLeak(Kind k) { return k == ErrorLeak; }
779
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000780 bool isOwned() const {
781 return getKind() == Owned;
782 }
783
Ted Kremenekdb863712008-04-16 22:32:20 +0000784 bool isNotOwned() const {
785 return getKind() == NotOwned;
786 }
787
Ted Kremenek4fd88972008-04-17 18:12:53 +0000788 bool isReturnedOwned() const {
789 return getKind() == ReturnedOwned;
790 }
791
792 bool isReturnedNotOwned() const {
793 return getKind() == ReturnedNotOwned;
794 }
795
796 bool isNonLeakError() const {
797 Kind k = getKind();
798 return isError(k) && !isLeak(k);
799 }
800
801 // State creation: normal state.
802
Ted Kremenek61b9f872008-04-10 23:09:18 +0000803 static RefVal makeOwned(unsigned Count = 0) {
804 return RefVal(Owned, Count);
805 }
806
807 static RefVal makeNotOwned(unsigned Count = 0) {
808 return RefVal(NotOwned, Count);
809 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000810
811 static RefVal makeReturnedOwned(unsigned Count) {
812 return RefVal(ReturnedOwned, Count);
813 }
814
815 static RefVal makeReturnedNotOwned() {
816 return RefVal(ReturnedNotOwned);
817 }
818
819 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000820
Ted Kremenekce48e002008-05-05 17:53:17 +0000821 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000822 static RefVal makeReleased() { return RefVal(Released); }
823 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
824 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000825
826 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000827
Ted Kremenek4fd88972008-04-17 18:12:53 +0000828 bool operator==(const RefVal& X) const {
829 return kind == X.kind && Cnt == X.Cnt;
830 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000831
Ted Kremenek4fd88972008-04-17 18:12:53 +0000832 void Profile(llvm::FoldingSetNodeID& ID) const {
833 ID.AddInteger((unsigned) kind);
834 ID.AddInteger(Cnt);
835 }
836
Ted Kremenekf3948042008-03-11 19:44:10 +0000837 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000838};
Ted Kremenekf3948042008-03-11 19:44:10 +0000839
840void RefVal::print(std::ostream& Out) const {
841 switch (getKind()) {
842 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000843 case Owned: {
844 Out << "Owned";
845 unsigned cnt = getCount();
846 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000847 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000848 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000849
Ted Kremenek61b9f872008-04-10 23:09:18 +0000850 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000851 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000852 unsigned cnt = getCount();
853 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000854 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000855 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000856
Ted Kremenek4fd88972008-04-17 18:12:53 +0000857 case ReturnedOwned: {
858 Out << "ReturnedOwned";
859 unsigned cnt = getCount();
860 if (cnt) Out << " (+ " << cnt << ")";
861 break;
862 }
863
864 case ReturnedNotOwned: {
865 Out << "ReturnedNotOwned";
866 unsigned cnt = getCount();
867 if (cnt) Out << " (+ " << cnt << ")";
868 break;
869 }
870
Ted Kremenekf3948042008-03-11 19:44:10 +0000871 case Released:
872 Out << "Released";
873 break;
874
Ted Kremenekdb863712008-04-16 22:32:20 +0000875 case ErrorLeak:
876 Out << "Leaked";
877 break;
878
Ted Kremenekf3948042008-03-11 19:44:10 +0000879 case ErrorUseAfterRelease:
880 Out << "Use-After-Release [ERROR]";
881 break;
882
883 case ErrorReleaseNotOwned:
884 Out << "Release of Not-Owned [ERROR]";
885 break;
886 }
887}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000888
Ted Kremenekce48e002008-05-05 17:53:17 +0000889static inline unsigned GetCount(RefVal V) {
890 switch (V.getKind()) {
891 default:
892 return V.getCount();
893
894 case RefVal::Owned:
895 return V.getCount()+1;
896 }
897}
898
Ted Kremenek13922612008-04-16 20:40:59 +0000899//===----------------------------------------------------------------------===//
900// Transfer functions.
901//===----------------------------------------------------------------------===//
902
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000903class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000904public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000905 // Type definitions.
906
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000907 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000908 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000909
Ted Kremenek8dd56462008-04-18 03:39:05 +0000910 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
911 ReleasesNotOwnedTy;
912
913 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
914
915 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000916 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000917
Ted Kremenekf3948042008-03-11 19:44:10 +0000918 class BindingsPrinter : public ValueState::CheckerStatePrinter {
919 public:
920 virtual void PrintCheckerState(std::ostream& Out, void* State,
921 const char* nl, const char* sep);
922 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000923
924private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000925 // Instance variables.
926
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000927 RetainSummaryManager Summaries;
928 const bool EmitStandardWarnings;
929 const LangOptions& LOpts;
930 RefBFactoryTy RefBFactory;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000931
Ted Kremenek73c750b2008-03-11 18:14:09 +0000932 UseAfterReleasesTy UseAfterReleases;
933 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000934 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000935
Ted Kremenekf3948042008-03-11 19:44:10 +0000936 BindingsPrinter Printer;
937
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000938 Selector RetainSelector;
939 Selector ReleaseSelector;
Ted Kremenek5934cee2008-05-01 02:18:37 +0000940 Selector AutoreleaseSelector;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000941
Ted Kremenek8dd56462008-04-18 03:39:05 +0000942public:
943
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000944 static RefBindings GetRefBindings(ValueState& StImpl) {
945 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
946 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000947
Ted Kremenek8dd56462008-04-18 03:39:05 +0000948private:
949
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000950 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
951 StImpl.CheckerState = B.getRoot();
952 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000953
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000954 RefBindings Remove(RefBindings B, SymbolID sym) {
955 return RefBFactory.Remove(B, sym);
956 }
957
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000958 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000959 RefVal::Kind& hasErr);
960
Ted Kremenekdb863712008-04-16 22:32:20 +0000961 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
962 GRStmtNodeBuilder<ValueState>& Builder,
963 Expr* NodeExpr, Expr* ErrorExpr,
964 ExplodedNode<ValueState>* Pred,
965 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000966 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000967
968 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
969 SymbolID sid, RefVal V, bool& hasLeak);
970
971 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
972 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000973
974public:
Ted Kremenek13922612008-04-16 20:40:59 +0000975
Ted Kremenek9f741612008-05-02 18:01:49 +0000976 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
977 const LangOptions& lopts)
Ted Kremenek377e2302008-04-29 05:33:51 +0000978 : Summaries(Ctx, gcenabled),
Ted Kremenek9f741612008-05-02 18:01:49 +0000979 EmitStandardWarnings(StandardWarnings),
Ted Kremenek072192b2008-04-30 23:47:44 +0000980 LOpts(lopts),
Ted Kremenekb83e02e2008-05-01 18:31:44 +0000981 RetainSelector(GetNullarySelector("retain", Ctx)),
982 ReleaseSelector(GetNullarySelector("release", Ctx)),
983 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000984
Ted Kremenek8dd56462008-04-18 03:39:05 +0000985 virtual ~CFRefCount() {
986 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
987 delete I->second;
988 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000989
990 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000991
992 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
993 return &Printer;
994 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000995
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000996 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenek072192b2008-04-30 23:47:44 +0000997 const LangOptions& getLangOptions() const { return LOpts; }
998
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000999 // Calls.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001000
1001 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1002 GRExprEngine& Eng,
1003 GRStmtNodeBuilder<ValueState>& Builder,
1004 Expr* Ex,
1005 Expr* Receiver,
1006 RetainSummary* Summ,
1007 Expr** arg_beg, Expr** arg_end,
1008 ExplodedNode<ValueState>* Pred);
1009
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001010 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +00001011 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001012 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +00001013 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001014 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001015
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001016
Ted Kremenek85348202008-04-15 23:44:31 +00001017 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1018 GRExprEngine& Engine,
1019 GRStmtNodeBuilder<ValueState>& Builder,
1020 ObjCMessageExpr* ME,
1021 ExplodedNode<ValueState>* Pred);
1022
1023 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1024 GRExprEngine& Engine,
1025 GRStmtNodeBuilder<ValueState>& Builder,
1026 ObjCMessageExpr* ME,
1027 ExplodedNode<ValueState>* Pred);
1028
Ted Kremenek13922612008-04-16 20:40:59 +00001029 // Stores.
1030
1031 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
1032 GRExprEngine& Engine,
1033 GRStmtNodeBuilder<ValueState>& Builder,
1034 Expr* E, ExplodedNode<ValueState>* Pred,
1035 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001036 // End-of-path.
1037
1038 virtual void EvalEndPath(GRExprEngine& Engine,
1039 GREndPathNodeBuilder<ValueState>& Builder);
1040
Ted Kremenek652adc62008-04-24 23:57:27 +00001041 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1042 GRExprEngine& Engine,
1043 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001044 ExplodedNode<ValueState>* Pred,
1045 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001046 ValueState* St,
1047 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001048 // Return statements.
1049
1050 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1051 GRExprEngine& Engine,
1052 GRStmtNodeBuilder<ValueState>& Builder,
1053 ReturnStmt* S,
1054 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +00001055
1056 // Assumptions.
1057
1058 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
1059 RVal Cond, bool Assumption, bool& isFeasible);
1060
Ted Kremenekfa34b332008-04-09 01:10:13 +00001061 // Error iterators.
1062
1063 typedef UseAfterReleasesTy::iterator use_after_iterator;
1064 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +00001065 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +00001066
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001067 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
1068 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +00001069
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001070 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
1071 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +00001072
1073 leaks_iterator leaks_begin() { return Leaks.begin(); }
1074 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001075};
1076
1077} // end anonymous namespace
1078
Ted Kremenek8dd56462008-04-18 03:39:05 +00001079
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001080
1081
Ted Kremenekf3948042008-03-11 19:44:10 +00001082void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
1083 void* State, const char* nl,
1084 const char* sep) {
1085 RefBindings B((RefBindings::TreeTy*) State);
1086
1087 if (State)
1088 Out << sep << nl;
1089
1090 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1091 Out << (*I).first << " : ";
1092 (*I).second.print(Out);
1093 Out << nl;
1094 }
1095}
1096
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001097static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001098 return Summ ? Summ->getArg(idx) : DoNothing;
1099}
1100
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001101static inline RetEffect GetRetEffect(RetainSummary* Summ) {
1102 return Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001103}
1104
Ted Kremenek14993892008-05-06 02:41:27 +00001105static inline ArgEffect GetReceiverE(RetainSummary* Summ) {
1106 return Summ ? Summ->getReceiverEffect() : DoNothing;
1107}
1108
Ted Kremenekdb863712008-04-16 22:32:20 +00001109void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
1110 GRStmtNodeBuilder<ValueState>& Builder,
1111 Expr* NodeExpr, Expr* ErrorExpr,
1112 ExplodedNode<ValueState>* Pred,
1113 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001114 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001115 Builder.BuildSinks = true;
1116 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
1117
1118 if (!N) return;
1119
1120 switch (hasErr) {
1121 default: assert(false);
1122 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001123 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001124 break;
1125
1126 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001127 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001128 break;
1129 }
1130}
1131
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001132void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1133 GRExprEngine& Eng,
1134 GRStmtNodeBuilder<ValueState>& Builder,
1135 Expr* Ex,
1136 Expr* Receiver,
1137 RetainSummary* Summ,
1138 Expr** arg_beg, Expr** arg_end,
1139 ExplodedNode<ValueState>* Pred) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001140
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001141
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001142 // Get the state.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001143 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001144 ValueState* St = Builder.GetState(Pred);
1145
Ted Kremenek14993892008-05-06 02:41:27 +00001146
1147 // Evaluate the effect of the arguments.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001148
1149 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001150 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001151 unsigned idx = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001152 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001153 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001154
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001155 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001156
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001157 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001158
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001159 if (isa<lval::SymbolVal>(V)) {
1160 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001161 RefBindings B = GetRefBindings(StVals);
1162
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001163 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001164 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001165 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001166
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001167 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001168 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001169 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001170 break;
1171 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001172 }
Ted Kremenekb8873552008-04-11 20:51:02 +00001173 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001174 else if (isa<LVal>(V)) {
1175 // Nuke all arguments passed by reference.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001176 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +00001177 }
Ted Kremeneka5488462008-04-22 21:39:21 +00001178 else if (isa<nonlval::LValAsInteger>(V))
1179 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001180 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001181
Ted Kremenek14993892008-05-06 02:41:27 +00001182 // Evaluate the effect on the message receiver.
1183
1184 if (!ErrorExpr && Receiver) {
1185 RVal V = StateMgr.GetRVal(St, Receiver);
1186
1187 if (isa<lval::SymbolVal>(V)) {
1188 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1189 RefBindings B = GetRefBindings(StVals);
1190
1191 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
1192 B = Update(B, Sym, T->getValue().second, GetReceiverE(Summ), hasErr);
1193 SetRefBindings(StVals, B);
1194
1195 if (hasErr) {
1196 ErrorExpr = Receiver;
1197 ErrorSym = T->getValue().first;
1198 }
1199 }
1200 }
1201 }
1202
1203 // Get the persistent state.
1204
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001205 St = StateMgr.getPersistentState(StVals);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001206
Ted Kremenek14993892008-05-06 02:41:27 +00001207 // Process any errors.
1208
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001209 if (hasErr) {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001210 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001211 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001212 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001213 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001214
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001215 // Finally, consult the summary for the return value.
1216
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001217 RetEffect RE = GetRetEffect(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001218
1219 switch (RE.getKind()) {
1220 default:
1221 assert (false && "Unhandled RetEffect."); break;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001222
Ted Kremenek940b1d82008-04-10 23:44:06 +00001223 case RetEffect::NoRet:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001224
Ted Kremenekf9561e52008-04-11 20:23:24 +00001225 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +00001226 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1227 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001228
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001229 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001230 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001231 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001232
Ted Kremenek0e470a52008-05-09 23:45:33 +00001233 RVal X = LVal::IsLValType(Ex->getType())
1234 ? cast<RVal>(lval::SymbolVal(Sym))
1235 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenekf9561e52008-04-11 20:23:24 +00001236
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001237 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001238 }
1239
Ted Kremenek940b1d82008-04-10 23:44:06 +00001240 break;
1241
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001242 case RetEffect::Alias: {
1243 unsigned idx = RE.getValue();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001244 assert ((arg_end - arg_beg) >= 0);
1245 assert (idx < (unsigned) (arg_end - arg_beg));
1246 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1247 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001248 break;
1249 }
1250
Ted Kremenek14993892008-05-06 02:41:27 +00001251 case RetEffect::ReceiverAlias: {
1252 assert (Receiver);
1253 RVal V = StateMgr.GetRVal(St, Receiver);
1254 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
1255 break;
1256 }
1257
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001258 case RetEffect::OwnedSymbol: {
1259 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001260 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1261
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001262 ValueState StImpl = *St;
1263 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001264 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001265
1266 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001267 Ex, lval::SymbolVal(Sym),
1268 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001269
1270 break;
1271 }
1272
1273 case RetEffect::NotOwnedSymbol: {
1274 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001275 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001276
1277 ValueState StImpl = *St;
1278 RefBindings B = GetRefBindings(StImpl);
1279 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1280
1281 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001282 Ex, lval::SymbolVal(Sym),
1283 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001284
1285 break;
1286 }
1287 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001288
1289 Builder.MakeNode(Dst, Ex, Pred, St);
1290}
1291
1292
1293void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1294 GRExprEngine& Eng,
1295 GRStmtNodeBuilder<ValueState>& Builder,
1296 CallExpr* CE, RVal L,
1297 ExplodedNode<ValueState>* Pred) {
1298
1299
1300 RetainSummary* Summ = NULL;
1301
1302 // Get the summary.
1303
1304 if (isa<lval::FuncVal>(L)) {
1305 lval::FuncVal FV = cast<lval::FuncVal>(L);
1306 FunctionDecl* FD = FV.getDecl();
1307 Summ = Summaries.getSummary(FD, Eng.getContext());
1308 }
1309
1310 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1311 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001312}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001313
Ted Kremenek85348202008-04-15 23:44:31 +00001314
1315void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1316 GRExprEngine& Eng,
1317 GRStmtNodeBuilder<ValueState>& Builder,
1318 ObjCMessageExpr* ME,
1319 ExplodedNode<ValueState>* Pred) {
1320
Ted Kremenekb3095252008-05-06 04:20:12 +00001321 RetainSummary* Summ;
Ted Kremenek9040c652008-05-01 21:31:50 +00001322
Ted Kremenekb3095252008-05-06 04:20:12 +00001323 if (ME->getReceiver())
Ted Kremenek1bffd742008-05-06 15:44:25 +00001324 Summ = Summaries.getMethodSummary(ME);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001325 else
Ted Kremenekb3095252008-05-06 04:20:12 +00001326 Summ = Summaries.getInstanceMethodSummary(ME->getClassName(),
1327 ME->getSelector());
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001328
Ted Kremenekb3095252008-05-06 04:20:12 +00001329 EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
1330 ME->arg_begin(), ME->arg_end(), Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001331}
Ted Kremenekb3095252008-05-06 04:20:12 +00001332
Ted Kremenek13922612008-04-16 20:40:59 +00001333// Stores.
1334
1335void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1336 GRExprEngine& Eng,
1337 GRStmtNodeBuilder<ValueState>& Builder,
1338 Expr* E, ExplodedNode<ValueState>* Pred,
1339 ValueState* St, RVal TargetLV, RVal Val) {
1340
1341 // Check if we have a binding for "Val" and if we are storing it to something
1342 // we don't understand or otherwise the value "escapes" the function.
1343
1344 if (!isa<lval::SymbolVal>(Val))
1345 return;
1346
1347 // Are we storing to something that causes the value to "escape"?
1348
1349 bool escapes = false;
1350
1351 if (!isa<lval::DeclVal>(TargetLV))
1352 escapes = true;
1353 else
1354 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1355
1356 if (!escapes)
1357 return;
1358
1359 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1360 RefBindings B = GetRefBindings(*St);
1361 RefBindings::TreeTy* T = B.SlimFind(Sym);
1362
1363 if (!T)
1364 return;
1365
Ted Kremenekdb863712008-04-16 22:32:20 +00001366 // Nuke the binding.
1367 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001368
1369 // Hand of the remaining logic to the parent implementation.
1370 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1371}
1372
Ted Kremenekdb863712008-04-16 22:32:20 +00001373
1374ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1375 SymbolID sid) {
1376 ValueState StImpl = *St;
1377 RefBindings B = GetRefBindings(StImpl);
1378 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1379 return VMgr.getPersistentState(StImpl);
1380}
1381
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001382// End-of-path.
1383
Ted Kremenekdb863712008-04-16 22:32:20 +00001384ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1385 ValueState* St, SymbolID sid,
1386 RefVal V, bool& hasLeak) {
1387
Ted Kremenek4fd88972008-04-17 18:12:53 +00001388 hasLeak = V.isOwned() ||
1389 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001390
1391 if (!hasLeak)
1392 return NukeBinding(VMgr, St, sid);
1393
1394 RefBindings B = GetRefBindings(*St);
1395 ValueState StImpl = *St;
Ted Kremenekce48e002008-05-05 17:53:17 +00001396
1397 StImpl.CheckerState =
1398 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1399
Ted Kremenekdb863712008-04-16 22:32:20 +00001400 return VMgr.getPersistentState(StImpl);
1401}
1402
1403void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001404 GREndPathNodeBuilder<ValueState>& Builder) {
1405
Ted Kremenekdb863712008-04-16 22:32:20 +00001406 ValueState* St = Builder.getState();
1407 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001408
Ted Kremenekdb863712008-04-16 22:32:20 +00001409 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001410
Ted Kremenekdb863712008-04-16 22:32:20 +00001411 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1412 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001413
Ted Kremenekdb863712008-04-16 22:32:20 +00001414 St = HandleSymbolDeath(Eng.getStateManager(), St,
1415 (*I).first, (*I).second, hasLeak);
1416
1417 if (hasLeak) Leaked.push_back((*I).first);
1418 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001419
1420 if (Leaked.empty())
1421 return;
1422
Ted Kremenek8dd56462008-04-18 03:39:05 +00001423 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001424
Ted Kremenek652adc62008-04-24 23:57:27 +00001425 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001426 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001427
Ted Kremenek8dd56462008-04-18 03:39:05 +00001428 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1429 assert (!LeaksAtNode);
1430 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001431
1432 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1433 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001434 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001435}
1436
Ted Kremenek652adc62008-04-24 23:57:27 +00001437// Dead symbols.
1438
1439void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1440 GRExprEngine& Eng,
1441 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001442 ExplodedNode<ValueState>* Pred,
1443 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001444 ValueState* St,
1445 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001446
Ted Kremenek652adc62008-04-24 23:57:27 +00001447 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1448
1449 RefBindings B = GetRefBindings(*St);
1450 llvm::SmallVector<SymbolID, 10> Leaked;
1451
1452 for (ValueStateManager::DeadSymbolsTy::const_iterator
1453 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1454
1455 RefBindings::TreeTy* T = B.SlimFind(*I);
1456
1457 if (!T)
1458 continue;
1459
1460 bool hasLeak = false;
1461
1462 St = HandleSymbolDeath(Eng.getStateManager(), St,
1463 *I, T->getValue().second, hasLeak);
1464
1465 if (hasLeak) Leaked.push_back(*I);
1466 }
1467
1468 if (Leaked.empty())
1469 return;
1470
1471 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1472
1473 if (!N)
1474 return;
1475
1476 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1477 assert (!LeaksAtNode);
1478 LeaksAtNode = new std::vector<SymbolID>();
1479
1480 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1481 E = Leaked.end(); I != E; ++I)
1482 (*LeaksAtNode).push_back(*I);
1483}
1484
Ted Kremenek4fd88972008-04-17 18:12:53 +00001485 // Return statements.
1486
1487void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1488 GRExprEngine& Eng,
1489 GRStmtNodeBuilder<ValueState>& Builder,
1490 ReturnStmt* S,
1491 ExplodedNode<ValueState>* Pred) {
1492
1493 Expr* RetE = S->getRetValue();
1494 if (!RetE) return;
1495
1496 ValueStateManager& StateMgr = Eng.getStateManager();
1497 ValueState* St = Builder.GetState(Pred);
1498 RVal V = StateMgr.GetRVal(St, RetE);
1499
1500 if (!isa<lval::SymbolVal>(V))
1501 return;
1502
1503 // Get the reference count binding (if any).
1504 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1505 RefBindings B = GetRefBindings(*St);
1506 RefBindings::TreeTy* T = B.SlimFind(Sym);
1507
1508 if (!T)
1509 return;
1510
1511 // Change the reference count.
1512
1513 RefVal X = T->getValue().second;
1514
1515 switch (X.getKind()) {
1516
1517 case RefVal::Owned: {
1518 unsigned cnt = X.getCount();
1519 X = RefVal::makeReturnedOwned(cnt);
1520 break;
1521 }
1522
1523 case RefVal::NotOwned: {
1524 unsigned cnt = X.getCount();
1525 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1526 : RefVal::makeReturnedNotOwned();
1527 break;
1528 }
1529
1530 default:
Ted Kremenek4fd88972008-04-17 18:12:53 +00001531 return;
1532 }
1533
1534 // Update the binding.
1535
1536 ValueState StImpl = *St;
1537 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1538 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1539}
1540
Ted Kremenekcb612922008-04-18 19:23:43 +00001541// Assumptions.
1542
1543ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1544 RVal Cond, bool Assumption,
1545 bool& isFeasible) {
1546
1547 // FIXME: We may add to the interface of EvalAssume the list of symbols
1548 // whose assumptions have changed. For now we just iterate through the
1549 // bindings and check if any of the tracked symbols are NULL. This isn't
1550 // too bad since the number of symbols we will track in practice are
1551 // probably small and EvalAssume is only called at branches and a few
1552 // other places.
1553
1554 RefBindings B = GetRefBindings(*St);
1555
1556 if (B.isEmpty())
1557 return St;
1558
1559 bool changed = false;
1560
1561 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1562
1563 // Check if the symbol is null (or equal to any constant).
1564 // If this is the case, stop tracking the symbol.
1565
1566 if (St->getSymVal(I.getKey())) {
1567 changed = true;
1568 B = RefBFactory.Remove(B, I.getKey());
1569 }
1570 }
1571
1572 if (!changed)
1573 return St;
1574
1575 ValueState StImpl = *St;
1576 StImpl.CheckerState = B.getRoot();
1577 return Eng.getStateManager().getPersistentState(StImpl);
1578}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001579
1580CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001581 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001582 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001583
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001584 // FIXME: This dispatch can potentially be sped up by unifiying it into
1585 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001586
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001587 switch (E) {
1588 default:
1589 assert (false && "Unhandled CFRef transition.");
1590
1591 case DoNothing:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001592 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001593 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001594 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001595 break;
1596 }
1597
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001598 return B;
1599
Ted Kremenek14993892008-05-06 02:41:27 +00001600 case StopTracking:
1601 return RefBFactory.Remove(B, sym);
1602
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001603 case IncRef:
1604 switch (V.getKind()) {
1605 default:
1606 assert(false);
1607
1608 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001609 V = RefVal::makeOwned(V.getCount()+1);
1610 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001611
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001612 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001613 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001614 break;
1615
1616 case RefVal::Released:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001617 if (isGCEnabled())
Ted Kremenek65c91652008-04-29 05:44:10 +00001618 V = RefVal::makeOwned();
1619 else {
1620 V = RefVal::makeUseAfterRelease();
1621 hasErr = V.getKind();
1622 }
1623
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001624 break;
1625 }
1626
Ted Kremenek940b1d82008-04-10 23:44:06 +00001627 break;
1628
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001629 case DecRef:
1630 switch (V.getKind()) {
1631 default:
1632 assert (false);
1633
1634 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001635 unsigned Count = V.getCount();
1636 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001637 break;
1638 }
1639
Ted Kremenek61b9f872008-04-10 23:09:18 +00001640 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001641 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001642
Ted Kremenek4fd88972008-04-17 18:12:53 +00001643 if (Count > 0)
1644 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001645 else {
1646 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001647 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001648 }
1649
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001650 break;
1651 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001652
1653 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001654 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001655 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001656 break;
1657 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001658
1659 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001660 }
1661
1662 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001663}
1664
Ted Kremenekfa34b332008-04-09 01:10:13 +00001665
1666//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001667// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001668//===----------------------------------------------------------------------===//
1669
Ted Kremenek8dd56462008-04-18 03:39:05 +00001670namespace {
1671
1672 //===-------------===//
1673 // Bug Descriptions. //
1674 //===-------------===//
1675
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001676 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001677 protected:
1678 CFRefCount& TF;
1679
1680 public:
1681 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenek072192b2008-04-30 23:47:44 +00001682
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001683 CFRefCount& getTF() { return TF; }
Ted Kremenek789deac2008-05-05 23:16:31 +00001684 const CFRefCount& getTF() const { return TF; }
1685
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001686 virtual bool isLeak() const { return false; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001687 };
1688
1689 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1690 public:
1691 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1692
1693 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001694 return "Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001695 }
1696 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001697 return "Reference-counted object is used"
1698 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001699 }
1700
1701 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001702 };
1703
1704 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1705 public:
1706 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1707
1708 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001709 return "Bad Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001710 }
1711 virtual const char* getDescription() const {
1712 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001713 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001714 "The object is not owned at this point by the caller.";
1715 }
1716
1717 virtual void EmitWarnings(BugReporter& BR);
1718 };
1719
1720 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1721 public:
1722 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1723
1724 virtual const char* getName() const {
Ted Kremenek432af592008-05-06 18:11:36 +00001725
1726 if (getTF().isGCEnabled())
1727 return "Memory Leak (GC)";
1728
1729 if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
1730 return "Memory Leak (Hybrid MM, non-GC)";
1731
1732 assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
1733 return "Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001734 }
1735
1736 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001737 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001738 }
1739
1740 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001741 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001742 virtual bool isLeak() const { return true; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001743 };
1744
1745 //===---------===//
1746 // Bug Reports. //
1747 //===---------===//
1748
1749 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1750 SymbolID Sym;
1751 public:
Ted Kremenek072192b2008-04-30 23:47:44 +00001752 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001753 : RangedBugReport(D, n), Sym(sym) {}
1754
1755 virtual ~CFRefReport() {}
1756
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001757 CFRefBug& getBugType() {
1758 return (CFRefBug&) RangedBugReport::getBugType();
1759 }
1760 const CFRefBug& getBugType() const {
1761 return (const CFRefBug&) RangedBugReport::getBugType();
1762 }
1763
1764 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1765 const SourceRange*& end) {
1766
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001767 if (!getBugType().isLeak())
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001768 RangedBugReport::getRanges(BR, beg, end);
1769 else {
1770 beg = 0;
1771 end = 0;
1772 }
1773 }
1774
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001775 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1776 ExplodedNode<ValueState>* N);
1777
Ted Kremenek072192b2008-04-30 23:47:44 +00001778 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek8dd56462008-04-18 03:39:05 +00001779
1780 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1781 ExplodedNode<ValueState>* PrevN,
1782 ExplodedGraph<ValueState>& G,
1783 BugReporter& BR);
1784 };
1785
1786
1787} // end anonymous namespace
1788
1789void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek9f741612008-05-02 18:01:49 +00001790 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001791 Eng.Register(new UseAfterRelease(*this));
1792 Eng.Register(new BadRelease(*this));
1793 Eng.Register(new Leak(*this));
1794}
1795
Ted Kremenek072192b2008-04-30 23:47:44 +00001796
1797static const char* Msgs[] = {
1798 "Code is compiled in garbage collection only mode" // GC only
1799 " (the bug occurs with garbage collection enabled).",
1800
1801 "Code is compiled without garbage collection.", // No GC.
1802
1803 "Code is compiled for use with and without garbage collection (GC)."
1804 " The bug occurs with GC enabled.", // Hybrid, with GC.
1805
1806 "Code is compiled for use with and without garbage collection (GC)."
1807 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1808};
1809
1810std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1811 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1812
1813 switch (TF.getLangOptions().getGCMode()) {
1814 default:
1815 assert(false);
Ted Kremenek31593ac2008-05-01 04:02:04 +00001816
1817 case LangOptions::GCOnly:
1818 assert (TF.isGCEnabled());
1819 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenek072192b2008-04-30 23:47:44 +00001820
1821 case LangOptions::NonGC:
1822 assert (!TF.isGCEnabled());
Ted Kremenek072192b2008-04-30 23:47:44 +00001823 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1824
1825 case LangOptions::HybridGC:
1826 if (TF.isGCEnabled())
1827 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1828 else
1829 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1830 }
1831}
1832
Ted Kremenek8dd56462008-04-18 03:39:05 +00001833PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1834 ExplodedNode<ValueState>* PrevN,
1835 ExplodedGraph<ValueState>& G,
1836 BugReporter& BR) {
1837
1838 // Check if the type state has changed.
1839
1840 ValueState* PrevSt = PrevN->getState();
1841 ValueState* CurrSt = N->getState();
1842
1843 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1844 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1845
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001846 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1847 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001848
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001849 if (!CurrT)
1850 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001851
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001852 const char* Msg = NULL;
1853 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenekce48e002008-05-05 17:53:17 +00001854
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001855 if (!PrevT) {
1856
Ted Kremenekce48e002008-05-05 17:53:17 +00001857 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1858
1859 if (CurrV.isOwned()) {
1860
1861 if (isa<CallExpr>(S))
1862 Msg = "Function call returns an object with a +1 retain count"
1863 " (owning reference).";
1864 else {
1865 assert (isa<ObjCMessageExpr>(S));
1866 Msg = "Method returns an object with a +1 retain count"
1867 " (owning reference).";
1868 }
1869 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001870 else {
1871 assert (CurrV.isNotOwned());
Ted Kremenekce48e002008-05-05 17:53:17 +00001872
1873 if (isa<CallExpr>(S))
1874 Msg = "Function call returns an object with a +0 retain count"
1875 " (non-owning reference).";
1876 else {
1877 assert (isa<ObjCMessageExpr>(S));
1878 Msg = "Method returns an object with a +0 retain count"
1879 " (non-owning reference).";
1880 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001881 }
Ted Kremenekce48e002008-05-05 17:53:17 +00001882
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001883 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1884 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1885
1886 if (Expr* Exp = dyn_cast<Expr>(S))
1887 P->addRange(Exp->getSourceRange());
1888
1889 return P;
1890 }
1891
1892 // Determine if the typestate has changed.
1893
1894 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1895
1896 if (PrevV == CurrV)
1897 return NULL;
1898
1899 // The typestate has changed.
1900
1901 std::ostringstream os;
1902
1903 switch (CurrV.getKind()) {
1904 case RefVal::Owned:
1905 case RefVal::NotOwned:
1906 assert (PrevV.getKind() == CurrV.getKind());
1907
1908 if (PrevV.getCount() > CurrV.getCount())
1909 os << "Reference count decremented.";
1910 else
1911 os << "Reference count incremented.";
1912
Ted Kremenekce48e002008-05-05 17:53:17 +00001913 if (unsigned Count = GetCount(CurrV)) {
1914
1915 os << " Object has +" << Count;
Ted Kremenek79c140b2008-04-18 05:32:44 +00001916
Ted Kremenekce48e002008-05-05 17:53:17 +00001917 if (Count > 1)
1918 os << " retain counts.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00001919 else
Ted Kremenekce48e002008-05-05 17:53:17 +00001920 os << " retain count.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00001921 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001922
1923 Msg = os.str().c_str();
1924
1925 break;
1926
1927 case RefVal::Released:
1928 Msg = "Object released.";
1929 break;
1930
1931 case RefVal::ReturnedOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00001932 Msg = "Object returned to caller as owning reference (single retain count"
1933 " transferred to caller).";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001934 break;
1935
1936 case RefVal::ReturnedNotOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00001937 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001938 break;
1939
1940 default:
1941 return NULL;
1942 }
1943
1944 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1945 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1946 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1947
1948 // Add the range by scanning the children of the statement for any bindings
1949 // to Sym.
1950
1951 ValueStateManager& VSM = BR.getEngine().getStateManager();
1952
1953 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1954 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1955 RVal X = VSM.GetRVal(CurrSt, Exp);
1956
1957 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1958 if (SV->getSymbol() == Sym) {
1959 P->addRange(Exp->getSourceRange()); break;
1960 }
1961 }
1962
1963 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001964}
1965
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00001966
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001967PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremeneke28565b2008-05-05 18:50:19 +00001968 ExplodedNode<ValueState>* EndN) {
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001969
1970 if (!getBugType().isLeak())
Ted Kremeneke28565b2008-05-05 18:50:19 +00001971 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001972
Ted Kremenekce48e002008-05-05 17:53:17 +00001973 typedef CFRefCount::RefBindings RefBindings;
1974
1975 // Get the retain count.
1976 unsigned long RetCount = 0;
1977
1978 {
Ted Kremeneke28565b2008-05-05 18:50:19 +00001979 ValueState* St = EndN->getState();
Ted Kremenekce48e002008-05-05 17:53:17 +00001980 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1981 RefBindings::TreeTy* T = B.SlimFind(Sym);
1982 assert (T);
1983 RetCount = GetCount(T->getValue().second);
1984 }
1985
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001986 // We are a leak. Walk up the graph to get to the first node where the
1987 // symbol appeared.
1988
Ted Kremeneke28565b2008-05-05 18:50:19 +00001989 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001990 ExplodedNode<ValueState>* Last = N;
Ted Kremeneke28565b2008-05-05 18:50:19 +00001991
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001992 // Find the first node that referred to the tracked symbol. We also
1993 // try and find the first VarDecl the value was stored to.
1994
1995 VarDecl* FirstDecl = 0;
Ted Kremeneke28565b2008-05-05 18:50:19 +00001996
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001997 while (N) {
1998 ValueState* St = N->getState();
1999 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002000 RefBindings::TreeTy* T = B.SlimFind(Sym);
2001
2002 if (!T)
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002003 break;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002004
2005 VarDecl* VD = 0;
2006
2007 // Determine if there is an LVal binding to the symbol.
2008 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
2009 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
2010 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
2011 continue;
2012
2013 if (VD) { // Multiple decls map to this symbol.
2014 VD = 0;
2015 break;
2016 }
2017
2018 VD = I->first;
2019 }
2020
2021 if (VD) FirstDecl = VD;
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002022
2023 Last = N;
2024 N = N->pred_empty() ? NULL : *(N->pred_begin());
2025 }
2026
Ted Kremeneke28565b2008-05-05 18:50:19 +00002027 // Get the allocate site.
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002028
2029 assert (Last);
2030 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
2031
Ted Kremeneke28565b2008-05-05 18:50:19 +00002032 SourceManager& SMgr = BR.getContext().getSourceManager();
2033 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002034
Ted Kremeneke28565b2008-05-05 18:50:19 +00002035 // Get the leak site. We may have multiple ExplodedNodes (one with the
2036 // leak) that occur on the same line number; if the node with the leak
2037 // has any immediate predecessor nodes with the same line number, find
2038 // any transitive-successors that have a different statement and use that
2039 // line number instead. This avoids emiting a diagnostic like:
2040 //
2041 // // 'y' is leaked.
2042 // int x = foo(y);
2043 //
2044 // instead we want:
2045 //
2046 // int x = foo(y);
2047 // // 'y' is leaked.
2048
2049 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
2050 assert (S);
2051 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
2052
2053 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
2054 // it occur on the same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002055
2056 PathDiagnosticPiece::DisplayHint Hint = PathDiagnosticPiece::Above;
Ted Kremeneke28565b2008-05-05 18:50:19 +00002057
2058 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002059 ExplodedNode<ValueState> *Pred = *(EndN->pred_begin());
2060 ProgramPoint PredPos = Pred->getLocation();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002061
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002062 if (PostStmt* PredPS = dyn_cast<PostStmt>(&PredPos)) {
Ted Kremeneke28565b2008-05-05 18:50:19 +00002063
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002064 Stmt* SPred = PredPS->getStmt();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002065
2066 // Predecessor at same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002067 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine) {
2068 Hint = PathDiagnosticPiece::Below;
2069 S = SPred;
2070 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002071 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002072
2073 // Generate the diagnostic.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002074 FullSourceLoc L( S->getLocStart(), SMgr);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002075 std::ostringstream os;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002076
Ted Kremeneke28565b2008-05-05 18:50:19 +00002077 os << "Object allocated on line " << AllocLine;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002078
2079 if (FirstDecl)
2080 os << " and stored into '" << FirstDecl->getName() << '\'';
2081
Ted Kremenekce48e002008-05-05 17:53:17 +00002082 os << " is no longer referenced after this point and has a retain count of +"
2083 << RetCount << " (object leaked).";
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002084
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002085 return new PathDiagnosticPiece(L, os.str(), Hint);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002086}
2087
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002088void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002089
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002090 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2091 E = TF.use_after_end(); I != E; ++I) {
2092
Ted Kremenek8dd56462008-04-18 03:39:05 +00002093 CFRefReport report(*this, I->first, I->second.second);
2094 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00002095 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00002096 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002097}
2098
2099void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002100
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002101 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2102 E = TF.bad_release_end(); I != E; ++I) {
2103
Ted Kremenek8dd56462008-04-18 03:39:05 +00002104 CFRefReport report(*this, I->first, I->second.second);
2105 report.addRange(I->second.first->getSourceRange());
2106 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002107 }
2108}
Ted Kremenekfa34b332008-04-09 01:10:13 +00002109
Ted Kremenek989d5192008-04-17 23:43:50 +00002110void Leak::EmitWarnings(BugReporter& BR) {
2111
2112 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2113 E = TF.leaks_end(); I != E; ++I) {
2114
Ted Kremenek8dd56462008-04-18 03:39:05 +00002115 std::vector<SymbolID>& SymV = *(I->second);
2116 unsigned n = SymV.size();
2117
2118 for (unsigned i = 0; i < n; ++i) {
2119 CFRefReport report(*this, I->first, SymV[i]);
2120 BR.EmitWarning(report);
2121 }
Ted Kremenek989d5192008-04-17 23:43:50 +00002122 }
2123}
2124
Ted Kremenekcb612922008-04-18 19:23:43 +00002125void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2126 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2127 I!=E; ++I)
2128 Nodes.push_back(I->first);
2129}
2130
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002131//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00002132// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002133//===----------------------------------------------------------------------===//
2134
Ted Kremenek072192b2008-04-30 23:47:44 +00002135GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek9f741612008-05-02 18:01:49 +00002136 bool StandardWarnings,
Ted Kremenek072192b2008-04-30 23:47:44 +00002137 const LangOptions& lopts) {
Ted Kremenek9f741612008-05-02 18:01:49 +00002138 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00002139}