blob: 6f8eae2186492c9ff26690fc3e679527c30b0db6 [file] [log] [blame]
Chris Lattnerbe1a7a02008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek827f93b2008-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 Greif2224fcb2008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek827f93b2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremeneka7338b42008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenekfe30beb2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenekfe4d2312008-05-01 23:13:35 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenekdd0126b2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000020#include "clang/Analysis/LocalCheckers.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000021#include "clang/Analysis/PathDiagnostic.h"
22#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremeneka7338b42008-03-11 06:39:11 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek2ac4ba62008-05-07 18:36:45 +000026#include "llvm/ADT/StringExtras.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000027#include "llvm/Support/Compiler.h"
Ted Kremenek3b11f7a2008-03-11 19:44:10 +000028#include <ostream>
Ted Kremeneka8503952008-04-18 04:55:01 +000029#include <sstream>
Ted Kremenek827f93b2008-03-06 00:08:09 +000030
31using namespace clang;
Ted Kremenek2ac4ba62008-05-07 18:36:45 +000032using llvm::CStrInCStrNoCase;
Ted Kremenek827f93b2008-03-06 00:08:09 +000033
Ted Kremenek7d421f32008-04-09 23:49:11 +000034//===----------------------------------------------------------------------===//
Ted Kremenekd9ccf682008-04-17 18:12:53 +000035// Utility functions.
36//===----------------------------------------------------------------------===//
37
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +000038static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenekd9ccf682008-04-17 18:12:53 +000039 IdentifierInfo* II = &Ctx.Idents.get(name);
40 return Ctx.Selectors.getSelector(0, &II);
41}
42
Ted Kremenek0e344d42008-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 Kremenek62820d82008-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 Kremenekd9ccf682008-04-17 18:12:53 +000091//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +000092// Symbolic Evaluation of Reference Counting Logic
93//===----------------------------------------------------------------------===//
94
Ted Kremeneka7338b42008-03-11 06:39:11 +000095namespace {
Ted Kremenek227c5372008-05-06 02:41:27 +000096 enum ArgEffect { IncRef, DecRef, DoNothing, StopTracking };
Ted Kremenekae855d42008-04-24 17:22:33 +000097 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremeneka7338b42008-03-11 06:39:11 +000098}
Ted Kremenek827f93b2008-03-06 00:08:09 +000099
Ted Kremeneka7338b42008-03-11 06:39:11 +0000100namespace llvm {
101 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +0000102 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenekae855d42008-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 Kremeneka4c74292008-04-10 22:58:08 +0000107 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000108 };
109} // end llvm namespace
110
111namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +0000112
Ted Kremeneka7338b42008-03-11 06:39:11 +0000113class RetEffect {
114public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000115 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000116 NotOwnedSymbol = 0x3, ReceiverAlias=0x4 };
Ted Kremeneka7338b42008-03-11 06:39:11 +0000117
118private:
119 unsigned Data;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000120 RetEffect(Kind k, unsigned D) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000121
Ted Kremeneka7338b42008-03-11 06:39:11 +0000122public:
123
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000124 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000125
126 unsigned getValue() const {
127 assert(getKind() == Alias);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000128 return Data >> 3;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000129 }
Ted Kremenekffefc352008-04-11 22:25:11 +0000130
Ted Kremeneka7338b42008-03-11 06:39:11 +0000131 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000132
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000133 static RetEffect MakeReceiverAlias() { return RetEffect(ReceiverAlias, 0); }
134
Ted Kremeneka7338b42008-03-11 06:39:11 +0000135 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000136
Ted Kremeneka7338b42008-03-11 06:39:11 +0000137 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
138
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000139 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
140
Ted Kremeneka7338b42008-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 Kremeneka8c3c432008-05-05 22:11:16 +0000147class RetainSummary : public llvm::FoldingSetNode {
Ted Kremenekbcaff792008-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 Kremeneka7338b42008-03-11 06:39:11 +0000151 ArgEffects* Args;
Ted Kremenekbcaff792008-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 Kremenek266d8b62008-05-06 02:26:56 +0000157 ArgEffect Receiver;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000158 RetEffect Ret;
159public:
160
Ted Kremenekbcaff792008-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 Kremeneka7338b42008-03-11 06:39:11 +0000164
Ted Kremenek0d721572008-03-11 17:48:22 +0000165 ArgEffect getArg(unsigned idx) const {
Ted Kremenekbcaff792008-05-06 15:44:25 +0000166
Ted Kremenekae855d42008-04-24 17:22:33 +0000167 if (!Args)
Ted Kremenekbcaff792008-05-06 15:44:25 +0000168 return DefaultArgEffect;
Ted Kremenekae855d42008-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 Kremenekbcaff792008-05-06 15:44:25 +0000179 return DefaultArgEffect;
Ted Kremenekae855d42008-04-24 17:22:33 +0000180
181 if (idx == I->first)
182 return I->second;
183 }
184
Ted Kremenekbcaff792008-05-06 15:44:25 +0000185 return DefaultArgEffect;
Ted Kremenek0d721572008-03-11 17:48:22 +0000186 }
187
Ted Kremenek266d8b62008-05-06 02:26:56 +0000188 RetEffect getRetEffect() const {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000189 return Ret;
190 }
191
Ted Kremenek266d8b62008-05-06 02:26:56 +0000192 ArgEffect getReceiverEffect() const {
193 return Receiver;
194 }
195
Ted Kremeneka7338b42008-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 Kremenek266d8b62008-05-06 02:26:56 +0000201 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A,
Ted Kremenekbcaff792008-05-06 15:44:25 +0000202 RetEffect RetEff, ArgEffect DefaultEff,
203 ArgEffect ReceiverEff) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000204 ID.AddPointer(A);
Ted Kremenek266d8b62008-05-06 02:26:56 +0000205 ID.Add(RetEff);
Ted Kremenekbcaff792008-05-06 15:44:25 +0000206 ID.AddInteger((unsigned) DefaultEff);
Ted Kremenek266d8b62008-05-06 02:26:56 +0000207 ID.AddInteger((unsigned) ReceiverEff);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000208 }
209
210 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenekbcaff792008-05-06 15:44:25 +0000211 Profile(ID, Args, Ret, DefaultArgEffect, Receiver);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000212 }
213};
214
215
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000216class RetainSummaryManager {
217
218 //==-----------------------------------------------------------------==//
219 // Typedefs.
220 //==-----------------------------------------------------------------==//
Ted Kremeneka7338b42008-03-11 06:39:11 +0000221
Ted Kremeneka8c3c432008-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 Kremenek0e344d42008-05-06 00:30:21 +0000232 ObjCMethSummariesTy;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000233
234 //==-----------------------------------------------------------------==//
235 // Data.
236 //==-----------------------------------------------------------------==//
237
238 // Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000239 ASTContext& Ctx;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000240
241 // GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000242 const bool GCEnabled;
243
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000244 // SummarySet - A FoldingSet of uniqued summaries.
Ted Kremeneka4c74292008-04-10 22:58:08 +0000245 SummarySetTy SummarySet;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000246
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000247 // FuncSummaries - A map from FunctionDecls to summaries.
248 FuncSummariesTy FuncSummaries;
249
Ted Kremenek0e344d42008-05-06 00:30:21 +0000250 // ObjCInstMethSummaries - A map from selectors (for instance methods)
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000251 // to summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000252 ObjCMethSummariesTy ObjCInstMethSummaries;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000253
Ted Kremenek0e344d42008-05-06 00:30:21 +0000254 // ObjCMethSummaries - A map from selectors to summaries.
255 ObjCMethSummariesTy ObjCMethSummaries;
Ted Kremeneka8c3c432008-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 Kremenekb3a44e72008-05-06 18:11:36 +0000267 RetainSummary* StopSummary;
268
Ted Kremeneka8c3c432008-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 Kremenekce3ed1e2008-03-12 01:21:45 +0000275 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000276
Ted Kremenek562c1302008-05-05 16:51:50 +0000277 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000278 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000279
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000280 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
281 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000282
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000283 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
284 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000285
Ted Kremenek266d8b62008-05-06 02:26:56 +0000286 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenekbcaff792008-05-06 15:44:25 +0000287 ArgEffect ReceiverEff = DoNothing,
288 ArgEffect DefaultEff = DoNothing);
289
Ted Kremenek0e344d42008-05-06 00:30:21 +0000290
Ted Kremenek266d8b62008-05-06 02:26:56 +0000291 RetainSummary* getPersistentSummary(RetEffect RE,
Ted Kremenekbcaff792008-05-06 15:44:25 +0000292 ArgEffect ReceiverEff = DoNothing,
293 ArgEffect DefaultEff = DoNothing) {
294 return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
Ted Kremenek0e344d42008-05-06 00:30:21 +0000295 }
Ted Kremenek42ea0322008-05-05 23:55:01 +0000296
Ted Kremenekb3a44e72008-05-06 18:11:36 +0000297
298
Ted Kremenekbcaff792008-05-06 15:44:25 +0000299 RetainSummary* getPersistentStopSummary() {
Ted Kremenekb3a44e72008-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 Kremenekbcaff792008-05-06 15:44:25 +0000307 }
Ted Kremenek926abf22008-05-06 04:20:12 +0000308
Ted Kremenek42ea0322008-05-05 23:55:01 +0000309 RetainSummary* getInitMethodSummary(Selector S);
310
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000311 void InitializeInstMethSummaries();
312 void InitializeMethSummaries();
Ted Kremenek0e344d42008-05-06 00:30:21 +0000313
Ted Kremeneka7338b42008-03-11 06:39:11 +0000314public:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000315
316 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenekb3a44e72008-05-06 18:11:36 +0000317 : Ctx(ctx), GCEnabled(gcenabled), StopSummary(0) {
Ted Kremenek0e344d42008-05-06 00:30:21 +0000318
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000319 InitializeInstMethSummaries();
320 InitializeMethSummaries();
Ted Kremenek0e344d42008-05-06 00:30:21 +0000321 }
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000322
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000323 ~RetainSummaryManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000324
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000325 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
326
Ted Kremenekbcaff792008-05-06 15:44:25 +0000327 RetainSummary* getMethodSummary(ObjCMessageExpr* ME);
Ted Kremenek926abf22008-05-06 04:20:12 +0000328 RetainSummary* getInstanceMethodSummary(IdentifierInfo* ClsName, Selector S);
329
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000330 bool isGCEnabled() const { return GCEnabled; }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000331};
332
333} // end anonymous namespace
334
335//===----------------------------------------------------------------------===//
336// Implementation of checker data structures.
337//===----------------------------------------------------------------------===//
338
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000339RetainSummaryManager::~RetainSummaryManager() {
Ted Kremeneka7338b42008-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 Kremenek42ea0322008-05-05 23:55:01 +0000345 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
346 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremeneka7338b42008-03-11 06:39:11 +0000347 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000348}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000349
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000350ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000351
Ted Kremenekae855d42008-04-24 17:22:33 +0000352 if (ScratchArgs.empty())
353 return NULL;
354
355 // Compute a profile for a non-empty ScratchArgs.
356
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000357 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000358
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000359 profile.Add(ScratchArgs);
360 void* InsertPos;
361
Ted Kremenekae855d42008-04-24 17:22:33 +0000362 // Look up the uniqued copy, or create a new one.
363
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000364 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000365 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000366
Ted Kremenekae855d42008-04-24 17:22:33 +0000367 if (E) {
Ted Kremenekce3ed1e2008-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 Kremeneka8c3c432008-05-05 22:11:16 +0000376 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000377
378 ScratchArgs.clear();
379 return &E->getValue();
380}
381
Ted Kremenek266d8b62008-05-06 02:26:56 +0000382RetainSummary*
383RetainSummaryManager::getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenekbcaff792008-05-06 15:44:25 +0000384 ArgEffect ReceiverEff,
385 ArgEffect DefaultEff) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000386
Ted Kremenekae855d42008-04-24 17:22:33 +0000387 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000388 llvm::FoldingSetNodeID profile;
Ted Kremenekbcaff792008-05-06 15:44:25 +0000389 RetainSummary::Profile(profile, AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000390
Ted Kremenekae855d42008-04-24 17:22:33 +0000391 // Look up the uniqued summary, or create one if it doesn't exist.
392 void* InsertPos;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000393 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000394
395 if (Summ)
396 return Summ;
397
Ted Kremenekae855d42008-04-24 17:22:33 +0000398 // Create the summary and return it.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000399 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
Ted Kremenekbcaff792008-05-06 15:44:25 +0000400 new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000401 SummarySet.InsertNode(Summ, InsertPos);
402
403 return Summ;
404}
405
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000406//===----------------------------------------------------------------------===//
407// Summary creation for functions (largely uses of Core Foundation).
408//===----------------------------------------------------------------------===//
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000409
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000410RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000411 ASTContext& Ctx) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000412
413 SourceLocation Loc = FD->getLocation();
414
415 if (!Loc.isFileID())
416 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000417
Ted Kremenekae855d42008-04-24 17:22:33 +0000418 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000419 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenekae855d42008-04-24 17:22:33 +0000420
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000421 if (I != FuncSummaries.end())
Ted Kremenekae855d42008-04-24 17:22:33 +0000422 return I->second;
423
424 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000425 const char* FName = FD->getIdentifier()->getName();
426
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000427 RetainSummary *S = 0;
Ted Kremenek562c1302008-05-05 16:51:50 +0000428
Ted Kremenek62820d82008-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 Kremenek562c1302008-05-05 16:51:50 +0000435 else if (FName[0] == 'N' && FName[1] == 'S')
436 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000437
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000438 FuncSummaries[FD] = S;
Ted Kremenek562c1302008-05-05 16:51:50 +0000439 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000440}
441
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000442RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000443 const char* FName) {
Ted Kremenek562c1302008-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 Kremeneka8c3c432008-05-05 22:11:16 +0000452RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000453 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000454
Ted Kremenek62820d82008-05-07 20:06:41 +0000455 if (FName[0] == 'C' && FName[1] == 'F')
456 FName += 2;
Ted Kremenek562c1302008-05-05 16:51:50 +0000457
458 if (strcmp(FName, "Retain") == 0)
459 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000460
Ted Kremenek562c1302008-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 Kremeneka8c3c432008-05-05 22:11:16 +0000476RetainSummary*
477RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000478
479 FunctionTypeProto* FT =
480 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
481
Ted Kremenek562c1302008-05-05 16:51:50 +0000482 if (FT) {
483
484 if (FT->getNumArgs() != 1)
485 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000486
Ted Kremenek562c1302008-05-05 16:51:50 +0000487 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
488
489 if (!ArgT)
490 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000491
Ted Kremenek562c1302008-05-05 16:51:50 +0000492 if (!ArgT->isPointerType())
493 return NULL;
494 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000495
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000496 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000497
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000498 switch (func) {
499 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000500 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek0e344d42008-05-06 00:30:21 +0000501 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000502 }
503
504 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000505 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek0e344d42008-05-06 00:30:21 +0000506 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000507 }
508
509 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000510 if (GCEnabled)
511 ScratchArgs.push_back(std::make_pair(0, DecRef));
512
Ted Kremenek0e344d42008-05-06 00:30:21 +0000513 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000514 }
515
516 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000517 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000518 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000519}
520
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000521RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000522
Ted Kremenek62820d82008-05-07 20:06:41 +0000523 FunctionType* FT =
524 dyn_cast<FunctionType>(FD->getType().getTypePtr());
Ted Kremenek562c1302008-05-05 16:51:50 +0000525
526 if (FT && !isCFRefType(FT->getResultType()))
527 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000528
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000529 // FIXME: Add special-cases for functions that retain/release. For now
530 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000531
532 assert (ScratchArgs.empty());
Ted Kremenek0e344d42008-05-06 00:30:21 +0000533 return getPersistentSummary(RetEffect::MakeOwned());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000534}
535
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000536RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000537
Ted Kremenek62820d82008-05-07 20:06:41 +0000538 FunctionType* FT =
539 dyn_cast<FunctionType>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000540
Ted Kremenek562c1302008-05-05 16:51:50 +0000541 if (FT) {
542 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000543
Ted Kremenek562c1302008-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 Kremenekce3ed1e2008-03-12 01:21:45 +0000553
Ted Kremenekce3ed1e2008-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 Kremenekae855d42008-04-24 17:22:33 +0000557 assert (ScratchArgs.empty());
Ted Kremenek0e344d42008-05-06 00:30:21 +0000558 return getPersistentSummary(RetEffect::MakeNotOwned());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000559}
560
Ted Kremeneka7338b42008-03-11 06:39:11 +0000561//===----------------------------------------------------------------------===//
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000562// Summary creation for Selectors.
563//===----------------------------------------------------------------------===//
564
Ted Kremenekbcaff792008-05-06 15:44:25 +0000565RetainSummary*
566RetainSummaryManager::getInitMethodSummary(Selector S) {
Ted Kremenek42ea0322008-05-05 23:55:01 +0000567 assert(ScratchArgs.empty());
568
569 RetainSummary* Summ =
Ted Kremenek0e344d42008-05-06 00:30:21 +0000570 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek42ea0322008-05-05 23:55:01 +0000571
Ted Kremenek0e344d42008-05-06 00:30:21 +0000572 ObjCMethSummaries[S] = Summ;
Ted Kremenek42ea0322008-05-05 23:55:01 +0000573 return Summ;
574}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000575
Ted Kremenekbcaff792008-05-06 15:44:25 +0000576RetainSummary*
577RetainSummaryManager::getMethodSummary(ObjCMessageExpr* ME) {
578
579 Selector S = ME->getSelector();
Ted Kremenek42ea0322008-05-05 23:55:01 +0000580
581 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000582 ObjCMethSummariesTy::iterator I = ObjCMethSummaries.find(S);
Ted Kremenek42ea0322008-05-05 23:55:01 +0000583
Ted Kremenek0e344d42008-05-06 00:30:21 +0000584 if (I != ObjCMethSummaries.end())
Ted Kremenek42ea0322008-05-05 23:55:01 +0000585 return I->second;
Ted Kremeneka7722b72008-05-06 21:26:51 +0000586
587#if 0
Ted Kremenekbcaff792008-05-06 15:44:25 +0000588 // Only generate real summaries for methods involving
589 // NSxxxx objects.
Ted Kremeneka7722b72008-05-06 21:26:51 +0000590
Ted Kremenekbcaff792008-05-06 15:44:25 +0000591 if (!isNSType(ME->getReceiver()->getType())) {
592 RetainSummary* Summ = getPersistentStopSummary();
593 ObjCMethSummaries[S] = Summ;
594 return Summ;
595 }
Ted Kremeneka7722b72008-05-06 21:26:51 +0000596#endif
Ted Kremenekb3a44e72008-05-06 18:11:36 +0000597
Ted Kremenek48b6d9e2008-05-07 03:45:05 +0000598 if (!ME->getType()->isPointerType())
599 return 0;
600
Ted Kremenek42ea0322008-05-05 23:55:01 +0000601 // "initXXX": pass-through for receiver.
602
603 const char* s = S.getIdentifierInfoForSlot(0)->getName();
Ted Kremenek48b6d9e2008-05-07 03:45:05 +0000604 assert (ScratchArgs.empty());
Ted Kremenek1d3d9562008-05-06 06:09:09 +0000605
Ted Kremenekbcfac332008-05-06 06:17:42 +0000606 if (strncmp(s, "init", 4) == 0)
Ted Kremenekb3a44e72008-05-06 18:11:36 +0000607 return getInitMethodSummary(S);
Ted Kremenekbcaff792008-05-06 15:44:25 +0000608
Ted Kremenek48b6d9e2008-05-07 03:45:05 +0000609 // "copyXXX", "createXXX", "newXXX": allocators.
Ted Kremenek42ea0322008-05-05 23:55:01 +0000610
Ted Kremenek5496f6d2008-05-07 04:25:59 +0000611 if (!isNSType(ME->getReceiver()->getType()))
612 return 0;
613
Ted Kremenek62820d82008-05-07 20:06:41 +0000614 if (CStrInCStrNoCase(s, "create") || CStrInCStrNoCase(s, "copy") ||
615 CStrInCStrNoCase(s, "new")) {
Ted Kremenek48b6d9e2008-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 Kremenekbcaff792008-05-06 15:44:25 +0000622 return Summ;
623 }
Ted Kremenekbcaff792008-05-06 15:44:25 +0000624
Ted Kremenek42ea0322008-05-05 23:55:01 +0000625 return 0;
626}
627
Ted Kremeneka7722b72008-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 Kremenek4c479322008-05-06 23:07:13 +0000638 return 0;
639
640#if 0
641 return 0;
642
Ted Kremeneka7722b72008-05-06 21:26:51 +0000643 // Don't track anything if using GC.
644 if (isGCEnabled())
Ted Kremenek4c479322008-05-06 23:07:13 +0000645 return 0;
646
Ted Kremeneka7722b72008-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 Kremenek4c479322008-05-06 23:07:13 +0000682#endif
Ted Kremeneka7722b72008-05-06 21:26:51 +0000683}
684
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000685void RetainSummaryManager::InitializeInstMethSummaries() {
Ted Kremenek0e344d42008-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 Kremenek228f0802008-05-07 05:34:45 +0000699 ObjCInstMethSummaries[ GetUnarySelector("allocWithZone", Ctx) ] = Summ;
Ted Kremenek0e344d42008-05-06 00:30:21 +0000700}
701
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000702void RetainSummaryManager::InitializeMethSummaries() {
703
704 assert (ScratchArgs.empty());
705
Ted Kremeneka7722b72008-05-06 21:26:51 +0000706 // Create the "init" selector. It just acts as a pass-through for the
707 // receiver.
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000708 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeReceiverAlias());
709 ObjCMethSummaries[ GetNullarySelector("init", Ctx) ] = Summ;
Ted Kremeneka7722b72008-05-06 21:26:51 +0000710
711 // The next methods are allocators.
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000712 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
Ted Kremeneka7722b72008-05-06 21:26:51 +0000713 Summ = getPersistentSummary(E);
714
715 // Create the "copy" selector.
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000716 ObjCMethSummaries[ GetNullarySelector("copy", Ctx) ] = Summ;
717
718 // Create the "mutableCopy" selector.
719 ObjCMethSummaries[ GetNullarySelector("mutableCopy", Ctx) ] = Summ;
Ted Kremenek266d8b62008-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;
729
730 // Create the "autorelease" selector.
Ted Kremenek227c5372008-05-06 02:41:27 +0000731 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : StopTracking);
Ted Kremenek266d8b62008-05-06 02:26:56 +0000732 ObjCMethSummaries[ GetNullarySelector("autorelease", Ctx) ] = Summ;
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000733}
734
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000735//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000736// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000737//===----------------------------------------------------------------------===//
738
Ted Kremeneka7338b42008-03-11 06:39:11 +0000739namespace {
740
Ted Kremenek7d421f32008-04-09 23:49:11 +0000741class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000742public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000743
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000744 enum Kind {
745 Owned = 0, // Owning reference.
746 NotOwned, // Reference is not owned by still valid (not freed).
747 Released, // Object has been released.
748 ReturnedOwned, // Returned object passes ownership to caller.
749 ReturnedNotOwned, // Return object does not pass ownership to caller.
750 ErrorUseAfterRelease, // Object used after released.
751 ErrorReleaseNotOwned, // Release of an object that was not owned.
752 ErrorLeak // A memory leak due to excessive reference counts.
753 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000754
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000755private:
756
757 Kind kind;
758 unsigned Cnt;
759
760 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
761
762 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000763
764public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000765
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000766 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000767
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000768 unsigned getCount() const { return Cnt; }
769
770 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000771
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000772 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
773
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000774 static bool isLeak(Kind k) { return k == ErrorLeak; }
775
Ted Kremenekffefc352008-04-11 22:25:11 +0000776 bool isOwned() const {
777 return getKind() == Owned;
778 }
779
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000780 bool isNotOwned() const {
781 return getKind() == NotOwned;
782 }
783
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000784 bool isReturnedOwned() const {
785 return getKind() == ReturnedOwned;
786 }
787
788 bool isReturnedNotOwned() const {
789 return getKind() == ReturnedNotOwned;
790 }
791
792 bool isNonLeakError() const {
793 Kind k = getKind();
794 return isError(k) && !isLeak(k);
795 }
796
797 // State creation: normal state.
798
Ted Kremenekc4f81022008-04-10 23:09:18 +0000799 static RefVal makeOwned(unsigned Count = 0) {
800 return RefVal(Owned, Count);
801 }
802
803 static RefVal makeNotOwned(unsigned Count = 0) {
804 return RefVal(NotOwned, Count);
805 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000806
807 static RefVal makeReturnedOwned(unsigned Count) {
808 return RefVal(ReturnedOwned, Count);
809 }
810
811 static RefVal makeReturnedNotOwned() {
812 return RefVal(ReturnedNotOwned);
813 }
814
815 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000816
Ted Kremenek9363fd92008-05-05 17:53:17 +0000817 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000818 static RefVal makeReleased() { return RefVal(Released); }
819 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
820 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000821
822 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000823
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000824 bool operator==(const RefVal& X) const {
825 return kind == X.kind && Cnt == X.Cnt;
826 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000827
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000828 void Profile(llvm::FoldingSetNodeID& ID) const {
829 ID.AddInteger((unsigned) kind);
830 ID.AddInteger(Cnt);
831 }
832
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000833 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000834};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000835
836void RefVal::print(std::ostream& Out) const {
837 switch (getKind()) {
838 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000839 case Owned: {
840 Out << "Owned";
841 unsigned cnt = getCount();
842 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000843 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000844 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000845
Ted Kremenekc4f81022008-04-10 23:09:18 +0000846 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000847 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000848 unsigned cnt = getCount();
849 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000850 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000851 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000852
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000853 case ReturnedOwned: {
854 Out << "ReturnedOwned";
855 unsigned cnt = getCount();
856 if (cnt) Out << " (+ " << cnt << ")";
857 break;
858 }
859
860 case ReturnedNotOwned: {
861 Out << "ReturnedNotOwned";
862 unsigned cnt = getCount();
863 if (cnt) Out << " (+ " << cnt << ")";
864 break;
865 }
866
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000867 case Released:
868 Out << "Released";
869 break;
870
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000871 case ErrorLeak:
872 Out << "Leaked";
873 break;
874
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000875 case ErrorUseAfterRelease:
876 Out << "Use-After-Release [ERROR]";
877 break;
878
879 case ErrorReleaseNotOwned:
880 Out << "Release of Not-Owned [ERROR]";
881 break;
882 }
883}
Ted Kremenek0d721572008-03-11 17:48:22 +0000884
Ted Kremenek9363fd92008-05-05 17:53:17 +0000885static inline unsigned GetCount(RefVal V) {
886 switch (V.getKind()) {
887 default:
888 return V.getCount();
889
890 case RefVal::Owned:
891 return V.getCount()+1;
892 }
893}
894
Ted Kremenek7aef4842008-04-16 20:40:59 +0000895//===----------------------------------------------------------------------===//
896// Transfer functions.
897//===----------------------------------------------------------------------===//
898
Ted Kremenek7d421f32008-04-09 23:49:11 +0000899class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000900public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000901 // Type definitions.
902
Ted Kremenek0d721572008-03-11 17:48:22 +0000903 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000904 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000905
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000906 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
907 ReleasesNotOwnedTy;
908
909 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
910
911 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000912 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000913
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000914 class BindingsPrinter : public ValueState::CheckerStatePrinter {
915 public:
916 virtual void PrintCheckerState(std::ostream& Out, void* State,
917 const char* nl, const char* sep);
918 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000919
920private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000921 // Instance variables.
922
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000923 RetainSummaryManager Summaries;
924 const bool EmitStandardWarnings;
925 const LangOptions& LOpts;
926 RefBFactoryTy RefBFactory;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000927
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000928 UseAfterReleasesTy UseAfterReleases;
929 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000930 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000931
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000932 BindingsPrinter Printer;
933
Ted Kremenek1feab292008-04-16 04:28:53 +0000934 Selector RetainSelector;
935 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000936 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000937
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000938public:
939
Ted Kremeneka7338b42008-03-11 06:39:11 +0000940 static RefBindings GetRefBindings(ValueState& StImpl) {
941 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
942 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000943
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000944private:
945
Ted Kremeneka7338b42008-03-11 06:39:11 +0000946 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
947 StImpl.CheckerState = B.getRoot();
948 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000949
Ted Kremeneka7338b42008-03-11 06:39:11 +0000950 RefBindings Remove(RefBindings B, SymbolID sym) {
951 return RefBFactory.Remove(B, sym);
952 }
953
Ted Kremenek0d721572008-03-11 17:48:22 +0000954 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000955 RefVal::Kind& hasErr);
956
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000957 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
958 GRStmtNodeBuilder<ValueState>& Builder,
959 Expr* NodeExpr, Expr* ErrorExpr,
960 ExplodedNode<ValueState>* Pred,
961 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000962 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000963
964 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
965 SymbolID sid, RefVal V, bool& hasLeak);
966
967 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
968 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000969
970public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000971
Ted Kremenek2f62f352008-05-02 18:01:49 +0000972 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
973 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000974 : Summaries(Ctx, gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000975 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000976 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000977 RetainSelector(GetNullarySelector("retain", Ctx)),
978 ReleaseSelector(GetNullarySelector("release", Ctx)),
979 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000980
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000981 virtual ~CFRefCount() {
982 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
983 delete I->second;
984 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000985
986 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000987
988 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
989 return &Printer;
990 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000991
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000992 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000993 const LangOptions& getLangOptions() const { return LOpts; }
994
Ted Kremeneka7338b42008-03-11 06:39:11 +0000995 // Calls.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000996
997 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
998 GRExprEngine& Eng,
999 GRStmtNodeBuilder<ValueState>& Builder,
1000 Expr* Ex,
1001 Expr* Receiver,
1002 RetainSummary* Summ,
1003 Expr** arg_beg, Expr** arg_end,
1004 ExplodedNode<ValueState>* Pred);
1005
Ted Kremeneka7338b42008-03-11 06:39:11 +00001006 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +00001007 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +00001008 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +00001009 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +00001010 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001011
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001012
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001013 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1014 GRExprEngine& Engine,
1015 GRStmtNodeBuilder<ValueState>& Builder,
1016 ObjCMessageExpr* ME,
1017 ExplodedNode<ValueState>* Pred);
1018
1019 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1020 GRExprEngine& Engine,
1021 GRStmtNodeBuilder<ValueState>& Builder,
1022 ObjCMessageExpr* ME,
1023 ExplodedNode<ValueState>* Pred);
1024
Ted Kremenek7aef4842008-04-16 20:40:59 +00001025 // Stores.
1026
1027 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
1028 GRExprEngine& Engine,
1029 GRStmtNodeBuilder<ValueState>& Builder,
1030 Expr* E, ExplodedNode<ValueState>* Pred,
1031 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +00001032 // End-of-path.
1033
1034 virtual void EvalEndPath(GRExprEngine& Engine,
1035 GREndPathNodeBuilder<ValueState>& Builder);
1036
Ted Kremenek541db372008-04-24 23:57:27 +00001037 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1038 GRExprEngine& Engine,
1039 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001040 ExplodedNode<ValueState>* Pred,
1041 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001042 ValueState* St,
1043 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001044 // Return statements.
1045
1046 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1047 GRExprEngine& Engine,
1048 GRStmtNodeBuilder<ValueState>& Builder,
1049 ReturnStmt* S,
1050 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001051
1052 // Assumptions.
1053
1054 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
1055 RVal Cond, bool Assumption, bool& isFeasible);
1056
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001057 // Error iterators.
1058
1059 typedef UseAfterReleasesTy::iterator use_after_iterator;
1060 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001061 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001062
Ted Kremenek7d421f32008-04-09 23:49:11 +00001063 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
1064 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001065
Ted Kremenek7d421f32008-04-09 23:49:11 +00001066 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
1067 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001068
1069 leaks_iterator leaks_begin() { return Leaks.begin(); }
1070 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +00001071};
1072
1073} // end anonymous namespace
1074
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001075
Ted Kremenek7d421f32008-04-09 23:49:11 +00001076
1077
Ted Kremenek3b11f7a2008-03-11 19:44:10 +00001078void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
1079 void* State, const char* nl,
1080 const char* sep) {
1081 RefBindings B((RefBindings::TreeTy*) State);
1082
1083 if (State)
1084 Out << sep << nl;
1085
1086 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1087 Out << (*I).first << " : ";
1088 (*I).second.print(Out);
1089 Out << nl;
1090 }
1091}
1092
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001093static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek455dd862008-04-11 20:23:24 +00001094 return Summ ? Summ->getArg(idx) : DoNothing;
1095}
1096
Ted Kremenek266d8b62008-05-06 02:26:56 +00001097static inline RetEffect GetRetEffect(RetainSummary* Summ) {
1098 return Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
Ted Kremenek455dd862008-04-11 20:23:24 +00001099}
1100
Ted Kremenek227c5372008-05-06 02:41:27 +00001101static inline ArgEffect GetReceiverE(RetainSummary* Summ) {
1102 return Summ ? Summ->getReceiverEffect() : DoNothing;
1103}
1104
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001105void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
1106 GRStmtNodeBuilder<ValueState>& Builder,
1107 Expr* NodeExpr, Expr* ErrorExpr,
1108 ExplodedNode<ValueState>* Pred,
1109 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001110 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +00001111 Builder.BuildSinks = true;
1112 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
1113
1114 if (!N) return;
1115
1116 switch (hasErr) {
1117 default: assert(false);
1118 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001119 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001120 break;
1121
1122 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001123 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001124 break;
1125 }
1126}
1127
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001128void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1129 GRExprEngine& Eng,
1130 GRStmtNodeBuilder<ValueState>& Builder,
1131 Expr* Ex,
1132 Expr* Receiver,
1133 RetainSummary* Summ,
1134 Expr** arg_beg, Expr** arg_end,
1135 ExplodedNode<ValueState>* Pred) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001136
Ted Kremenek827f93b2008-03-06 00:08:09 +00001137
Ted Kremeneka7338b42008-03-11 06:39:11 +00001138 // Get the state.
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001139 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +00001140 ValueState* St = Builder.GetState(Pred);
1141
Ted Kremenek227c5372008-05-06 02:41:27 +00001142
1143 // Evaluate the effect of the arguments.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001144
1145 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +00001146 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001147 unsigned idx = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001148 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001149 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001150
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001151 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001152
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001153 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001154
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001155 if (isa<lval::SymbolVal>(V)) {
1156 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +00001157 RefBindings B = GetRefBindings(StVals);
1158
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001159 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +00001160 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001161 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001162
Ted Kremenek1feab292008-04-16 04:28:53 +00001163 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001164 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001165 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001166 break;
1167 }
Ted Kremeneka7338b42008-03-11 06:39:11 +00001168 }
Ted Kremeneke4924202008-04-11 20:51:02 +00001169 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001170 else if (isa<LVal>(V)) {
1171 // Nuke all arguments passed by reference.
Ted Kremenek455dd862008-04-11 20:23:24 +00001172 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +00001173 }
Ted Kremenekbe621292008-04-22 21:39:21 +00001174 else if (isa<nonlval::LValAsInteger>(V))
1175 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001176 }
Ted Kremenek1feab292008-04-16 04:28:53 +00001177
Ted Kremenek227c5372008-05-06 02:41:27 +00001178 // Evaluate the effect on the message receiver.
1179
1180 if (!ErrorExpr && Receiver) {
1181 RVal V = StateMgr.GetRVal(St, Receiver);
1182
1183 if (isa<lval::SymbolVal>(V)) {
1184 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1185 RefBindings B = GetRefBindings(StVals);
1186
1187 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
1188 B = Update(B, Sym, T->getValue().second, GetReceiverE(Summ), hasErr);
1189 SetRefBindings(StVals, B);
1190
1191 if (hasErr) {
1192 ErrorExpr = Receiver;
1193 ErrorSym = T->getValue().first;
1194 }
1195 }
1196 }
1197 }
1198
1199 // Get the persistent state.
1200
Ted Kremenek1feab292008-04-16 04:28:53 +00001201 St = StateMgr.getPersistentState(StVals);
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001202
Ted Kremenek227c5372008-05-06 02:41:27 +00001203 // Process any errors.
1204
Ted Kremenek1feab292008-04-16 04:28:53 +00001205 if (hasErr) {
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001206 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001207 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001208 return;
Ted Kremenek0d721572008-03-11 17:48:22 +00001209 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001210
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001211 // Finally, consult the summary for the return value.
1212
Ted Kremenek266d8b62008-05-06 02:26:56 +00001213 RetEffect RE = GetRetEffect(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001214
1215 switch (RE.getKind()) {
1216 default:
1217 assert (false && "Unhandled RetEffect."); break;
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001218
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001219 case RetEffect::NoRet:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001220
Ted Kremenek455dd862008-04-11 20:23:24 +00001221 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +00001222 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1223 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +00001224
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001225 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenek455dd862008-04-11 20:23:24 +00001226 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001227 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek455dd862008-04-11 20:23:24 +00001228
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001229 RVal X = Ex->getType()->isPointerType()
1230 ? cast<RVal>(lval::SymbolVal(Sym))
1231 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenek455dd862008-04-11 20:23:24 +00001232
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001233 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek455dd862008-04-11 20:23:24 +00001234 }
1235
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001236 break;
1237
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001238 case RetEffect::Alias: {
1239 unsigned idx = RE.getValue();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001240 assert ((arg_end - arg_beg) >= 0);
1241 assert (idx < (unsigned) (arg_end - arg_beg));
1242 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1243 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001244 break;
1245 }
1246
Ted Kremenek227c5372008-05-06 02:41:27 +00001247 case RetEffect::ReceiverAlias: {
1248 assert (Receiver);
1249 RVal V = StateMgr.GetRVal(St, Receiver);
1250 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
1251 break;
1252 }
1253
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001254 case RetEffect::OwnedSymbol: {
1255 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001256 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1257
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001258 ValueState StImpl = *St;
1259 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001260 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001261
1262 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001263 Ex, lval::SymbolVal(Sym),
1264 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001265
1266 break;
1267 }
1268
1269 case RetEffect::NotOwnedSymbol: {
1270 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001271 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001272
1273 ValueState StImpl = *St;
1274 RefBindings B = GetRefBindings(StImpl);
1275 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1276
1277 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001278 Ex, lval::SymbolVal(Sym),
1279 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001280
1281 break;
1282 }
1283 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001284
1285 Builder.MakeNode(Dst, Ex, Pred, St);
1286}
1287
1288
1289void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1290 GRExprEngine& Eng,
1291 GRStmtNodeBuilder<ValueState>& Builder,
1292 CallExpr* CE, RVal L,
1293 ExplodedNode<ValueState>* Pred) {
1294
1295
1296 RetainSummary* Summ = NULL;
1297
1298 // Get the summary.
1299
1300 if (isa<lval::FuncVal>(L)) {
1301 lval::FuncVal FV = cast<lval::FuncVal>(L);
1302 FunctionDecl* FD = FV.getDecl();
1303 Summ = Summaries.getSummary(FD, Eng.getContext());
1304 }
1305
1306 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1307 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek827f93b2008-03-06 00:08:09 +00001308}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001309
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001310
1311void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1312 GRExprEngine& Eng,
1313 GRStmtNodeBuilder<ValueState>& Builder,
1314 ObjCMessageExpr* ME,
1315 ExplodedNode<ValueState>* Pred) {
1316
Ted Kremenek926abf22008-05-06 04:20:12 +00001317 RetainSummary* Summ;
Ted Kremenek33661802008-05-01 21:31:50 +00001318
Ted Kremenek926abf22008-05-06 04:20:12 +00001319 if (ME->getReceiver())
Ted Kremenekbcaff792008-05-06 15:44:25 +00001320 Summ = Summaries.getMethodSummary(ME);
Ted Kremenek1feab292008-04-16 04:28:53 +00001321 else
Ted Kremenek926abf22008-05-06 04:20:12 +00001322 Summ = Summaries.getInstanceMethodSummary(ME->getClassName(),
1323 ME->getSelector());
Ted Kremenek1feab292008-04-16 04:28:53 +00001324
Ted Kremenek926abf22008-05-06 04:20:12 +00001325 EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
1326 ME->arg_begin(), ME->arg_end(), Pred);
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001327}
Ted Kremenek926abf22008-05-06 04:20:12 +00001328
Ted Kremenek7aef4842008-04-16 20:40:59 +00001329// Stores.
1330
1331void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1332 GRExprEngine& Eng,
1333 GRStmtNodeBuilder<ValueState>& Builder,
1334 Expr* E, ExplodedNode<ValueState>* Pred,
1335 ValueState* St, RVal TargetLV, RVal Val) {
1336
1337 // Check if we have a binding for "Val" and if we are storing it to something
1338 // we don't understand or otherwise the value "escapes" the function.
1339
1340 if (!isa<lval::SymbolVal>(Val))
1341 return;
1342
1343 // Are we storing to something that causes the value to "escape"?
1344
1345 bool escapes = false;
1346
1347 if (!isa<lval::DeclVal>(TargetLV))
1348 escapes = true;
1349 else
1350 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1351
1352 if (!escapes)
1353 return;
1354
1355 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1356 RefBindings B = GetRefBindings(*St);
1357 RefBindings::TreeTy* T = B.SlimFind(Sym);
1358
1359 if (!T)
1360 return;
1361
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001362 // Nuke the binding.
1363 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001364
1365 // Hand of the remaining logic to the parent implementation.
1366 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1367}
1368
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001369
1370ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1371 SymbolID sid) {
1372 ValueState StImpl = *St;
1373 RefBindings B = GetRefBindings(StImpl);
1374 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1375 return VMgr.getPersistentState(StImpl);
1376}
1377
Ted Kremenekffefc352008-04-11 22:25:11 +00001378// End-of-path.
1379
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001380ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1381 ValueState* St, SymbolID sid,
1382 RefVal V, bool& hasLeak) {
1383
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001384 hasLeak = V.isOwned() ||
1385 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001386
1387 if (!hasLeak)
1388 return NukeBinding(VMgr, St, sid);
1389
1390 RefBindings B = GetRefBindings(*St);
1391 ValueState StImpl = *St;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001392
1393 StImpl.CheckerState =
1394 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1395
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001396 return VMgr.getPersistentState(StImpl);
1397}
1398
1399void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001400 GREndPathNodeBuilder<ValueState>& Builder) {
1401
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001402 ValueState* St = Builder.getState();
1403 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001404
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001405 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001406
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001407 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1408 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001409
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001410 St = HandleSymbolDeath(Eng.getStateManager(), St,
1411 (*I).first, (*I).second, hasLeak);
1412
1413 if (hasLeak) Leaked.push_back((*I).first);
1414 }
Ted Kremenek541db372008-04-24 23:57:27 +00001415
1416 if (Leaked.empty())
1417 return;
1418
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001419 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001420
Ted Kremenek541db372008-04-24 23:57:27 +00001421 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001422 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001423
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001424 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1425 assert (!LeaksAtNode);
1426 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001427
1428 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1429 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001430 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001431}
1432
Ted Kremenek541db372008-04-24 23:57:27 +00001433// Dead symbols.
1434
1435void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1436 GRExprEngine& Eng,
1437 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001438 ExplodedNode<ValueState>* Pred,
1439 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001440 ValueState* St,
1441 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001442
Ted Kremenek541db372008-04-24 23:57:27 +00001443 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1444
1445 RefBindings B = GetRefBindings(*St);
1446 llvm::SmallVector<SymbolID, 10> Leaked;
1447
1448 for (ValueStateManager::DeadSymbolsTy::const_iterator
1449 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1450
1451 RefBindings::TreeTy* T = B.SlimFind(*I);
1452
1453 if (!T)
1454 continue;
1455
1456 bool hasLeak = false;
1457
1458 St = HandleSymbolDeath(Eng.getStateManager(), St,
1459 *I, T->getValue().second, hasLeak);
1460
1461 if (hasLeak) Leaked.push_back(*I);
1462 }
1463
1464 if (Leaked.empty())
1465 return;
1466
1467 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1468
1469 if (!N)
1470 return;
1471
1472 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1473 assert (!LeaksAtNode);
1474 LeaksAtNode = new std::vector<SymbolID>();
1475
1476 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1477 E = Leaked.end(); I != E; ++I)
1478 (*LeaksAtNode).push_back(*I);
1479}
1480
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001481 // Return statements.
1482
1483void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1484 GRExprEngine& Eng,
1485 GRStmtNodeBuilder<ValueState>& Builder,
1486 ReturnStmt* S,
1487 ExplodedNode<ValueState>* Pred) {
1488
1489 Expr* RetE = S->getRetValue();
1490 if (!RetE) return;
1491
1492 ValueStateManager& StateMgr = Eng.getStateManager();
1493 ValueState* St = Builder.GetState(Pred);
1494 RVal V = StateMgr.GetRVal(St, RetE);
1495
1496 if (!isa<lval::SymbolVal>(V))
1497 return;
1498
1499 // Get the reference count binding (if any).
1500 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1501 RefBindings B = GetRefBindings(*St);
1502 RefBindings::TreeTy* T = B.SlimFind(Sym);
1503
1504 if (!T)
1505 return;
1506
1507 // Change the reference count.
1508
1509 RefVal X = T->getValue().second;
1510
1511 switch (X.getKind()) {
1512
1513 case RefVal::Owned: {
1514 unsigned cnt = X.getCount();
1515 X = RefVal::makeReturnedOwned(cnt);
1516 break;
1517 }
1518
1519 case RefVal::NotOwned: {
1520 unsigned cnt = X.getCount();
1521 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1522 : RefVal::makeReturnedNotOwned();
1523 break;
1524 }
1525
1526 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001527 return;
1528 }
1529
1530 // Update the binding.
1531
1532 ValueState StImpl = *St;
1533 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1534 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1535}
1536
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001537// Assumptions.
1538
1539ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1540 RVal Cond, bool Assumption,
1541 bool& isFeasible) {
1542
1543 // FIXME: We may add to the interface of EvalAssume the list of symbols
1544 // whose assumptions have changed. For now we just iterate through the
1545 // bindings and check if any of the tracked symbols are NULL. This isn't
1546 // too bad since the number of symbols we will track in practice are
1547 // probably small and EvalAssume is only called at branches and a few
1548 // other places.
1549
1550 RefBindings B = GetRefBindings(*St);
1551
1552 if (B.isEmpty())
1553 return St;
1554
1555 bool changed = false;
1556
1557 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1558
1559 // Check if the symbol is null (or equal to any constant).
1560 // If this is the case, stop tracking the symbol.
1561
1562 if (St->getSymVal(I.getKey())) {
1563 changed = true;
1564 B = RefBFactory.Remove(B, I.getKey());
1565 }
1566 }
1567
1568 if (!changed)
1569 return St;
1570
1571 ValueState StImpl = *St;
1572 StImpl.CheckerState = B.getRoot();
1573 return Eng.getStateManager().getPersistentState(StImpl);
1574}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001575
1576CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001577 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001578 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001579
Ted Kremenek0d721572008-03-11 17:48:22 +00001580 // FIXME: This dispatch can potentially be sped up by unifiying it into
1581 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001582
Ted Kremenek0d721572008-03-11 17:48:22 +00001583 switch (E) {
1584 default:
1585 assert (false && "Unhandled CFRef transition.");
1586
1587 case DoNothing:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001588 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001589 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001590 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001591 break;
1592 }
1593
Ted Kremenek0d721572008-03-11 17:48:22 +00001594 return B;
1595
Ted Kremenek227c5372008-05-06 02:41:27 +00001596 case StopTracking:
1597 return RefBFactory.Remove(B, sym);
1598
Ted Kremenek0d721572008-03-11 17:48:22 +00001599 case IncRef:
1600 switch (V.getKind()) {
1601 default:
1602 assert(false);
1603
1604 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001605 V = RefVal::makeOwned(V.getCount()+1);
1606 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001607
Ted Kremenek0d721572008-03-11 17:48:22 +00001608 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001609 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001610 break;
1611
1612 case RefVal::Released:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001613 if (isGCEnabled())
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001614 V = RefVal::makeOwned();
1615 else {
1616 V = RefVal::makeUseAfterRelease();
1617 hasErr = V.getKind();
1618 }
1619
Ted Kremenek0d721572008-03-11 17:48:22 +00001620 break;
1621 }
1622
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001623 break;
1624
Ted Kremenek0d721572008-03-11 17:48:22 +00001625 case DecRef:
1626 switch (V.getKind()) {
1627 default:
1628 assert (false);
1629
1630 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001631 unsigned Count = V.getCount();
1632 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001633 break;
1634 }
1635
Ted Kremenekc4f81022008-04-10 23:09:18 +00001636 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001637 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001638
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001639 if (Count > 0)
1640 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001641 else {
1642 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001643 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001644 }
1645
Ted Kremenek0d721572008-03-11 17:48:22 +00001646 break;
1647 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001648
1649 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001650 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001651 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001652 break;
1653 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001654
1655 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001656 }
1657
1658 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001659}
1660
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001661
1662//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001663// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001664//===----------------------------------------------------------------------===//
1665
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001666namespace {
1667
1668 //===-------------===//
1669 // Bug Descriptions. //
1670 //===-------------===//
1671
Ted Kremeneke3769852008-04-18 20:54:29 +00001672 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001673 protected:
1674 CFRefCount& TF;
1675
1676 public:
1677 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001678
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001679 CFRefCount& getTF() { return TF; }
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001680 const CFRefCount& getTF() const { return TF; }
1681
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001682 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001683 };
1684
1685 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1686 public:
1687 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1688
1689 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001690 return "Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001691 }
1692 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001693 return "Reference-counted object is used"
1694 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001695 }
1696
1697 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001698 };
1699
1700 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1701 public:
1702 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1703
1704 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001705 return "Bad Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001706 }
1707 virtual const char* getDescription() const {
1708 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001709 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001710 "The object is not owned at this point by the caller.";
1711 }
1712
1713 virtual void EmitWarnings(BugReporter& BR);
1714 };
1715
1716 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1717 public:
1718 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1719
1720 virtual const char* getName() const {
Ted Kremenekb3a44e72008-05-06 18:11:36 +00001721
1722 if (getTF().isGCEnabled())
1723 return "Memory Leak (GC)";
1724
1725 if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
1726 return "Memory Leak (Hybrid MM, non-GC)";
1727
1728 assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
1729 return "Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001730 }
1731
1732 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001733 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001734 }
1735
1736 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001737 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001738 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001739 };
1740
1741 //===---------===//
1742 // Bug Reports. //
1743 //===---------===//
1744
1745 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1746 SymbolID Sym;
1747 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001748 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001749 : RangedBugReport(D, n), Sym(sym) {}
1750
1751 virtual ~CFRefReport() {}
1752
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001753 CFRefBug& getBugType() {
1754 return (CFRefBug&) RangedBugReport::getBugType();
1755 }
1756 const CFRefBug& getBugType() const {
1757 return (const CFRefBug&) RangedBugReport::getBugType();
1758 }
1759
1760 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1761 const SourceRange*& end) {
1762
Ted Kremenek198cae02008-05-02 20:53:50 +00001763 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001764 RangedBugReport::getRanges(BR, beg, end);
1765 else {
1766 beg = 0;
1767 end = 0;
1768 }
1769 }
1770
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001771 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1772 ExplodedNode<ValueState>* N);
1773
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001774 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001775
1776 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1777 ExplodedNode<ValueState>* PrevN,
1778 ExplodedGraph<ValueState>& G,
1779 BugReporter& BR);
1780 };
1781
1782
1783} // end anonymous namespace
1784
1785void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001786 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001787 Eng.Register(new UseAfterRelease(*this));
1788 Eng.Register(new BadRelease(*this));
1789 Eng.Register(new Leak(*this));
1790}
1791
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001792
1793static const char* Msgs[] = {
1794 "Code is compiled in garbage collection only mode" // GC only
1795 " (the bug occurs with garbage collection enabled).",
1796
1797 "Code is compiled without garbage collection.", // No GC.
1798
1799 "Code is compiled for use with and without garbage collection (GC)."
1800 " The bug occurs with GC enabled.", // Hybrid, with GC.
1801
1802 "Code is compiled for use with and without garbage collection (GC)."
1803 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1804};
1805
1806std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1807 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1808
1809 switch (TF.getLangOptions().getGCMode()) {
1810 default:
1811 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001812
1813 case LangOptions::GCOnly:
1814 assert (TF.isGCEnabled());
1815 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001816
1817 case LangOptions::NonGC:
1818 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001819 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1820
1821 case LangOptions::HybridGC:
1822 if (TF.isGCEnabled())
1823 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1824 else
1825 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1826 }
1827}
1828
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001829PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1830 ExplodedNode<ValueState>* PrevN,
1831 ExplodedGraph<ValueState>& G,
1832 BugReporter& BR) {
1833
1834 // Check if the type state has changed.
1835
1836 ValueState* PrevSt = PrevN->getState();
1837 ValueState* CurrSt = N->getState();
1838
1839 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1840 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1841
Ted Kremeneka8503952008-04-18 04:55:01 +00001842 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1843 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001844
Ted Kremeneka8503952008-04-18 04:55:01 +00001845 if (!CurrT)
1846 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001847
Ted Kremeneka8503952008-04-18 04:55:01 +00001848 const char* Msg = NULL;
1849 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001850
Ted Kremeneka8503952008-04-18 04:55:01 +00001851 if (!PrevT) {
1852
Ted Kremenek9363fd92008-05-05 17:53:17 +00001853 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1854
1855 if (CurrV.isOwned()) {
1856
1857 if (isa<CallExpr>(S))
1858 Msg = "Function call returns an object with a +1 retain count"
1859 " (owning reference).";
1860 else {
1861 assert (isa<ObjCMessageExpr>(S));
1862 Msg = "Method returns an object with a +1 retain count"
1863 " (owning reference).";
1864 }
1865 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001866 else {
1867 assert (CurrV.isNotOwned());
Ted Kremenek9363fd92008-05-05 17:53:17 +00001868
1869 if (isa<CallExpr>(S))
1870 Msg = "Function call returns an object with a +0 retain count"
1871 " (non-owning reference).";
1872 else {
1873 assert (isa<ObjCMessageExpr>(S));
1874 Msg = "Method returns an object with a +0 retain count"
1875 " (non-owning reference).";
1876 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001877 }
Ted Kremenek9363fd92008-05-05 17:53:17 +00001878
Ted Kremeneka8503952008-04-18 04:55:01 +00001879 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1880 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1881
1882 if (Expr* Exp = dyn_cast<Expr>(S))
1883 P->addRange(Exp->getSourceRange());
1884
1885 return P;
1886 }
1887
1888 // Determine if the typestate has changed.
1889
1890 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1891
1892 if (PrevV == CurrV)
1893 return NULL;
1894
1895 // The typestate has changed.
1896
1897 std::ostringstream os;
1898
1899 switch (CurrV.getKind()) {
1900 case RefVal::Owned:
1901 case RefVal::NotOwned:
1902 assert (PrevV.getKind() == CurrV.getKind());
1903
1904 if (PrevV.getCount() > CurrV.getCount())
1905 os << "Reference count decremented.";
1906 else
1907 os << "Reference count incremented.";
1908
Ted Kremenek9363fd92008-05-05 17:53:17 +00001909 if (unsigned Count = GetCount(CurrV)) {
1910
1911 os << " Object has +" << Count;
Ted Kremenek752b5842008-04-18 05:32:44 +00001912
Ted Kremenek9363fd92008-05-05 17:53:17 +00001913 if (Count > 1)
1914 os << " retain counts.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001915 else
Ted Kremenek9363fd92008-05-05 17:53:17 +00001916 os << " retain count.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001917 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001918
1919 Msg = os.str().c_str();
1920
1921 break;
1922
1923 case RefVal::Released:
1924 Msg = "Object released.";
1925 break;
1926
1927 case RefVal::ReturnedOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001928 Msg = "Object returned to caller as owning reference (single retain count"
1929 " transferred to caller).";
Ted Kremeneka8503952008-04-18 04:55:01 +00001930 break;
1931
1932 case RefVal::ReturnedNotOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001933 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremeneka8503952008-04-18 04:55:01 +00001934 break;
1935
1936 default:
1937 return NULL;
1938 }
1939
1940 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1941 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1942 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1943
1944 // Add the range by scanning the children of the statement for any bindings
1945 // to Sym.
1946
1947 ValueStateManager& VSM = BR.getEngine().getStateManager();
1948
1949 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1950 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1951 RVal X = VSM.GetRVal(CurrSt, Exp);
1952
1953 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1954 if (SV->getSymbol() == Sym) {
1955 P->addRange(Exp->getSourceRange()); break;
1956 }
1957 }
1958
1959 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001960}
1961
Ted Kremenek4c479322008-05-06 23:07:13 +00001962
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001963PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremenekea794e92008-05-05 18:50:19 +00001964 ExplodedNode<ValueState>* EndN) {
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001965
1966 if (!getBugType().isLeak())
Ted Kremenekea794e92008-05-05 18:50:19 +00001967 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001968
Ted Kremenek9363fd92008-05-05 17:53:17 +00001969 typedef CFRefCount::RefBindings RefBindings;
1970
1971 // Get the retain count.
1972 unsigned long RetCount = 0;
1973
1974 {
Ted Kremenekea794e92008-05-05 18:50:19 +00001975 ValueState* St = EndN->getState();
Ted Kremenek9363fd92008-05-05 17:53:17 +00001976 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1977 RefBindings::TreeTy* T = B.SlimFind(Sym);
1978 assert (T);
1979 RetCount = GetCount(T->getValue().second);
1980 }
1981
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001982 // We are a leak. Walk up the graph to get to the first node where the
1983 // symbol appeared.
1984
Ted Kremenekea794e92008-05-05 18:50:19 +00001985 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001986 ExplodedNode<ValueState>* Last = N;
Ted Kremenekea794e92008-05-05 18:50:19 +00001987
Ted Kremenek198cae02008-05-02 20:53:50 +00001988 // Find the first node that referred to the tracked symbol. We also
1989 // try and find the first VarDecl the value was stored to.
1990
1991 VarDecl* FirstDecl = 0;
Ted Kremenekea794e92008-05-05 18:50:19 +00001992
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001993 while (N) {
1994 ValueState* St = N->getState();
1995 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001996 RefBindings::TreeTy* T = B.SlimFind(Sym);
1997
1998 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001999 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00002000
2001 VarDecl* VD = 0;
2002
2003 // Determine if there is an LVal binding to the symbol.
2004 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
2005 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
2006 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
2007 continue;
2008
2009 if (VD) { // Multiple decls map to this symbol.
2010 VD = 0;
2011 break;
2012 }
2013
2014 VD = I->first;
2015 }
2016
2017 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002018
2019 Last = N;
2020 N = N->pred_empty() ? NULL : *(N->pred_begin());
2021 }
2022
Ted Kremenekea794e92008-05-05 18:50:19 +00002023 // Get the allocate site.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002024
2025 assert (Last);
2026 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
2027
Ted Kremenekea794e92008-05-05 18:50:19 +00002028 SourceManager& SMgr = BR.getContext().getSourceManager();
2029 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002030
Ted Kremenekea794e92008-05-05 18:50:19 +00002031 // Get the leak site. We may have multiple ExplodedNodes (one with the
2032 // leak) that occur on the same line number; if the node with the leak
2033 // has any immediate predecessor nodes with the same line number, find
2034 // any transitive-successors that have a different statement and use that
2035 // line number instead. This avoids emiting a diagnostic like:
2036 //
2037 // // 'y' is leaked.
2038 // int x = foo(y);
2039 //
2040 // instead we want:
2041 //
2042 // int x = foo(y);
2043 // // 'y' is leaked.
2044
2045 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
2046 assert (S);
2047 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
2048
2049 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
2050 // it occur on the same line?
Ted Kremenek4c479322008-05-06 23:07:13 +00002051
2052 PathDiagnosticPiece::DisplayHint Hint = PathDiagnosticPiece::Above;
Ted Kremenekea794e92008-05-05 18:50:19 +00002053
2054 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
Ted Kremenek4c479322008-05-06 23:07:13 +00002055 ExplodedNode<ValueState> *Pred = *(EndN->pred_begin());
2056 ProgramPoint PredPos = Pred->getLocation();
Ted Kremenekea794e92008-05-05 18:50:19 +00002057
Ted Kremenek4c479322008-05-06 23:07:13 +00002058 if (PostStmt* PredPS = dyn_cast<PostStmt>(&PredPos)) {
Ted Kremenekea794e92008-05-05 18:50:19 +00002059
Ted Kremenek4c479322008-05-06 23:07:13 +00002060 Stmt* SPred = PredPS->getStmt();
Ted Kremenekea794e92008-05-05 18:50:19 +00002061
2062 // Predecessor at same line?
Ted Kremenek4c479322008-05-06 23:07:13 +00002063 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine) {
2064 Hint = PathDiagnosticPiece::Below;
2065 S = SPred;
2066 }
Ted Kremenekea794e92008-05-05 18:50:19 +00002067 }
Ted Kremenekea794e92008-05-05 18:50:19 +00002068
2069 // Generate the diagnostic.
Ted Kremenek4c479322008-05-06 23:07:13 +00002070 FullSourceLoc L( S->getLocStart(), SMgr);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002071 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00002072
Ted Kremenekea794e92008-05-05 18:50:19 +00002073 os << "Object allocated on line " << AllocLine;
Ted Kremenek198cae02008-05-02 20:53:50 +00002074
2075 if (FirstDecl)
2076 os << " and stored into '" << FirstDecl->getName() << '\'';
2077
Ted Kremenek9363fd92008-05-05 17:53:17 +00002078 os << " is no longer referenced after this point and has a retain count of +"
2079 << RetCount << " (object leaked).";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002080
Ted Kremenek4c479322008-05-06 23:07:13 +00002081 return new PathDiagnosticPiece(L, os.str(), Hint);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002082}
2083
Ted Kremenek7d421f32008-04-09 23:49:11 +00002084void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002085
Ted Kremenek7d421f32008-04-09 23:49:11 +00002086 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2087 E = TF.use_after_end(); I != E; ++I) {
2088
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002089 CFRefReport report(*this, I->first, I->second.second);
2090 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00002091 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002092 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00002093}
2094
2095void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002096
Ted Kremenek7d421f32008-04-09 23:49:11 +00002097 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2098 E = TF.bad_release_end(); I != E; ++I) {
2099
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002100 CFRefReport report(*this, I->first, I->second.second);
2101 report.addRange(I->second.first->getSourceRange());
2102 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00002103 }
2104}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002105
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002106void Leak::EmitWarnings(BugReporter& BR) {
2107
2108 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2109 E = TF.leaks_end(); I != E; ++I) {
2110
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002111 std::vector<SymbolID>& SymV = *(I->second);
2112 unsigned n = SymV.size();
2113
2114 for (unsigned i = 0; i < n; ++i) {
2115 CFRefReport report(*this, I->first, SymV[i]);
2116 BR.EmitWarning(report);
2117 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002118 }
2119}
2120
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00002121void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2122 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2123 I!=E; ++I)
2124 Nodes.push_back(I->first);
2125}
2126
Ted Kremeneka7338b42008-03-11 06:39:11 +00002127//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00002128// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00002129//===----------------------------------------------------------------------===//
2130
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002131GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00002132 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002133 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00002134 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00002135}