blob: e247a60585f77a87713734cc0b7f961939009ced [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 Kremenek10fe66d2008-04-09 01:10:13 +000026#include "llvm/Support/Compiler.h"
Ted Kremenek3b11f7a2008-03-11 19:44:10 +000027#include <ostream>
Ted Kremeneka8503952008-04-18 04:55:01 +000028#include <sstream>
Ted Kremenek827f93b2008-03-06 00:08:09 +000029
30using namespace clang;
31
Ted Kremenek7d421f32008-04-09 23:49:11 +000032//===----------------------------------------------------------------------===//
Ted Kremenekd9ccf682008-04-17 18:12:53 +000033// Utility functions.
34//===----------------------------------------------------------------------===//
35
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +000036static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenekd9ccf682008-04-17 18:12:53 +000037 IdentifierInfo* II = &Ctx.Idents.get(name);
38 return Ctx.Selectors.getSelector(0, &II);
39}
40
Ted Kremenek0e344d42008-05-06 00:30:21 +000041static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
42 IdentifierInfo* II = &Ctx.Idents.get(name);
43 return Ctx.Selectors.getSelector(1, &II);
44}
45
Ted Kremenekd9ccf682008-04-17 18:12:53 +000046//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +000047// Symbolic Evaluation of Reference Counting Logic
48//===----------------------------------------------------------------------===//
49
Ted Kremeneka7338b42008-03-11 06:39:11 +000050namespace {
51 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenekae855d42008-04-24 17:22:33 +000052 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremeneka7338b42008-03-11 06:39:11 +000053}
Ted Kremenek827f93b2008-03-06 00:08:09 +000054
Ted Kremeneka7338b42008-03-11 06:39:11 +000055namespace llvm {
56 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +000057 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenekae855d42008-04-24 17:22:33 +000058 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
59 ID.AddInteger(I->first);
60 ID.AddInteger((unsigned) I->second);
61 }
Ted Kremeneka4c74292008-04-10 22:58:08 +000062 }
Ted Kremeneka7338b42008-03-11 06:39:11 +000063 };
64} // end llvm namespace
65
66namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +000067
Ted Kremeneka7338b42008-03-11 06:39:11 +000068class RetEffect {
69public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000070 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
Ted Kremeneka8c3c432008-05-05 22:11:16 +000071 NotOwnedSymbol = 0x3, ReceiverAlias=0x4 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000072
73private:
74 unsigned Data;
Ted Kremeneka8c3c432008-05-05 22:11:16 +000075 RetEffect(Kind k, unsigned D) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000076
Ted Kremeneka7338b42008-03-11 06:39:11 +000077public:
78
Ted Kremeneka8c3c432008-05-05 22:11:16 +000079 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremeneka7338b42008-03-11 06:39:11 +000080
81 unsigned getValue() const {
82 assert(getKind() == Alias);
Ted Kremeneka8c3c432008-05-05 22:11:16 +000083 return Data >> 3;
Ted Kremeneka7338b42008-03-11 06:39:11 +000084 }
Ted Kremenekffefc352008-04-11 22:25:11 +000085
Ted Kremeneka7338b42008-03-11 06:39:11 +000086 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000087
Ted Kremeneka8c3c432008-05-05 22:11:16 +000088 static RetEffect MakeReceiverAlias() { return RetEffect(ReceiverAlias, 0); }
89
Ted Kremeneka7338b42008-03-11 06:39:11 +000090 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000091
Ted Kremeneka7338b42008-03-11 06:39:11 +000092 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
93
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000094 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
95
Ted Kremeneka7338b42008-03-11 06:39:11 +000096 operator Kind() const { return getKind(); }
97
98 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
99};
100
101
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000102class RetainSummary : public llvm::FoldingSetNode {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000103 ArgEffects* Args;
104 RetEffect Ret;
105public:
106
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000107 RetainSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000108
109 unsigned getNumArgs() const { return Args->size(); }
110
Ted Kremenek0d721572008-03-11 17:48:22 +0000111 ArgEffect getArg(unsigned idx) const {
Ted Kremenekae855d42008-04-24 17:22:33 +0000112 if (!Args)
113 return DoNothing;
114
115 // If Args is present, it is likely to contain only 1 element.
116 // Just do a linear search. Do it from the back because functions with
117 // large numbers of arguments will be tail heavy with respect to which
118 // argument they actually modify with respect to the reference count.
119
120 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
121 I!=E; ++I) {
122
123 if (idx > I->first)
124 return DoNothing;
125
126 if (idx == I->first)
127 return I->second;
128 }
129
130 return DoNothing;
Ted Kremenek0d721572008-03-11 17:48:22 +0000131 }
132
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000133 RetEffect getRet() const {
134 return Ret;
135 }
136
Ted Kremeneka7338b42008-03-11 06:39:11 +0000137 typedef ArgEffects::const_iterator arg_iterator;
138
139 arg_iterator begin_args() const { return Args->begin(); }
140 arg_iterator end_args() const { return Args->end(); }
141
142 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
143 ID.AddPointer(A);
144 ID.Add(R);
145 }
146
147 void Profile(llvm::FoldingSetNodeID& ID) const {
148 Profile(ID, Args, Ret);
149 }
150};
151
152
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000153class RetainSummaryManager {
154
155 //==-----------------------------------------------------------------==//
156 // Typedefs.
157 //==-----------------------------------------------------------------==//
Ted Kremeneka7338b42008-03-11 06:39:11 +0000158
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000159 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
160 ArgEffectsSetTy;
161
162 typedef llvm::FoldingSet<RetainSummary>
163 SummarySetTy;
164
165 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
166 FuncSummariesTy;
167
168 typedef llvm::DenseMap<Selector, RetainSummary*>
Ted Kremenek0e344d42008-05-06 00:30:21 +0000169 ObjCMethSummariesTy;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000170
171 //==-----------------------------------------------------------------==//
172 // Data.
173 //==-----------------------------------------------------------------==//
174
175 // Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000176 ASTContext& Ctx;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000177
178 // GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000179 const bool GCEnabled;
180
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000181 // SummarySet - A FoldingSet of uniqued summaries.
Ted Kremeneka4c74292008-04-10 22:58:08 +0000182 SummarySetTy SummarySet;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000183
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000184 // FuncSummaries - A map from FunctionDecls to summaries.
185 FuncSummariesTy FuncSummaries;
186
Ted Kremenek0e344d42008-05-06 00:30:21 +0000187 // ObjCInstMethSummaries - A map from selectors (for instance methods)
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000188 // to summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000189 ObjCMethSummariesTy ObjCInstMethSummaries;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000190
Ted Kremenek0e344d42008-05-06 00:30:21 +0000191 // ObjCMethSummaries - A map from selectors to summaries.
192 ObjCMethSummariesTy ObjCMethSummaries;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000193
194 // ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
195 ArgEffectsSetTy ArgEffectsSet;
196
197 // BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
198 // and all other data used by the checker.
199 llvm::BumpPtrAllocator BPAlloc;
200
201 // ScratchArgs - A holding buffer for construct ArgEffects.
202 ArgEffects ScratchArgs;
203
204 //==-----------------------------------------------------------------==//
205 // Methods.
206 //==-----------------------------------------------------------------==//
207
208 // getArgEffects - Returns a persistent ArgEffects object based on the
209 // data in ScratchArgs.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000210 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000211
Ted Kremenek562c1302008-05-05 16:51:50 +0000212 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000213 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000214
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000215 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
216 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000217
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000218 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
219 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000220
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000221 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenek0e344d42008-05-06 00:30:21 +0000222
223 RetainSummary* getPersistentSummary(RetEffect RE) {
224 return getPersistentSummary(getArgEffects(), RE);
225 }
Ted Kremenek42ea0322008-05-05 23:55:01 +0000226
227 RetainSummary* getInstanceMethodSummary(Selector S);
228
229 RetainSummary* getMethodSummary(Selector S);
230 RetainSummary* getInitMethodSummary(Selector S);
231
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000232 void InitializeInstMethSummaries();
233 void InitializeMethSummaries();
Ted Kremenek0e344d42008-05-06 00:30:21 +0000234
Ted Kremeneka7338b42008-03-11 06:39:11 +0000235public:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000236
237 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek0e344d42008-05-06 00:30:21 +0000238 : Ctx(ctx), GCEnabled(gcenabled) {
239
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000240 InitializeInstMethSummaries();
241 InitializeMethSummaries();
Ted Kremenek0e344d42008-05-06 00:30:21 +0000242 }
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000243
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000244 ~RetainSummaryManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000245
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000246 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
247
248 bool isGCEnabled() const { return GCEnabled; }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000249};
250
251} // end anonymous namespace
252
253//===----------------------------------------------------------------------===//
254// Implementation of checker data structures.
255//===----------------------------------------------------------------------===//
256
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000257RetainSummaryManager::~RetainSummaryManager() {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000258
259 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
260 // mitigating the need to do explicit cleanup of the
261 // Argument-Effect summaries.
262
Ted Kremenek42ea0322008-05-05 23:55:01 +0000263 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
264 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremeneka7338b42008-03-11 06:39:11 +0000265 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000266}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000267
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000268ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000269
Ted Kremenekae855d42008-04-24 17:22:33 +0000270 if (ScratchArgs.empty())
271 return NULL;
272
273 // Compute a profile for a non-empty ScratchArgs.
274
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000275 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000276
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000277 profile.Add(ScratchArgs);
278 void* InsertPos;
279
Ted Kremenekae855d42008-04-24 17:22:33 +0000280 // Look up the uniqued copy, or create a new one.
281
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000282 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000283 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000284
Ted Kremenekae855d42008-04-24 17:22:33 +0000285 if (E) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000286 ScratchArgs.clear();
287 return &E->getValue();
288 }
289
290 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
291 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
292
293 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000294 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000295
296 ScratchArgs.clear();
297 return &E->getValue();
298}
299
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000300RetainSummary* RetainSummaryManager::getPersistentSummary(ArgEffects* AE,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000301 RetEffect RE) {
302
Ted Kremenekae855d42008-04-24 17:22:33 +0000303 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000304 llvm::FoldingSetNodeID profile;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000305 RetainSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000306
Ted Kremenekae855d42008-04-24 17:22:33 +0000307 // Look up the uniqued summary, or create one if it doesn't exist.
308 void* InsertPos;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000309 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000310
311 if (Summ)
312 return Summ;
313
Ted Kremenekae855d42008-04-24 17:22:33 +0000314 // Create the summary and return it.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000315 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
316 new (Summ) RetainSummary(AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000317 SummarySet.InsertNode(Summ, InsertPos);
318
319 return Summ;
320}
321
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000322//===----------------------------------------------------------------------===//
323// Summary creation for functions (largely uses of Core Foundation).
324//===----------------------------------------------------------------------===//
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000325
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000326RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000327 ASTContext& Ctx) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000328
329 SourceLocation Loc = FD->getLocation();
330
331 if (!Loc.isFileID())
332 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000333
Ted Kremenekae855d42008-04-24 17:22:33 +0000334 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000335 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenekae855d42008-04-24 17:22:33 +0000336
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000337 if (I != FuncSummaries.end())
Ted Kremenekae855d42008-04-24 17:22:33 +0000338 return I->second;
339
340 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000341 const char* FName = FD->getIdentifier()->getName();
342
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000343 RetainSummary *S = 0;
Ted Kremenek562c1302008-05-05 16:51:50 +0000344
345 if (FName[0] == 'C' && FName[1] == 'F')
346 S = getCFSummary(FD, FName);
347 else if (FName[0] == 'N' && FName[1] == 'S')
348 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000349
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000350 FuncSummaries[FD] = S;
Ted Kremenek562c1302008-05-05 16:51:50 +0000351 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000352}
353
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000354RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000355 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000356 FName += 2;
357
358 if (strcmp(FName, "MakeCollectable") == 0)
359 return getUnarySummary(FD, cfmakecollectable);
360
361 return 0;
362}
363
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000364RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000365 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000366
367 FName += 2;
368
369 if (strcmp(FName, "Retain") == 0)
370 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000371
Ted Kremenek562c1302008-05-05 16:51:50 +0000372 if (strcmp(FName, "Release") == 0)
373 return getUnarySummary(FD, cfrelease);
374
375 if (strcmp(FName, "MakeCollectable") == 0)
376 return getUnarySummary(FD, cfmakecollectable);
377
378 if (strstr(FName, "Create") || strstr(FName, "Copy"))
379 return getCFSummaryCreateRule(FD);
380
381 if (strstr(FName, "Get"))
382 return getCFSummaryGetRule(FD);
383
384 return 0;
385}
386
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000387RetainSummary*
388RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000389
390 FunctionTypeProto* FT =
391 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
392
Ted Kremenek562c1302008-05-05 16:51:50 +0000393 if (FT) {
394
395 if (FT->getNumArgs() != 1)
396 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000397
Ted Kremenek562c1302008-05-05 16:51:50 +0000398 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
399
400 if (!ArgT)
401 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000402
Ted Kremenek562c1302008-05-05 16:51:50 +0000403 if (!ArgT->isPointerType())
404 return NULL;
405 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000406
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000407 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000408
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000409 switch (func) {
410 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000411 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek0e344d42008-05-06 00:30:21 +0000412 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000413 }
414
415 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000416 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek0e344d42008-05-06 00:30:21 +0000417 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000418 }
419
420 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000421 if (GCEnabled)
422 ScratchArgs.push_back(std::make_pair(0, DecRef));
423
Ted Kremenek0e344d42008-05-06 00:30:21 +0000424 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000425 }
426
427 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000428 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000429 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000430}
431
432static bool isCFRefType(QualType T) {
433
434 if (!T->isPointerType())
435 return false;
436
437 // Check the typedef for the name "CF" and the substring "Ref".
438
439 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
440
441 if (!TD)
442 return false;
443
444 const char* TDName = TD->getDecl()->getIdentifier()->getName();
445 assert (TDName);
446
447 if (TDName[0] != 'C' || TDName[1] != 'F')
448 return false;
449
450 if (strstr(TDName, "Ref") == 0)
451 return false;
452
453 return true;
454}
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000455
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000456RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000457
Ted Kremenek562c1302008-05-05 16:51:50 +0000458 FunctionTypeProto* FT =
459 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
460
461 if (FT && !isCFRefType(FT->getResultType()))
462 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000463
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000464 // FIXME: Add special-cases for functions that retain/release. For now
465 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000466
467 assert (ScratchArgs.empty());
Ted Kremenek0e344d42008-05-06 00:30:21 +0000468 return getPersistentSummary(RetEffect::MakeOwned());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000469}
470
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000471RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000472
Ted Kremenek562c1302008-05-05 16:51:50 +0000473 FunctionTypeProto* FT =
474 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000475
Ted Kremenek562c1302008-05-05 16:51:50 +0000476 if (FT) {
477 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000478
Ted Kremenek562c1302008-05-05 16:51:50 +0000479 // FIXME: For now we assume that all pointer types returned are referenced
480 // counted. Since this is the "Get" rule, we assume non-ownership, which
481 // works fine for things that are not reference counted. We do this because
482 // some generic data structures return "void*". We need something better
483 // in the future.
484
485 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
486 return 0;
487 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000488
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000489 // FIXME: Add special-cases for functions that retain/release. For now
490 // just handle the default case.
491
Ted Kremenekae855d42008-04-24 17:22:33 +0000492 assert (ScratchArgs.empty());
Ted Kremenek0e344d42008-05-06 00:30:21 +0000493 return getPersistentSummary(RetEffect::MakeNotOwned());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000494}
495
Ted Kremeneka7338b42008-03-11 06:39:11 +0000496//===----------------------------------------------------------------------===//
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000497// Summary creation for Selectors.
498//===----------------------------------------------------------------------===//
499
Ted Kremenek42ea0322008-05-05 23:55:01 +0000500RetainSummary* RetainSummaryManager::getInitMethodSummary(Selector S) {
501 assert(ScratchArgs.empty());
502
503 RetainSummary* Summ =
Ted Kremenek0e344d42008-05-06 00:30:21 +0000504 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek42ea0322008-05-05 23:55:01 +0000505
Ted Kremenek0e344d42008-05-06 00:30:21 +0000506 ObjCMethSummaries[S] = Summ;
Ted Kremenek42ea0322008-05-05 23:55:01 +0000507 return Summ;
508}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000509
Ted Kremenek42ea0322008-05-05 23:55:01 +0000510RetainSummary* RetainSummaryManager::getMethodSummary(Selector S) {
511
512 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000513 ObjCMethSummariesTy::iterator I = ObjCMethSummaries.find(S);
Ted Kremenek42ea0322008-05-05 23:55:01 +0000514
Ted Kremenek0e344d42008-05-06 00:30:21 +0000515 if (I != ObjCMethSummaries.end())
Ted Kremenek42ea0322008-05-05 23:55:01 +0000516 return I->second;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000517
Ted Kremenek42ea0322008-05-05 23:55:01 +0000518 // "initXXX": pass-through for receiver.
519
520 const char* s = S.getIdentifierInfoForSlot(0)->getName();
521
522 if (s[0] == 'i' && s[10] == 'n' && s[2] == 'i' && s[3] == 't')
523 return getInitMethodSummary(S);
524
525 return 0;
526}
527
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000528void RetainSummaryManager::InitializeInstMethSummaries() {
Ted Kremenek0e344d42008-05-06 00:30:21 +0000529
530 assert (ScratchArgs.empty());
531
532 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
533 RetainSummary* Summ = getPersistentSummary(E);
534
535 // Create the "alloc" selector.
536 ObjCInstMethSummaries[ GetNullarySelector("alloc", Ctx) ] = Summ;
537
538 // Create the "new" selector.
539 ObjCInstMethSummaries[ GetNullarySelector("new", Ctx) ] = Summ;
540
541 // Create the "allocWithZone:" selector.
542 ObjCInstMethSummaries[ GetUnarySelector("allocWithZone", Ctx) ] = Summ;
543
544 // Create the "copyWithZone:" selector.
545 ObjCInstMethSummaries[ GetUnarySelector("copyWithZone", Ctx) ] = Summ;
546
547 // Create the "mutableCopyWithZone:" selector.
548 ObjCInstMethSummaries[ GetUnarySelector("mutableCopyWithZone", Ctx) ] = Summ;
549}
550
Ted Kremenek83b2cde2008-05-06 00:38:54 +0000551void RetainSummaryManager::InitializeMethSummaries() {
552
553 assert (ScratchArgs.empty());
554
555 // Create the "init" selector.
556 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeReceiverAlias());
557 ObjCMethSummaries[ GetNullarySelector("init", Ctx) ] = Summ;
558
559 // Create the "copy" selector.
560 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
561 Summ = getPersistentSummary(E);
562 ObjCMethSummaries[ GetNullarySelector("copy", Ctx) ] = Summ;
563
564 // Create the "mutableCopy" selector.
565 ObjCMethSummaries[ GetNullarySelector("mutableCopy", Ctx) ] = Summ;
566}
567
Ted Kremenek0e344d42008-05-06 00:30:21 +0000568
Ted Kremenek42ea0322008-05-05 23:55:01 +0000569RetainSummary* RetainSummaryManager::getInstanceMethodSummary(Selector S) {
570
571 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000572 ObjCMethSummariesTy::iterator I = ObjCInstMethSummaries.find(S);
Ted Kremenek42ea0322008-05-05 23:55:01 +0000573
Ted Kremenek0e344d42008-05-06 00:30:21 +0000574 if (I != ObjCInstMethSummaries.end())
Ted Kremenek42ea0322008-05-05 23:55:01 +0000575 return I->second;
576
577 return 0;
578}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000579
580//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000581// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000582//===----------------------------------------------------------------------===//
583
Ted Kremeneka7338b42008-03-11 06:39:11 +0000584namespace {
585
Ted Kremenek7d421f32008-04-09 23:49:11 +0000586class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000587public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000588
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000589 enum Kind {
590 Owned = 0, // Owning reference.
591 NotOwned, // Reference is not owned by still valid (not freed).
592 Released, // Object has been released.
593 ReturnedOwned, // Returned object passes ownership to caller.
594 ReturnedNotOwned, // Return object does not pass ownership to caller.
595 ErrorUseAfterRelease, // Object used after released.
596 ErrorReleaseNotOwned, // Release of an object that was not owned.
597 ErrorLeak // A memory leak due to excessive reference counts.
598 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000599
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000600private:
601
602 Kind kind;
603 unsigned Cnt;
604
605 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
606
607 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000608
609public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000610
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000611 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000612
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000613 unsigned getCount() const { return Cnt; }
614
615 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000616
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000617 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
618
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000619 static bool isLeak(Kind k) { return k == ErrorLeak; }
620
Ted Kremenekffefc352008-04-11 22:25:11 +0000621 bool isOwned() const {
622 return getKind() == Owned;
623 }
624
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000625 bool isNotOwned() const {
626 return getKind() == NotOwned;
627 }
628
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000629 bool isReturnedOwned() const {
630 return getKind() == ReturnedOwned;
631 }
632
633 bool isReturnedNotOwned() const {
634 return getKind() == ReturnedNotOwned;
635 }
636
637 bool isNonLeakError() const {
638 Kind k = getKind();
639 return isError(k) && !isLeak(k);
640 }
641
642 // State creation: normal state.
643
Ted Kremenekc4f81022008-04-10 23:09:18 +0000644 static RefVal makeOwned(unsigned Count = 0) {
645 return RefVal(Owned, Count);
646 }
647
648 static RefVal makeNotOwned(unsigned Count = 0) {
649 return RefVal(NotOwned, Count);
650 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000651
652 static RefVal makeReturnedOwned(unsigned Count) {
653 return RefVal(ReturnedOwned, Count);
654 }
655
656 static RefVal makeReturnedNotOwned() {
657 return RefVal(ReturnedNotOwned);
658 }
659
660 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000661
Ted Kremenek9363fd92008-05-05 17:53:17 +0000662 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000663 static RefVal makeReleased() { return RefVal(Released); }
664 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
665 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000666
667 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000668
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000669 bool operator==(const RefVal& X) const {
670 return kind == X.kind && Cnt == X.Cnt;
671 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000672
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000673 void Profile(llvm::FoldingSetNodeID& ID) const {
674 ID.AddInteger((unsigned) kind);
675 ID.AddInteger(Cnt);
676 }
677
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000678 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000679};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000680
681void RefVal::print(std::ostream& Out) const {
682 switch (getKind()) {
683 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000684 case Owned: {
685 Out << "Owned";
686 unsigned cnt = getCount();
687 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000688 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000689 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000690
Ted Kremenekc4f81022008-04-10 23:09:18 +0000691 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000692 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000693 unsigned cnt = getCount();
694 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000695 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000696 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000697
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000698 case ReturnedOwned: {
699 Out << "ReturnedOwned";
700 unsigned cnt = getCount();
701 if (cnt) Out << " (+ " << cnt << ")";
702 break;
703 }
704
705 case ReturnedNotOwned: {
706 Out << "ReturnedNotOwned";
707 unsigned cnt = getCount();
708 if (cnt) Out << " (+ " << cnt << ")";
709 break;
710 }
711
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000712 case Released:
713 Out << "Released";
714 break;
715
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000716 case ErrorLeak:
717 Out << "Leaked";
718 break;
719
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000720 case ErrorUseAfterRelease:
721 Out << "Use-After-Release [ERROR]";
722 break;
723
724 case ErrorReleaseNotOwned:
725 Out << "Release of Not-Owned [ERROR]";
726 break;
727 }
728}
Ted Kremenek0d721572008-03-11 17:48:22 +0000729
Ted Kremenek9363fd92008-05-05 17:53:17 +0000730static inline unsigned GetCount(RefVal V) {
731 switch (V.getKind()) {
732 default:
733 return V.getCount();
734
735 case RefVal::Owned:
736 return V.getCount()+1;
737 }
738}
739
Ted Kremenek7aef4842008-04-16 20:40:59 +0000740//===----------------------------------------------------------------------===//
741// Transfer functions.
742//===----------------------------------------------------------------------===//
743
Ted Kremenek7d421f32008-04-09 23:49:11 +0000744class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000745public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000746 // Type definitions.
747
Ted Kremenek0d721572008-03-11 17:48:22 +0000748 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000749 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000750
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000751 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
752 ReleasesNotOwnedTy;
753
754 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
755
756 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000757 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000758
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000759 class BindingsPrinter : public ValueState::CheckerStatePrinter {
760 public:
761 virtual void PrintCheckerState(std::ostream& Out, void* State,
762 const char* nl, const char* sep);
763 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000764
765private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000766 // Instance variables.
767
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000768 RetainSummaryManager Summaries;
769 const bool EmitStandardWarnings;
770 const LangOptions& LOpts;
771 RefBFactoryTy RefBFactory;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000772
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000773 UseAfterReleasesTy UseAfterReleases;
774 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000775 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000776
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000777 BindingsPrinter Printer;
778
Ted Kremenek1feab292008-04-16 04:28:53 +0000779 Selector RetainSelector;
780 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000781 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000782
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000783public:
784
Ted Kremeneka7338b42008-03-11 06:39:11 +0000785 static RefBindings GetRefBindings(ValueState& StImpl) {
786 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
787 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000788
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000789private:
790
Ted Kremeneka7338b42008-03-11 06:39:11 +0000791 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
792 StImpl.CheckerState = B.getRoot();
793 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000794
Ted Kremeneka7338b42008-03-11 06:39:11 +0000795 RefBindings Remove(RefBindings B, SymbolID sym) {
796 return RefBFactory.Remove(B, sym);
797 }
798
Ted Kremenek0d721572008-03-11 17:48:22 +0000799 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000800 RefVal::Kind& hasErr);
801
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000802 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
803 GRStmtNodeBuilder<ValueState>& Builder,
804 Expr* NodeExpr, Expr* ErrorExpr,
805 ExplodedNode<ValueState>* Pred,
806 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000807 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000808
809 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
810 SymbolID sid, RefVal V, bool& hasLeak);
811
812 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
813 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000814
815public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000816
Ted Kremenek2f62f352008-05-02 18:01:49 +0000817 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
818 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000819 : Summaries(Ctx, gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000820 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000821 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000822 RetainSelector(GetNullarySelector("retain", Ctx)),
823 ReleaseSelector(GetNullarySelector("release", Ctx)),
824 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000825
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000826 virtual ~CFRefCount() {
827 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
828 delete I->second;
829 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000830
831 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000832
833 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
834 return &Printer;
835 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000836
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000837 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000838 const LangOptions& getLangOptions() const { return LOpts; }
839
Ted Kremeneka7338b42008-03-11 06:39:11 +0000840 // Calls.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000841
842 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
843 GRExprEngine& Eng,
844 GRStmtNodeBuilder<ValueState>& Builder,
845 Expr* Ex,
846 Expr* Receiver,
847 RetainSummary* Summ,
848 Expr** arg_beg, Expr** arg_end,
849 ExplodedNode<ValueState>* Pred);
850
Ted Kremeneka7338b42008-03-11 06:39:11 +0000851 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000852 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000853 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000854 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000855 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000856
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000857
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000858 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
859 GRExprEngine& Engine,
860 GRStmtNodeBuilder<ValueState>& Builder,
861 ObjCMessageExpr* ME,
862 ExplodedNode<ValueState>* Pred);
863
864 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
865 GRExprEngine& Engine,
866 GRStmtNodeBuilder<ValueState>& Builder,
867 ObjCMessageExpr* ME,
868 ExplodedNode<ValueState>* Pred);
869
Ted Kremenek7aef4842008-04-16 20:40:59 +0000870 // Stores.
871
872 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
873 GRExprEngine& Engine,
874 GRStmtNodeBuilder<ValueState>& Builder,
875 Expr* E, ExplodedNode<ValueState>* Pred,
876 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000877 // End-of-path.
878
879 virtual void EvalEndPath(GRExprEngine& Engine,
880 GREndPathNodeBuilder<ValueState>& Builder);
881
Ted Kremenek541db372008-04-24 23:57:27 +0000882 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
883 GRExprEngine& Engine,
884 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000885 ExplodedNode<ValueState>* Pred,
886 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000887 ValueState* St,
888 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000889 // Return statements.
890
891 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
892 GRExprEngine& Engine,
893 GRStmtNodeBuilder<ValueState>& Builder,
894 ReturnStmt* S,
895 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +0000896
897 // Assumptions.
898
899 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
900 RVal Cond, bool Assumption, bool& isFeasible);
901
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000902 // Error iterators.
903
904 typedef UseAfterReleasesTy::iterator use_after_iterator;
905 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000906 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000907
Ted Kremenek7d421f32008-04-09 23:49:11 +0000908 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
909 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000910
Ted Kremenek7d421f32008-04-09 23:49:11 +0000911 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
912 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000913
914 leaks_iterator leaks_begin() { return Leaks.begin(); }
915 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000916};
917
918} // end anonymous namespace
919
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000920
Ted Kremenek7d421f32008-04-09 23:49:11 +0000921
922
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000923void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
924 void* State, const char* nl,
925 const char* sep) {
926 RefBindings B((RefBindings::TreeTy*) State);
927
928 if (State)
929 Out << sep << nl;
930
931 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
932 Out << (*I).first << " : ";
933 (*I).second.print(Out);
934 Out << nl;
935 }
936}
937
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000938static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000939 return Summ ? Summ->getArg(idx) : DoNothing;
940}
941
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000942static inline RetEffect GetRetE(RetainSummary* Summ) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000943 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
944}
945
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000946void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
947 GRStmtNodeBuilder<ValueState>& Builder,
948 Expr* NodeExpr, Expr* ErrorExpr,
949 ExplodedNode<ValueState>* Pred,
950 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000951 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000952 Builder.BuildSinks = true;
953 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
954
955 if (!N) return;
956
957 switch (hasErr) {
958 default: assert(false);
959 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000960 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000961 break;
962
963 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000964 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000965 break;
966 }
967}
968
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000969void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
970 GRExprEngine& Eng,
971 GRStmtNodeBuilder<ValueState>& Builder,
972 Expr* Ex,
973 Expr* Receiver,
974 RetainSummary* Summ,
975 Expr** arg_beg, Expr** arg_end,
976 ExplodedNode<ValueState>* Pred) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000977
Ted Kremenek827f93b2008-03-06 00:08:09 +0000978
Ted Kremeneka7338b42008-03-11 06:39:11 +0000979 // Get the state.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000980 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000981 ValueState* St = Builder.GetState(Pred);
982
983 // Evaluate the effects of the call.
984
985 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000986 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000987
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000988 // This function has a summary. Evaluate the effect of the arguments.
989
990 unsigned idx = 0;
991
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000992 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000993 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000994
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000995 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000996
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000997 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000998
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000999 if (isa<lval::SymbolVal>(V)) {
1000 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +00001001 RefBindings B = GetRefBindings(StVals);
1002
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001003 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +00001004 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001005 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001006
Ted Kremenek1feab292008-04-16 04:28:53 +00001007 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001008 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001009 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001010 break;
1011 }
Ted Kremeneka7338b42008-03-11 06:39:11 +00001012 }
Ted Kremeneke4924202008-04-11 20:51:02 +00001013 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001014 else if (isa<LVal>(V)) {
1015 // Nuke all arguments passed by reference.
Ted Kremenek455dd862008-04-11 20:23:24 +00001016 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +00001017 }
Ted Kremenekbe621292008-04-22 21:39:21 +00001018 else if (isa<nonlval::LValAsInteger>(V))
1019 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001020 }
Ted Kremenek1feab292008-04-16 04:28:53 +00001021
1022 St = StateMgr.getPersistentState(StVals);
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001023
Ted Kremenek1feab292008-04-16 04:28:53 +00001024 if (hasErr) {
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001025 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001026 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001027 return;
Ted Kremenek0d721572008-03-11 17:48:22 +00001028 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001029
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001030 // Finally, consult the summary for the return value.
1031
Ted Kremenek455dd862008-04-11 20:23:24 +00001032 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001033
1034 switch (RE.getKind()) {
1035 default:
1036 assert (false && "Unhandled RetEffect."); break;
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001037
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001038 case RetEffect::NoRet:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001039
Ted Kremenek455dd862008-04-11 20:23:24 +00001040 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +00001041 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1042 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +00001043
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001044 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenek455dd862008-04-11 20:23:24 +00001045 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001046 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek455dd862008-04-11 20:23:24 +00001047
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001048 RVal X = Ex->getType()->isPointerType()
1049 ? cast<RVal>(lval::SymbolVal(Sym))
1050 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenek455dd862008-04-11 20:23:24 +00001051
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001052 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek455dd862008-04-11 20:23:24 +00001053 }
1054
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001055 break;
1056
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001057 case RetEffect::Alias: {
1058 unsigned idx = RE.getValue();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001059 assert ((arg_end - arg_beg) >= 0);
1060 assert (idx < (unsigned) (arg_end - arg_beg));
1061 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1062 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001063 break;
1064 }
1065
1066 case RetEffect::OwnedSymbol: {
1067 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001068 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1069
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001070 ValueState StImpl = *St;
1071 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001072 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001073
1074 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001075 Ex, lval::SymbolVal(Sym),
1076 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001077
1078 break;
1079 }
1080
1081 case RetEffect::NotOwnedSymbol: {
1082 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001083 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001084
1085 ValueState StImpl = *St;
1086 RefBindings B = GetRefBindings(StImpl);
1087 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1088
1089 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001090 Ex, lval::SymbolVal(Sym),
1091 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001092
1093 break;
1094 }
1095 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001096
1097 Builder.MakeNode(Dst, Ex, Pred, St);
1098}
1099
1100
1101void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1102 GRExprEngine& Eng,
1103 GRStmtNodeBuilder<ValueState>& Builder,
1104 CallExpr* CE, RVal L,
1105 ExplodedNode<ValueState>* Pred) {
1106
1107
1108 RetainSummary* Summ = NULL;
1109
1110 // Get the summary.
1111
1112 if (isa<lval::FuncVal>(L)) {
1113 lval::FuncVal FV = cast<lval::FuncVal>(L);
1114 FunctionDecl* FD = FV.getDecl();
1115 Summ = Summaries.getSummary(FD, Eng.getContext());
1116 }
1117
1118 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1119 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek827f93b2008-03-06 00:08:09 +00001120}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001121
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001122
1123void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1124 GRExprEngine& Eng,
1125 GRStmtNodeBuilder<ValueState>& Builder,
1126 ObjCMessageExpr* ME,
1127 ExplodedNode<ValueState>* Pred) {
1128
Ted Kremenek33661802008-05-01 21:31:50 +00001129 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
1130 return;
1131
1132 // The basic transfer function logic for message expressions does nothing.
1133 // We just invalidate all arguments passed in by references.
1134
1135 ValueStateManager& StateMgr = Eng.getStateManager();
1136 ValueState* St = Builder.GetState(Pred);
1137 RefBindings B = GetRefBindings(*St);
1138
1139 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
1140 I != E; ++I) {
1141
1142 RVal V = StateMgr.GetRVal(St, *I);
1143
1144 if (isa<LVal>(V)) {
1145
1146 LVal lv = cast<LVal>(V);
1147
1148 // Did the lval bind to a symbol?
1149 RVal X = StateMgr.GetRVal(St, lv);
1150
1151 if (isa<lval::SymbolVal>(X)) {
Ted Kremenek6a24ec02008-05-01 23:38:35 +00001152 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
Ted Kremenek33661802008-05-01 21:31:50 +00001153 B = Remove(B, Sym);
1154
1155 // Create a new state with the updated bindings.
1156 ValueState StVals = *St;
1157 SetRefBindings(StVals, B);
1158 St = StateMgr.getPersistentState(StVals);
1159 }
1160
1161 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
1162 }
1163 }
1164
1165 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001166}
1167
1168bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1169 GRExprEngine& Eng,
1170 GRStmtNodeBuilder<ValueState>& Builder,
1171 ObjCMessageExpr* ME,
1172 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001173
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001174 if (isGCEnabled())
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001175 return true;
1176
Ted Kremenek1feab292008-04-16 04:28:53 +00001177 // Handle "toll-free bridging" of calls to "Release" and "Retain".
1178
1179 // FIXME: track the underlying object type associated so that we can
1180 // flag illegal uses of toll-free bridging (or at least handle it
1181 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001182
1183 Selector S = ME->getSelector();
1184
1185 if (!S.isUnarySelector())
1186 return true;
1187
Ted Kremenek1feab292008-04-16 04:28:53 +00001188 Expr* Receiver = ME->getReceiver();
1189
1190 if (!Receiver)
1191 return true;
1192
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001193 // Check if we are calling "autorelease".
1194
1195 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001196
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001197 if (S == AutoreleaseSelector)
1198 mode = IsAutorelease;
1199 else if (S == RetainSelector)
1200 mode = IsRetain;
1201 else if (S == ReleaseSelector)
1202 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001203
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001204 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001205 return true;
1206
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001207 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001208 ValueStateManager& StateMgr = Eng.getStateManager();
1209 ValueState* St = Builder.GetState(Pred);
1210 RVal V = StateMgr.GetRVal(St, Receiver);
1211
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001212 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001213 if (!isa<lval::SymbolVal>(V))
1214 return true;
1215
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001216 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001217 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1218 RefBindings B = GetRefBindings(*St);
1219
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001220 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001221 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001222
Ted Kremenek1feab292008-04-16 04:28:53 +00001223 if (!T)
1224 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001225
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001226 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001227
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001228 // Update the bindings.
1229 switch (mode) {
1230 case IsNone:
1231 assert(false);
1232
1233 case IsRelease:
1234 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1235 break;
1236
1237 case IsRetain:
1238 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1239 break;
1240
1241 case IsAutorelease:
1242 // For now we just stop tracking a value if we see
1243 // it sent "autorelease." In the future we can potentially
1244 // track the associated pool.
1245 B = Remove(B, Sym);
1246 break;
1247 }
1248
1249 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001250 ValueState StVals = *St;
1251 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001252 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001253
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001254 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001255 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001256 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001257 else
1258 Builder.MakeNode(Dst, ME, Pred, St);
1259
1260 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001261}
1262
Ted Kremenek7aef4842008-04-16 20:40:59 +00001263// Stores.
1264
1265void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1266 GRExprEngine& Eng,
1267 GRStmtNodeBuilder<ValueState>& Builder,
1268 Expr* E, ExplodedNode<ValueState>* Pred,
1269 ValueState* St, RVal TargetLV, RVal Val) {
1270
1271 // Check if we have a binding for "Val" and if we are storing it to something
1272 // we don't understand or otherwise the value "escapes" the function.
1273
1274 if (!isa<lval::SymbolVal>(Val))
1275 return;
1276
1277 // Are we storing to something that causes the value to "escape"?
1278
1279 bool escapes = false;
1280
1281 if (!isa<lval::DeclVal>(TargetLV))
1282 escapes = true;
1283 else
1284 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1285
1286 if (!escapes)
1287 return;
1288
1289 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1290 RefBindings B = GetRefBindings(*St);
1291 RefBindings::TreeTy* T = B.SlimFind(Sym);
1292
1293 if (!T)
1294 return;
1295
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001296 // Nuke the binding.
1297 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001298
1299 // Hand of the remaining logic to the parent implementation.
1300 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1301}
1302
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001303
1304ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1305 SymbolID sid) {
1306 ValueState StImpl = *St;
1307 RefBindings B = GetRefBindings(StImpl);
1308 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1309 return VMgr.getPersistentState(StImpl);
1310}
1311
Ted Kremenekffefc352008-04-11 22:25:11 +00001312// End-of-path.
1313
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001314ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1315 ValueState* St, SymbolID sid,
1316 RefVal V, bool& hasLeak) {
1317
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001318 hasLeak = V.isOwned() ||
1319 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001320
1321 if (!hasLeak)
1322 return NukeBinding(VMgr, St, sid);
1323
1324 RefBindings B = GetRefBindings(*St);
1325 ValueState StImpl = *St;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001326
1327 StImpl.CheckerState =
1328 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1329
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001330 return VMgr.getPersistentState(StImpl);
1331}
1332
1333void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001334 GREndPathNodeBuilder<ValueState>& Builder) {
1335
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001336 ValueState* St = Builder.getState();
1337 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001338
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001339 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001340
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001341 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1342 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001343
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001344 St = HandleSymbolDeath(Eng.getStateManager(), St,
1345 (*I).first, (*I).second, hasLeak);
1346
1347 if (hasLeak) Leaked.push_back((*I).first);
1348 }
Ted Kremenek541db372008-04-24 23:57:27 +00001349
1350 if (Leaked.empty())
1351 return;
1352
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001353 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001354
Ted Kremenek541db372008-04-24 23:57:27 +00001355 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001356 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001357
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001358 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1359 assert (!LeaksAtNode);
1360 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001361
1362 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1363 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001364 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001365}
1366
Ted Kremenek541db372008-04-24 23:57:27 +00001367// Dead symbols.
1368
1369void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1370 GRExprEngine& Eng,
1371 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001372 ExplodedNode<ValueState>* Pred,
1373 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001374 ValueState* St,
1375 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001376
Ted Kremenek541db372008-04-24 23:57:27 +00001377 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1378
1379 RefBindings B = GetRefBindings(*St);
1380 llvm::SmallVector<SymbolID, 10> Leaked;
1381
1382 for (ValueStateManager::DeadSymbolsTy::const_iterator
1383 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1384
1385 RefBindings::TreeTy* T = B.SlimFind(*I);
1386
1387 if (!T)
1388 continue;
1389
1390 bool hasLeak = false;
1391
1392 St = HandleSymbolDeath(Eng.getStateManager(), St,
1393 *I, T->getValue().second, hasLeak);
1394
1395 if (hasLeak) Leaked.push_back(*I);
1396 }
1397
1398 if (Leaked.empty())
1399 return;
1400
1401 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1402
1403 if (!N)
1404 return;
1405
1406 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1407 assert (!LeaksAtNode);
1408 LeaksAtNode = new std::vector<SymbolID>();
1409
1410 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1411 E = Leaked.end(); I != E; ++I)
1412 (*LeaksAtNode).push_back(*I);
1413}
1414
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001415 // Return statements.
1416
1417void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1418 GRExprEngine& Eng,
1419 GRStmtNodeBuilder<ValueState>& Builder,
1420 ReturnStmt* S,
1421 ExplodedNode<ValueState>* Pred) {
1422
1423 Expr* RetE = S->getRetValue();
1424 if (!RetE) return;
1425
1426 ValueStateManager& StateMgr = Eng.getStateManager();
1427 ValueState* St = Builder.GetState(Pred);
1428 RVal V = StateMgr.GetRVal(St, RetE);
1429
1430 if (!isa<lval::SymbolVal>(V))
1431 return;
1432
1433 // Get the reference count binding (if any).
1434 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1435 RefBindings B = GetRefBindings(*St);
1436 RefBindings::TreeTy* T = B.SlimFind(Sym);
1437
1438 if (!T)
1439 return;
1440
1441 // Change the reference count.
1442
1443 RefVal X = T->getValue().second;
1444
1445 switch (X.getKind()) {
1446
1447 case RefVal::Owned: {
1448 unsigned cnt = X.getCount();
1449 X = RefVal::makeReturnedOwned(cnt);
1450 break;
1451 }
1452
1453 case RefVal::NotOwned: {
1454 unsigned cnt = X.getCount();
1455 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1456 : RefVal::makeReturnedNotOwned();
1457 break;
1458 }
1459
1460 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001461 return;
1462 }
1463
1464 // Update the binding.
1465
1466 ValueState StImpl = *St;
1467 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1468 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1469}
1470
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001471// Assumptions.
1472
1473ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1474 RVal Cond, bool Assumption,
1475 bool& isFeasible) {
1476
1477 // FIXME: We may add to the interface of EvalAssume the list of symbols
1478 // whose assumptions have changed. For now we just iterate through the
1479 // bindings and check if any of the tracked symbols are NULL. This isn't
1480 // too bad since the number of symbols we will track in practice are
1481 // probably small and EvalAssume is only called at branches and a few
1482 // other places.
1483
1484 RefBindings B = GetRefBindings(*St);
1485
1486 if (B.isEmpty())
1487 return St;
1488
1489 bool changed = false;
1490
1491 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1492
1493 // Check if the symbol is null (or equal to any constant).
1494 // If this is the case, stop tracking the symbol.
1495
1496 if (St->getSymVal(I.getKey())) {
1497 changed = true;
1498 B = RefBFactory.Remove(B, I.getKey());
1499 }
1500 }
1501
1502 if (!changed)
1503 return St;
1504
1505 ValueState StImpl = *St;
1506 StImpl.CheckerState = B.getRoot();
1507 return Eng.getStateManager().getPersistentState(StImpl);
1508}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001509
1510CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001511 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001512 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001513
Ted Kremenek0d721572008-03-11 17:48:22 +00001514 // FIXME: This dispatch can potentially be sped up by unifiying it into
1515 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001516
Ted Kremenek0d721572008-03-11 17:48:22 +00001517 switch (E) {
1518 default:
1519 assert (false && "Unhandled CFRef transition.");
1520
1521 case DoNothing:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001522 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001523 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001524 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001525 break;
1526 }
1527
Ted Kremenek0d721572008-03-11 17:48:22 +00001528 return B;
1529
1530 case IncRef:
1531 switch (V.getKind()) {
1532 default:
1533 assert(false);
1534
1535 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001536 V = RefVal::makeOwned(V.getCount()+1);
1537 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001538
Ted Kremenek0d721572008-03-11 17:48:22 +00001539 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001540 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001541 break;
1542
1543 case RefVal::Released:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001544 if (isGCEnabled())
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001545 V = RefVal::makeOwned();
1546 else {
1547 V = RefVal::makeUseAfterRelease();
1548 hasErr = V.getKind();
1549 }
1550
Ted Kremenek0d721572008-03-11 17:48:22 +00001551 break;
1552 }
1553
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001554 break;
1555
Ted Kremenek0d721572008-03-11 17:48:22 +00001556 case DecRef:
1557 switch (V.getKind()) {
1558 default:
1559 assert (false);
1560
1561 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001562 unsigned Count = V.getCount();
1563 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001564 break;
1565 }
1566
Ted Kremenekc4f81022008-04-10 23:09:18 +00001567 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001568 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001569
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001570 if (Count > 0)
1571 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001572 else {
1573 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001574 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001575 }
1576
Ted Kremenek0d721572008-03-11 17:48:22 +00001577 break;
1578 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001579
1580 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001581 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001582 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001583 break;
1584 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001585
1586 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001587 }
1588
1589 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001590}
1591
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001592
1593//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001594// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001595//===----------------------------------------------------------------------===//
1596
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001597namespace {
1598
1599 //===-------------===//
1600 // Bug Descriptions. //
1601 //===-------------===//
1602
Ted Kremeneke3769852008-04-18 20:54:29 +00001603 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001604 protected:
1605 CFRefCount& TF;
1606
1607 public:
1608 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001609
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001610 CFRefCount& getTF() { return TF; }
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001611 const CFRefCount& getTF() const { return TF; }
1612
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001613 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001614 };
1615
1616 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1617 public:
1618 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1619
1620 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001621 return "Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001622 }
1623 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001624 return "Reference-counted object is used"
1625 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001626 }
1627
1628 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001629 };
1630
1631 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1632 public:
1633 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1634
1635 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001636 return "Bad Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001637 }
1638 virtual const char* getDescription() const {
1639 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001640 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001641 "The object is not owned at this point by the caller.";
1642 }
1643
1644 virtual void EmitWarnings(BugReporter& BR);
1645 };
1646
1647 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1648 public:
1649 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1650
1651 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001652 return getTF().isGCEnabled() ? "Memory Leak (GC)" : "Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001653 }
1654
1655 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001656 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001657 }
1658
1659 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001660 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001661 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001662 };
1663
1664 //===---------===//
1665 // Bug Reports. //
1666 //===---------===//
1667
1668 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1669 SymbolID Sym;
1670 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001671 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001672 : RangedBugReport(D, n), Sym(sym) {}
1673
1674 virtual ~CFRefReport() {}
1675
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001676 CFRefBug& getBugType() {
1677 return (CFRefBug&) RangedBugReport::getBugType();
1678 }
1679 const CFRefBug& getBugType() const {
1680 return (const CFRefBug&) RangedBugReport::getBugType();
1681 }
1682
1683 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1684 const SourceRange*& end) {
1685
Ted Kremenek198cae02008-05-02 20:53:50 +00001686 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001687 RangedBugReport::getRanges(BR, beg, end);
1688 else {
1689 beg = 0;
1690 end = 0;
1691 }
1692 }
1693
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001694 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1695 ExplodedNode<ValueState>* N);
1696
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001697 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001698
1699 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1700 ExplodedNode<ValueState>* PrevN,
1701 ExplodedGraph<ValueState>& G,
1702 BugReporter& BR);
1703 };
1704
1705
1706} // end anonymous namespace
1707
1708void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001709 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001710 Eng.Register(new UseAfterRelease(*this));
1711 Eng.Register(new BadRelease(*this));
1712 Eng.Register(new Leak(*this));
1713}
1714
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001715
1716static const char* Msgs[] = {
1717 "Code is compiled in garbage collection only mode" // GC only
1718 " (the bug occurs with garbage collection enabled).",
1719
1720 "Code is compiled without garbage collection.", // No GC.
1721
1722 "Code is compiled for use with and without garbage collection (GC)."
1723 " The bug occurs with GC enabled.", // Hybrid, with GC.
1724
1725 "Code is compiled for use with and without garbage collection (GC)."
1726 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1727};
1728
1729std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1730 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1731
1732 switch (TF.getLangOptions().getGCMode()) {
1733 default:
1734 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001735
1736 case LangOptions::GCOnly:
1737 assert (TF.isGCEnabled());
1738 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001739
1740 case LangOptions::NonGC:
1741 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001742 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1743
1744 case LangOptions::HybridGC:
1745 if (TF.isGCEnabled())
1746 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1747 else
1748 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1749 }
1750}
1751
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001752PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1753 ExplodedNode<ValueState>* PrevN,
1754 ExplodedGraph<ValueState>& G,
1755 BugReporter& BR) {
1756
1757 // Check if the type state has changed.
1758
1759 ValueState* PrevSt = PrevN->getState();
1760 ValueState* CurrSt = N->getState();
1761
1762 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1763 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1764
Ted Kremeneka8503952008-04-18 04:55:01 +00001765 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1766 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001767
Ted Kremeneka8503952008-04-18 04:55:01 +00001768 if (!CurrT)
1769 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001770
Ted Kremeneka8503952008-04-18 04:55:01 +00001771 const char* Msg = NULL;
1772 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001773
Ted Kremeneka8503952008-04-18 04:55:01 +00001774 if (!PrevT) {
1775
Ted Kremenek9363fd92008-05-05 17:53:17 +00001776 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1777
1778 if (CurrV.isOwned()) {
1779
1780 if (isa<CallExpr>(S))
1781 Msg = "Function call returns an object with a +1 retain count"
1782 " (owning reference).";
1783 else {
1784 assert (isa<ObjCMessageExpr>(S));
1785 Msg = "Method returns an object with a +1 retain count"
1786 " (owning reference).";
1787 }
1788 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001789 else {
1790 assert (CurrV.isNotOwned());
Ted Kremenek9363fd92008-05-05 17:53:17 +00001791
1792 if (isa<CallExpr>(S))
1793 Msg = "Function call returns an object with a +0 retain count"
1794 " (non-owning reference).";
1795 else {
1796 assert (isa<ObjCMessageExpr>(S));
1797 Msg = "Method returns an object with a +0 retain count"
1798 " (non-owning reference).";
1799 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001800 }
Ted Kremenek9363fd92008-05-05 17:53:17 +00001801
Ted Kremeneka8503952008-04-18 04:55:01 +00001802 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1803 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1804
1805 if (Expr* Exp = dyn_cast<Expr>(S))
1806 P->addRange(Exp->getSourceRange());
1807
1808 return P;
1809 }
1810
1811 // Determine if the typestate has changed.
1812
1813 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1814
1815 if (PrevV == CurrV)
1816 return NULL;
1817
1818 // The typestate has changed.
1819
1820 std::ostringstream os;
1821
1822 switch (CurrV.getKind()) {
1823 case RefVal::Owned:
1824 case RefVal::NotOwned:
1825 assert (PrevV.getKind() == CurrV.getKind());
1826
1827 if (PrevV.getCount() > CurrV.getCount())
1828 os << "Reference count decremented.";
1829 else
1830 os << "Reference count incremented.";
1831
Ted Kremenek9363fd92008-05-05 17:53:17 +00001832 if (unsigned Count = GetCount(CurrV)) {
1833
1834 os << " Object has +" << Count;
Ted Kremenek752b5842008-04-18 05:32:44 +00001835
Ted Kremenek9363fd92008-05-05 17:53:17 +00001836 if (Count > 1)
1837 os << " retain counts.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001838 else
Ted Kremenek9363fd92008-05-05 17:53:17 +00001839 os << " retain count.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001840 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001841
1842 Msg = os.str().c_str();
1843
1844 break;
1845
1846 case RefVal::Released:
1847 Msg = "Object released.";
1848 break;
1849
1850 case RefVal::ReturnedOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001851 Msg = "Object returned to caller as owning reference (single retain count"
1852 " transferred to caller).";
Ted Kremeneka8503952008-04-18 04:55:01 +00001853 break;
1854
1855 case RefVal::ReturnedNotOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001856 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremeneka8503952008-04-18 04:55:01 +00001857 break;
1858
1859 default:
1860 return NULL;
1861 }
1862
1863 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1864 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1865 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1866
1867 // Add the range by scanning the children of the statement for any bindings
1868 // to Sym.
1869
1870 ValueStateManager& VSM = BR.getEngine().getStateManager();
1871
1872 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1873 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1874 RVal X = VSM.GetRVal(CurrSt, Exp);
1875
1876 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1877 if (SV->getSymbol() == Sym) {
1878 P->addRange(Exp->getSourceRange()); break;
1879 }
1880 }
1881
1882 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001883}
1884
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001885PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremenekea794e92008-05-05 18:50:19 +00001886 ExplodedNode<ValueState>* EndN) {
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001887
1888 if (!getBugType().isLeak())
Ted Kremenekea794e92008-05-05 18:50:19 +00001889 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001890
Ted Kremenek9363fd92008-05-05 17:53:17 +00001891 typedef CFRefCount::RefBindings RefBindings;
1892
1893 // Get the retain count.
1894 unsigned long RetCount = 0;
1895
1896 {
Ted Kremenekea794e92008-05-05 18:50:19 +00001897 ValueState* St = EndN->getState();
Ted Kremenek9363fd92008-05-05 17:53:17 +00001898 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1899 RefBindings::TreeTy* T = B.SlimFind(Sym);
1900 assert (T);
1901 RetCount = GetCount(T->getValue().second);
1902 }
1903
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001904 // We are a leak. Walk up the graph to get to the first node where the
1905 // symbol appeared.
1906
Ted Kremenekea794e92008-05-05 18:50:19 +00001907 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001908 ExplodedNode<ValueState>* Last = N;
Ted Kremenekea794e92008-05-05 18:50:19 +00001909
Ted Kremenek198cae02008-05-02 20:53:50 +00001910 // Find the first node that referred to the tracked symbol. We also
1911 // try and find the first VarDecl the value was stored to.
1912
1913 VarDecl* FirstDecl = 0;
Ted Kremenekea794e92008-05-05 18:50:19 +00001914
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001915 while (N) {
1916 ValueState* St = N->getState();
1917 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001918 RefBindings::TreeTy* T = B.SlimFind(Sym);
1919
1920 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001921 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00001922
1923 VarDecl* VD = 0;
1924
1925 // Determine if there is an LVal binding to the symbol.
1926 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1927 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1928 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1929 continue;
1930
1931 if (VD) { // Multiple decls map to this symbol.
1932 VD = 0;
1933 break;
1934 }
1935
1936 VD = I->first;
1937 }
1938
1939 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001940
1941 Last = N;
1942 N = N->pred_empty() ? NULL : *(N->pred_begin());
1943 }
1944
Ted Kremenekea794e92008-05-05 18:50:19 +00001945 // Get the allocate site.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001946
1947 assert (Last);
1948 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1949
Ted Kremenekea794e92008-05-05 18:50:19 +00001950 SourceManager& SMgr = BR.getContext().getSourceManager();
1951 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001952
Ted Kremenekea794e92008-05-05 18:50:19 +00001953 // Get the leak site. We may have multiple ExplodedNodes (one with the
1954 // leak) that occur on the same line number; if the node with the leak
1955 // has any immediate predecessor nodes with the same line number, find
1956 // any transitive-successors that have a different statement and use that
1957 // line number instead. This avoids emiting a diagnostic like:
1958 //
1959 // // 'y' is leaked.
1960 // int x = foo(y);
1961 //
1962 // instead we want:
1963 //
1964 // int x = foo(y);
1965 // // 'y' is leaked.
1966
1967 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
1968 assert (S);
1969 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
1970
1971 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
1972 // it occur on the same line?
1973
1974 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
1975 N = *(EndN->pred_begin());
1976
1977 do {
1978 ProgramPoint P = N->getLocation();
1979
1980 if (!isa<PostStmt>(P))
1981 break;
1982
1983 // Predecessor at same line?
1984
1985 Stmt* SPred = cast<PostStmt>(P).getStmt();
1986
1987 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine)
1988 break;
1989
1990 // The predecessor (where the object was not yet leaked) is a statement
1991 // on the same line. Get the first successor statement that appears
1992 // on a different line. For this operation, we can traverse the
1993 // non-trimmed graph.
1994
1995 N = getEndNode(); // This is the node where the leak occured in the
1996 // original graph.
1997
1998 while (!N->succ_empty()) {
1999
2000 N = *(N->succ_begin());
2001 ProgramPoint P = N->getLocation();
2002
2003 if (!isa<PostStmt>(P))
2004 continue;
2005
2006 Stmt* SSucc = cast<PostStmt>(P).getStmt();
2007
2008 if (SMgr.getLogicalLineNumber(SSucc->getLocStart()) != EndLine) {
2009 S = SSucc;
2010 break;
2011 }
2012 }
2013 }
2014 while (false);
2015
2016 // Construct the location.
2017
2018 FullSourceLoc L(S->getLocStart(), SMgr);
2019
2020 // Generate the diagnostic.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002021 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00002022
Ted Kremenekea794e92008-05-05 18:50:19 +00002023 os << "Object allocated on line " << AllocLine;
Ted Kremenek198cae02008-05-02 20:53:50 +00002024
2025 if (FirstDecl)
2026 os << " and stored into '" << FirstDecl->getName() << '\'';
2027
Ted Kremenek9363fd92008-05-05 17:53:17 +00002028 os << " is no longer referenced after this point and has a retain count of +"
2029 << RetCount << " (object leaked).";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002030
Ted Kremenekea794e92008-05-05 18:50:19 +00002031 return new PathDiagnosticPiece(L, os.str());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002032}
2033
Ted Kremenek7d421f32008-04-09 23:49:11 +00002034void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002035
Ted Kremenek7d421f32008-04-09 23:49:11 +00002036 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2037 E = TF.use_after_end(); I != E; ++I) {
2038
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002039 CFRefReport report(*this, I->first, I->second.second);
2040 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00002041 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002042 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00002043}
2044
2045void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002046
Ted Kremenek7d421f32008-04-09 23:49:11 +00002047 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2048 E = TF.bad_release_end(); I != E; ++I) {
2049
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002050 CFRefReport report(*this, I->first, I->second.second);
2051 report.addRange(I->second.first->getSourceRange());
2052 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00002053 }
2054}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002055
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002056void Leak::EmitWarnings(BugReporter& BR) {
2057
2058 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2059 E = TF.leaks_end(); I != E; ++I) {
2060
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002061 std::vector<SymbolID>& SymV = *(I->second);
2062 unsigned n = SymV.size();
2063
2064 for (unsigned i = 0; i < n; ++i) {
2065 CFRefReport report(*this, I->first, SymV[i]);
2066 BR.EmitWarning(report);
2067 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002068 }
2069}
2070
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00002071void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2072 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2073 I!=E; ++I)
2074 Nodes.push_back(I->first);
2075}
2076
Ted Kremeneka7338b42008-03-11 06:39:11 +00002077//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00002078// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00002079//===----------------------------------------------------------------------===//
2080
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002081GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00002082 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002083 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00002084 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00002085}