blob: b06579703f022586eab59daa5d537b86dcaed8c8 [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 Kremenek0e344d42008-05-06 00:30:21 +0000232 void InitializeInstanceSummaries();
233
Ted Kremeneka7338b42008-03-11 06:39:11 +0000234public:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000235
236 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek0e344d42008-05-06 00:30:21 +0000237 : Ctx(ctx), GCEnabled(gcenabled) {
238
239 InitializeInstanceSummaries();
240 }
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000241
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000242 ~RetainSummaryManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000243
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000244 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
245
246 bool isGCEnabled() const { return GCEnabled; }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000247};
248
249} // end anonymous namespace
250
251//===----------------------------------------------------------------------===//
252// Implementation of checker data structures.
253//===----------------------------------------------------------------------===//
254
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000255RetainSummaryManager::~RetainSummaryManager() {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000256
257 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
258 // mitigating the need to do explicit cleanup of the
259 // Argument-Effect summaries.
260
Ted Kremenek42ea0322008-05-05 23:55:01 +0000261 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
262 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremeneka7338b42008-03-11 06:39:11 +0000263 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000264}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000265
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000266ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000267
Ted Kremenekae855d42008-04-24 17:22:33 +0000268 if (ScratchArgs.empty())
269 return NULL;
270
271 // Compute a profile for a non-empty ScratchArgs.
272
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000273 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000274
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000275 profile.Add(ScratchArgs);
276 void* InsertPos;
277
Ted Kremenekae855d42008-04-24 17:22:33 +0000278 // Look up the uniqued copy, or create a new one.
279
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000280 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000281 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000282
Ted Kremenekae855d42008-04-24 17:22:33 +0000283 if (E) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000284 ScratchArgs.clear();
285 return &E->getValue();
286 }
287
288 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
289 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
290
291 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000292 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000293
294 ScratchArgs.clear();
295 return &E->getValue();
296}
297
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000298RetainSummary* RetainSummaryManager::getPersistentSummary(ArgEffects* AE,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000299 RetEffect RE) {
300
Ted Kremenekae855d42008-04-24 17:22:33 +0000301 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000302 llvm::FoldingSetNodeID profile;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000303 RetainSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000304
Ted Kremenekae855d42008-04-24 17:22:33 +0000305 // Look up the uniqued summary, or create one if it doesn't exist.
306 void* InsertPos;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000307 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000308
309 if (Summ)
310 return Summ;
311
Ted Kremenekae855d42008-04-24 17:22:33 +0000312 // Create the summary and return it.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000313 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
314 new (Summ) RetainSummary(AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000315 SummarySet.InsertNode(Summ, InsertPos);
316
317 return Summ;
318}
319
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000320//===----------------------------------------------------------------------===//
321// Summary creation for functions (largely uses of Core Foundation).
322//===----------------------------------------------------------------------===//
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000323
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000324RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000325 ASTContext& Ctx) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000326
327 SourceLocation Loc = FD->getLocation();
328
329 if (!Loc.isFileID())
330 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000331
Ted Kremenekae855d42008-04-24 17:22:33 +0000332 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000333 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenekae855d42008-04-24 17:22:33 +0000334
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000335 if (I != FuncSummaries.end())
Ted Kremenekae855d42008-04-24 17:22:33 +0000336 return I->second;
337
338 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000339 const char* FName = FD->getIdentifier()->getName();
340
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000341 RetainSummary *S = 0;
Ted Kremenek562c1302008-05-05 16:51:50 +0000342
343 if (FName[0] == 'C' && FName[1] == 'F')
344 S = getCFSummary(FD, FName);
345 else if (FName[0] == 'N' && FName[1] == 'S')
346 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000347
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000348 FuncSummaries[FD] = S;
Ted Kremenek562c1302008-05-05 16:51:50 +0000349 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000350}
351
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000352RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000353 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000354 FName += 2;
355
356 if (strcmp(FName, "MakeCollectable") == 0)
357 return getUnarySummary(FD, cfmakecollectable);
358
359 return 0;
360}
361
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000362RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000363 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000364
365 FName += 2;
366
367 if (strcmp(FName, "Retain") == 0)
368 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000369
Ted Kremenek562c1302008-05-05 16:51:50 +0000370 if (strcmp(FName, "Release") == 0)
371 return getUnarySummary(FD, cfrelease);
372
373 if (strcmp(FName, "MakeCollectable") == 0)
374 return getUnarySummary(FD, cfmakecollectable);
375
376 if (strstr(FName, "Create") || strstr(FName, "Copy"))
377 return getCFSummaryCreateRule(FD);
378
379 if (strstr(FName, "Get"))
380 return getCFSummaryGetRule(FD);
381
382 return 0;
383}
384
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000385RetainSummary*
386RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000387
388 FunctionTypeProto* FT =
389 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
390
Ted Kremenek562c1302008-05-05 16:51:50 +0000391 if (FT) {
392
393 if (FT->getNumArgs() != 1)
394 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000395
Ted Kremenek562c1302008-05-05 16:51:50 +0000396 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
397
398 if (!ArgT)
399 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000400
Ted Kremenek562c1302008-05-05 16:51:50 +0000401 if (!ArgT->isPointerType())
402 return NULL;
403 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000404
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000405 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000406
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000407 switch (func) {
408 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000409 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek0e344d42008-05-06 00:30:21 +0000410 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000411 }
412
413 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000414 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek0e344d42008-05-06 00:30:21 +0000415 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000416 }
417
418 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000419 if (GCEnabled)
420 ScratchArgs.push_back(std::make_pair(0, DecRef));
421
Ted Kremenek0e344d42008-05-06 00:30:21 +0000422 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000423 }
424
425 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000426 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000427 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000428}
429
430static bool isCFRefType(QualType T) {
431
432 if (!T->isPointerType())
433 return false;
434
435 // Check the typedef for the name "CF" and the substring "Ref".
436
437 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
438
439 if (!TD)
440 return false;
441
442 const char* TDName = TD->getDecl()->getIdentifier()->getName();
443 assert (TDName);
444
445 if (TDName[0] != 'C' || TDName[1] != 'F')
446 return false;
447
448 if (strstr(TDName, "Ref") == 0)
449 return false;
450
451 return true;
452}
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000453
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000454RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000455
Ted Kremenek562c1302008-05-05 16:51:50 +0000456 FunctionTypeProto* FT =
457 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
458
459 if (FT && !isCFRefType(FT->getResultType()))
460 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000461
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000462 // FIXME: Add special-cases for functions that retain/release. For now
463 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000464
465 assert (ScratchArgs.empty());
Ted Kremenek0e344d42008-05-06 00:30:21 +0000466 return getPersistentSummary(RetEffect::MakeOwned());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000467}
468
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000469RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000470
Ted Kremenek562c1302008-05-05 16:51:50 +0000471 FunctionTypeProto* FT =
472 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000473
Ted Kremenek562c1302008-05-05 16:51:50 +0000474 if (FT) {
475 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000476
Ted Kremenek562c1302008-05-05 16:51:50 +0000477 // FIXME: For now we assume that all pointer types returned are referenced
478 // counted. Since this is the "Get" rule, we assume non-ownership, which
479 // works fine for things that are not reference counted. We do this because
480 // some generic data structures return "void*". We need something better
481 // in the future.
482
483 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
484 return 0;
485 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000486
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000487 // FIXME: Add special-cases for functions that retain/release. For now
488 // just handle the default case.
489
Ted Kremenekae855d42008-04-24 17:22:33 +0000490 assert (ScratchArgs.empty());
Ted Kremenek0e344d42008-05-06 00:30:21 +0000491 return getPersistentSummary(RetEffect::MakeNotOwned());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000492}
493
Ted Kremeneka7338b42008-03-11 06:39:11 +0000494//===----------------------------------------------------------------------===//
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000495// Summary creation for Selectors.
496//===----------------------------------------------------------------------===//
497
Ted Kremenek42ea0322008-05-05 23:55:01 +0000498RetainSummary* RetainSummaryManager::getInitMethodSummary(Selector S) {
499 assert(ScratchArgs.empty());
500
501 RetainSummary* Summ =
Ted Kremenek0e344d42008-05-06 00:30:21 +0000502 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek42ea0322008-05-05 23:55:01 +0000503
Ted Kremenek0e344d42008-05-06 00:30:21 +0000504 ObjCMethSummaries[S] = Summ;
Ted Kremenek42ea0322008-05-05 23:55:01 +0000505 return Summ;
506}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000507
Ted Kremenek42ea0322008-05-05 23:55:01 +0000508RetainSummary* RetainSummaryManager::getMethodSummary(Selector S) {
509
510 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000511 ObjCMethSummariesTy::iterator I = ObjCMethSummaries.find(S);
Ted Kremenek42ea0322008-05-05 23:55:01 +0000512
Ted Kremenek0e344d42008-05-06 00:30:21 +0000513 if (I != ObjCMethSummaries.end())
Ted Kremenek42ea0322008-05-05 23:55:01 +0000514 return I->second;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000515
Ted Kremenek42ea0322008-05-05 23:55:01 +0000516 // "initXXX": pass-through for receiver.
517
518 const char* s = S.getIdentifierInfoForSlot(0)->getName();
519
520 if (s[0] == 'i' && s[10] == 'n' && s[2] == 'i' && s[3] == 't')
521 return getInitMethodSummary(S);
522
523 return 0;
524}
525
Ted Kremenek0e344d42008-05-06 00:30:21 +0000526void RetainSummaryManager::InitializeInstanceSummaries() {
527
528 assert (ScratchArgs.empty());
529
530 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
531 RetainSummary* Summ = getPersistentSummary(E);
532
533 // Create the "alloc" selector.
534 ObjCInstMethSummaries[ GetNullarySelector("alloc", Ctx) ] = Summ;
535
536 // Create the "new" selector.
537 ObjCInstMethSummaries[ GetNullarySelector("new", Ctx) ] = Summ;
538
539 // Create the "allocWithZone:" selector.
540 ObjCInstMethSummaries[ GetUnarySelector("allocWithZone", Ctx) ] = Summ;
541
542 // Create the "copyWithZone:" selector.
543 ObjCInstMethSummaries[ GetUnarySelector("copyWithZone", Ctx) ] = Summ;
544
545 // Create the "mutableCopyWithZone:" selector.
546 ObjCInstMethSummaries[ GetUnarySelector("mutableCopyWithZone", Ctx) ] = Summ;
547}
548
549
Ted Kremenek42ea0322008-05-05 23:55:01 +0000550RetainSummary* RetainSummaryManager::getInstanceMethodSummary(Selector S) {
551
552 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek0e344d42008-05-06 00:30:21 +0000553 ObjCMethSummariesTy::iterator I = ObjCInstMethSummaries.find(S);
Ted Kremenek42ea0322008-05-05 23:55:01 +0000554
Ted Kremenek0e344d42008-05-06 00:30:21 +0000555 if (I != ObjCInstMethSummaries.end())
Ted Kremenek42ea0322008-05-05 23:55:01 +0000556 return I->second;
557
558 return 0;
559}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000560
561//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000562// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000563//===----------------------------------------------------------------------===//
564
Ted Kremeneka7338b42008-03-11 06:39:11 +0000565namespace {
566
Ted Kremenek7d421f32008-04-09 23:49:11 +0000567class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000568public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000569
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000570 enum Kind {
571 Owned = 0, // Owning reference.
572 NotOwned, // Reference is not owned by still valid (not freed).
573 Released, // Object has been released.
574 ReturnedOwned, // Returned object passes ownership to caller.
575 ReturnedNotOwned, // Return object does not pass ownership to caller.
576 ErrorUseAfterRelease, // Object used after released.
577 ErrorReleaseNotOwned, // Release of an object that was not owned.
578 ErrorLeak // A memory leak due to excessive reference counts.
579 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000580
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000581private:
582
583 Kind kind;
584 unsigned Cnt;
585
586 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
587
588 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000589
590public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000591
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000592 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000593
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000594 unsigned getCount() const { return Cnt; }
595
596 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000597
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000598 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
599
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000600 static bool isLeak(Kind k) { return k == ErrorLeak; }
601
Ted Kremenekffefc352008-04-11 22:25:11 +0000602 bool isOwned() const {
603 return getKind() == Owned;
604 }
605
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000606 bool isNotOwned() const {
607 return getKind() == NotOwned;
608 }
609
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000610 bool isReturnedOwned() const {
611 return getKind() == ReturnedOwned;
612 }
613
614 bool isReturnedNotOwned() const {
615 return getKind() == ReturnedNotOwned;
616 }
617
618 bool isNonLeakError() const {
619 Kind k = getKind();
620 return isError(k) && !isLeak(k);
621 }
622
623 // State creation: normal state.
624
Ted Kremenekc4f81022008-04-10 23:09:18 +0000625 static RefVal makeOwned(unsigned Count = 0) {
626 return RefVal(Owned, Count);
627 }
628
629 static RefVal makeNotOwned(unsigned Count = 0) {
630 return RefVal(NotOwned, Count);
631 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000632
633 static RefVal makeReturnedOwned(unsigned Count) {
634 return RefVal(ReturnedOwned, Count);
635 }
636
637 static RefVal makeReturnedNotOwned() {
638 return RefVal(ReturnedNotOwned);
639 }
640
641 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000642
Ted Kremenek9363fd92008-05-05 17:53:17 +0000643 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000644 static RefVal makeReleased() { return RefVal(Released); }
645 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
646 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000647
648 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000649
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000650 bool operator==(const RefVal& X) const {
651 return kind == X.kind && Cnt == X.Cnt;
652 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000653
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000654 void Profile(llvm::FoldingSetNodeID& ID) const {
655 ID.AddInteger((unsigned) kind);
656 ID.AddInteger(Cnt);
657 }
658
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000659 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000660};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000661
662void RefVal::print(std::ostream& Out) const {
663 switch (getKind()) {
664 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000665 case Owned: {
666 Out << "Owned";
667 unsigned cnt = getCount();
668 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000669 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000670 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000671
Ted Kremenekc4f81022008-04-10 23:09:18 +0000672 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000673 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000674 unsigned cnt = getCount();
675 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000676 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000677 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000678
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000679 case ReturnedOwned: {
680 Out << "ReturnedOwned";
681 unsigned cnt = getCount();
682 if (cnt) Out << " (+ " << cnt << ")";
683 break;
684 }
685
686 case ReturnedNotOwned: {
687 Out << "ReturnedNotOwned";
688 unsigned cnt = getCount();
689 if (cnt) Out << " (+ " << cnt << ")";
690 break;
691 }
692
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000693 case Released:
694 Out << "Released";
695 break;
696
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000697 case ErrorLeak:
698 Out << "Leaked";
699 break;
700
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000701 case ErrorUseAfterRelease:
702 Out << "Use-After-Release [ERROR]";
703 break;
704
705 case ErrorReleaseNotOwned:
706 Out << "Release of Not-Owned [ERROR]";
707 break;
708 }
709}
Ted Kremenek0d721572008-03-11 17:48:22 +0000710
Ted Kremenek9363fd92008-05-05 17:53:17 +0000711static inline unsigned GetCount(RefVal V) {
712 switch (V.getKind()) {
713 default:
714 return V.getCount();
715
716 case RefVal::Owned:
717 return V.getCount()+1;
718 }
719}
720
Ted Kremenek7aef4842008-04-16 20:40:59 +0000721//===----------------------------------------------------------------------===//
722// Transfer functions.
723//===----------------------------------------------------------------------===//
724
Ted Kremenek7d421f32008-04-09 23:49:11 +0000725class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000726public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000727 // Type definitions.
728
Ted Kremenek0d721572008-03-11 17:48:22 +0000729 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000730 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000731
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000732 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
733 ReleasesNotOwnedTy;
734
735 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
736
737 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000738 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000739
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000740 class BindingsPrinter : public ValueState::CheckerStatePrinter {
741 public:
742 virtual void PrintCheckerState(std::ostream& Out, void* State,
743 const char* nl, const char* sep);
744 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000745
746private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000747 // Instance variables.
748
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000749 RetainSummaryManager Summaries;
750 const bool EmitStandardWarnings;
751 const LangOptions& LOpts;
752 RefBFactoryTy RefBFactory;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000753
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000754 UseAfterReleasesTy UseAfterReleases;
755 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000756 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000757
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000758 BindingsPrinter Printer;
759
Ted Kremenek1feab292008-04-16 04:28:53 +0000760 Selector RetainSelector;
761 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000762 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000763
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000764public:
765
Ted Kremeneka7338b42008-03-11 06:39:11 +0000766 static RefBindings GetRefBindings(ValueState& StImpl) {
767 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
768 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000769
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000770private:
771
Ted Kremeneka7338b42008-03-11 06:39:11 +0000772 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
773 StImpl.CheckerState = B.getRoot();
774 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000775
Ted Kremeneka7338b42008-03-11 06:39:11 +0000776 RefBindings Remove(RefBindings B, SymbolID sym) {
777 return RefBFactory.Remove(B, sym);
778 }
779
Ted Kremenek0d721572008-03-11 17:48:22 +0000780 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000781 RefVal::Kind& hasErr);
782
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000783 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
784 GRStmtNodeBuilder<ValueState>& Builder,
785 Expr* NodeExpr, Expr* ErrorExpr,
786 ExplodedNode<ValueState>* Pred,
787 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000788 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000789
790 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
791 SymbolID sid, RefVal V, bool& hasLeak);
792
793 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
794 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000795
796public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000797
Ted Kremenek2f62f352008-05-02 18:01:49 +0000798 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
799 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000800 : Summaries(Ctx, gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000801 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000802 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000803 RetainSelector(GetNullarySelector("retain", Ctx)),
804 ReleaseSelector(GetNullarySelector("release", Ctx)),
805 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000806
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000807 virtual ~CFRefCount() {
808 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
809 delete I->second;
810 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000811
812 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000813
814 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
815 return &Printer;
816 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000817
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000818 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000819 const LangOptions& getLangOptions() const { return LOpts; }
820
Ted Kremeneka7338b42008-03-11 06:39:11 +0000821 // Calls.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000822
823 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
824 GRExprEngine& Eng,
825 GRStmtNodeBuilder<ValueState>& Builder,
826 Expr* Ex,
827 Expr* Receiver,
828 RetainSummary* Summ,
829 Expr** arg_beg, Expr** arg_end,
830 ExplodedNode<ValueState>* Pred);
831
Ted Kremeneka7338b42008-03-11 06:39:11 +0000832 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000833 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000834 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000835 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000836 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000837
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000838
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000839 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
840 GRExprEngine& Engine,
841 GRStmtNodeBuilder<ValueState>& Builder,
842 ObjCMessageExpr* ME,
843 ExplodedNode<ValueState>* Pred);
844
845 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
846 GRExprEngine& Engine,
847 GRStmtNodeBuilder<ValueState>& Builder,
848 ObjCMessageExpr* ME,
849 ExplodedNode<ValueState>* Pred);
850
Ted Kremenek7aef4842008-04-16 20:40:59 +0000851 // Stores.
852
853 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
854 GRExprEngine& Engine,
855 GRStmtNodeBuilder<ValueState>& Builder,
856 Expr* E, ExplodedNode<ValueState>* Pred,
857 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000858 // End-of-path.
859
860 virtual void EvalEndPath(GRExprEngine& Engine,
861 GREndPathNodeBuilder<ValueState>& Builder);
862
Ted Kremenek541db372008-04-24 23:57:27 +0000863 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
864 GRExprEngine& Engine,
865 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000866 ExplodedNode<ValueState>* Pred,
867 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000868 ValueState* St,
869 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000870 // Return statements.
871
872 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
873 GRExprEngine& Engine,
874 GRStmtNodeBuilder<ValueState>& Builder,
875 ReturnStmt* S,
876 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +0000877
878 // Assumptions.
879
880 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
881 RVal Cond, bool Assumption, bool& isFeasible);
882
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000883 // Error iterators.
884
885 typedef UseAfterReleasesTy::iterator use_after_iterator;
886 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000887 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000888
Ted Kremenek7d421f32008-04-09 23:49:11 +0000889 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
890 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000891
Ted Kremenek7d421f32008-04-09 23:49:11 +0000892 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
893 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000894
895 leaks_iterator leaks_begin() { return Leaks.begin(); }
896 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000897};
898
899} // end anonymous namespace
900
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000901
Ted Kremenek7d421f32008-04-09 23:49:11 +0000902
903
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000904void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
905 void* State, const char* nl,
906 const char* sep) {
907 RefBindings B((RefBindings::TreeTy*) State);
908
909 if (State)
910 Out << sep << nl;
911
912 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
913 Out << (*I).first << " : ";
914 (*I).second.print(Out);
915 Out << nl;
916 }
917}
918
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000919static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000920 return Summ ? Summ->getArg(idx) : DoNothing;
921}
922
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000923static inline RetEffect GetRetE(RetainSummary* Summ) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000924 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
925}
926
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000927void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
928 GRStmtNodeBuilder<ValueState>& Builder,
929 Expr* NodeExpr, Expr* ErrorExpr,
930 ExplodedNode<ValueState>* Pred,
931 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000932 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000933 Builder.BuildSinks = true;
934 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
935
936 if (!N) return;
937
938 switch (hasErr) {
939 default: assert(false);
940 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000941 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000942 break;
943
944 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000945 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000946 break;
947 }
948}
949
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000950void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
951 GRExprEngine& Eng,
952 GRStmtNodeBuilder<ValueState>& Builder,
953 Expr* Ex,
954 Expr* Receiver,
955 RetainSummary* Summ,
956 Expr** arg_beg, Expr** arg_end,
957 ExplodedNode<ValueState>* Pred) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000958
Ted Kremenek827f93b2008-03-06 00:08:09 +0000959
Ted Kremeneka7338b42008-03-11 06:39:11 +0000960 // Get the state.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000961 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000962 ValueState* St = Builder.GetState(Pred);
963
964 // Evaluate the effects of the call.
965
966 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000967 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000968
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000969 // This function has a summary. Evaluate the effect of the arguments.
970
971 unsigned idx = 0;
972
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000973 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000974 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000975
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000976 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000977
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000978 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000979
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000980 if (isa<lval::SymbolVal>(V)) {
981 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000982 RefBindings B = GetRefBindings(StVals);
983
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000984 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000985 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000986 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000987
Ted Kremenek1feab292008-04-16 04:28:53 +0000988 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000989 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000990 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000991 break;
992 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000993 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000994 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000995 else if (isa<LVal>(V)) {
996 // Nuke all arguments passed by reference.
Ted Kremenek455dd862008-04-11 20:23:24 +0000997 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000998 }
Ted Kremenekbe621292008-04-22 21:39:21 +0000999 else if (isa<nonlval::LValAsInteger>(V))
1000 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001001 }
Ted Kremenek1feab292008-04-16 04:28:53 +00001002
1003 St = StateMgr.getPersistentState(StVals);
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001004
Ted Kremenek1feab292008-04-16 04:28:53 +00001005 if (hasErr) {
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001006 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001007 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001008 return;
Ted Kremenek0d721572008-03-11 17:48:22 +00001009 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001010
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001011 // Finally, consult the summary for the return value.
1012
Ted Kremenek455dd862008-04-11 20:23:24 +00001013 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001014
1015 switch (RE.getKind()) {
1016 default:
1017 assert (false && "Unhandled RetEffect."); break;
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001018
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001019 case RetEffect::NoRet:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001020
Ted Kremenek455dd862008-04-11 20:23:24 +00001021 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +00001022 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1023 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +00001024
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001025 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenek455dd862008-04-11 20:23:24 +00001026 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001027 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek455dd862008-04-11 20:23:24 +00001028
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001029 RVal X = Ex->getType()->isPointerType()
1030 ? cast<RVal>(lval::SymbolVal(Sym))
1031 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenek455dd862008-04-11 20:23:24 +00001032
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001033 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek455dd862008-04-11 20:23:24 +00001034 }
1035
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001036 break;
1037
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001038 case RetEffect::Alias: {
1039 unsigned idx = RE.getValue();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001040 assert ((arg_end - arg_beg) >= 0);
1041 assert (idx < (unsigned) (arg_end - arg_beg));
1042 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1043 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001044 break;
1045 }
1046
1047 case RetEffect::OwnedSymbol: {
1048 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001049 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1050
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001051 ValueState StImpl = *St;
1052 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001053 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001054
1055 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001056 Ex, lval::SymbolVal(Sym),
1057 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001058
1059 break;
1060 }
1061
1062 case RetEffect::NotOwnedSymbol: {
1063 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001064 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001065
1066 ValueState StImpl = *St;
1067 RefBindings B = GetRefBindings(StImpl);
1068 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1069
1070 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001071 Ex, lval::SymbolVal(Sym),
1072 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001073
1074 break;
1075 }
1076 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001077
1078 Builder.MakeNode(Dst, Ex, Pred, St);
1079}
1080
1081
1082void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1083 GRExprEngine& Eng,
1084 GRStmtNodeBuilder<ValueState>& Builder,
1085 CallExpr* CE, RVal L,
1086 ExplodedNode<ValueState>* Pred) {
1087
1088
1089 RetainSummary* Summ = NULL;
1090
1091 // Get the summary.
1092
1093 if (isa<lval::FuncVal>(L)) {
1094 lval::FuncVal FV = cast<lval::FuncVal>(L);
1095 FunctionDecl* FD = FV.getDecl();
1096 Summ = Summaries.getSummary(FD, Eng.getContext());
1097 }
1098
1099 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1100 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek827f93b2008-03-06 00:08:09 +00001101}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001102
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001103
1104void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1105 GRExprEngine& Eng,
1106 GRStmtNodeBuilder<ValueState>& Builder,
1107 ObjCMessageExpr* ME,
1108 ExplodedNode<ValueState>* Pred) {
1109
Ted Kremenek33661802008-05-01 21:31:50 +00001110 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
1111 return;
1112
1113 // The basic transfer function logic for message expressions does nothing.
1114 // We just invalidate all arguments passed in by references.
1115
1116 ValueStateManager& StateMgr = Eng.getStateManager();
1117 ValueState* St = Builder.GetState(Pred);
1118 RefBindings B = GetRefBindings(*St);
1119
1120 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
1121 I != E; ++I) {
1122
1123 RVal V = StateMgr.GetRVal(St, *I);
1124
1125 if (isa<LVal>(V)) {
1126
1127 LVal lv = cast<LVal>(V);
1128
1129 // Did the lval bind to a symbol?
1130 RVal X = StateMgr.GetRVal(St, lv);
1131
1132 if (isa<lval::SymbolVal>(X)) {
Ted Kremenek6a24ec02008-05-01 23:38:35 +00001133 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
Ted Kremenek33661802008-05-01 21:31:50 +00001134 B = Remove(B, Sym);
1135
1136 // Create a new state with the updated bindings.
1137 ValueState StVals = *St;
1138 SetRefBindings(StVals, B);
1139 St = StateMgr.getPersistentState(StVals);
1140 }
1141
1142 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
1143 }
1144 }
1145
1146 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001147}
1148
1149bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1150 GRExprEngine& Eng,
1151 GRStmtNodeBuilder<ValueState>& Builder,
1152 ObjCMessageExpr* ME,
1153 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001154
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001155 if (isGCEnabled())
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001156 return true;
1157
Ted Kremenek1feab292008-04-16 04:28:53 +00001158 // Handle "toll-free bridging" of calls to "Release" and "Retain".
1159
1160 // FIXME: track the underlying object type associated so that we can
1161 // flag illegal uses of toll-free bridging (or at least handle it
1162 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001163
1164 Selector S = ME->getSelector();
1165
1166 if (!S.isUnarySelector())
1167 return true;
1168
Ted Kremenek1feab292008-04-16 04:28:53 +00001169 Expr* Receiver = ME->getReceiver();
1170
1171 if (!Receiver)
1172 return true;
1173
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001174 // Check if we are calling "autorelease".
1175
1176 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001177
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001178 if (S == AutoreleaseSelector)
1179 mode = IsAutorelease;
1180 else if (S == RetainSelector)
1181 mode = IsRetain;
1182 else if (S == ReleaseSelector)
1183 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001184
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001185 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001186 return true;
1187
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001188 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001189 ValueStateManager& StateMgr = Eng.getStateManager();
1190 ValueState* St = Builder.GetState(Pred);
1191 RVal V = StateMgr.GetRVal(St, Receiver);
1192
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001193 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001194 if (!isa<lval::SymbolVal>(V))
1195 return true;
1196
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001197 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001198 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1199 RefBindings B = GetRefBindings(*St);
1200
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001201 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001202 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001203
Ted Kremenek1feab292008-04-16 04:28:53 +00001204 if (!T)
1205 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001206
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001207 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001208
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001209 // Update the bindings.
1210 switch (mode) {
1211 case IsNone:
1212 assert(false);
1213
1214 case IsRelease:
1215 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1216 break;
1217
1218 case IsRetain:
1219 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1220 break;
1221
1222 case IsAutorelease:
1223 // For now we just stop tracking a value if we see
1224 // it sent "autorelease." In the future we can potentially
1225 // track the associated pool.
1226 B = Remove(B, Sym);
1227 break;
1228 }
1229
1230 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001231 ValueState StVals = *St;
1232 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001233 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001234
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001235 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001236 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001237 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001238 else
1239 Builder.MakeNode(Dst, ME, Pred, St);
1240
1241 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001242}
1243
Ted Kremenek7aef4842008-04-16 20:40:59 +00001244// Stores.
1245
1246void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1247 GRExprEngine& Eng,
1248 GRStmtNodeBuilder<ValueState>& Builder,
1249 Expr* E, ExplodedNode<ValueState>* Pred,
1250 ValueState* St, RVal TargetLV, RVal Val) {
1251
1252 // Check if we have a binding for "Val" and if we are storing it to something
1253 // we don't understand or otherwise the value "escapes" the function.
1254
1255 if (!isa<lval::SymbolVal>(Val))
1256 return;
1257
1258 // Are we storing to something that causes the value to "escape"?
1259
1260 bool escapes = false;
1261
1262 if (!isa<lval::DeclVal>(TargetLV))
1263 escapes = true;
1264 else
1265 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1266
1267 if (!escapes)
1268 return;
1269
1270 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1271 RefBindings B = GetRefBindings(*St);
1272 RefBindings::TreeTy* T = B.SlimFind(Sym);
1273
1274 if (!T)
1275 return;
1276
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001277 // Nuke the binding.
1278 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001279
1280 // Hand of the remaining logic to the parent implementation.
1281 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1282}
1283
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001284
1285ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1286 SymbolID sid) {
1287 ValueState StImpl = *St;
1288 RefBindings B = GetRefBindings(StImpl);
1289 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1290 return VMgr.getPersistentState(StImpl);
1291}
1292
Ted Kremenekffefc352008-04-11 22:25:11 +00001293// End-of-path.
1294
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001295ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1296 ValueState* St, SymbolID sid,
1297 RefVal V, bool& hasLeak) {
1298
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001299 hasLeak = V.isOwned() ||
1300 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001301
1302 if (!hasLeak)
1303 return NukeBinding(VMgr, St, sid);
1304
1305 RefBindings B = GetRefBindings(*St);
1306 ValueState StImpl = *St;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001307
1308 StImpl.CheckerState =
1309 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1310
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001311 return VMgr.getPersistentState(StImpl);
1312}
1313
1314void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001315 GREndPathNodeBuilder<ValueState>& Builder) {
1316
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001317 ValueState* St = Builder.getState();
1318 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001319
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001320 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001321
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001322 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1323 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001324
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001325 St = HandleSymbolDeath(Eng.getStateManager(), St,
1326 (*I).first, (*I).second, hasLeak);
1327
1328 if (hasLeak) Leaked.push_back((*I).first);
1329 }
Ted Kremenek541db372008-04-24 23:57:27 +00001330
1331 if (Leaked.empty())
1332 return;
1333
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001334 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001335
Ted Kremenek541db372008-04-24 23:57:27 +00001336 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001337 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001338
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001339 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1340 assert (!LeaksAtNode);
1341 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001342
1343 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1344 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001345 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001346}
1347
Ted Kremenek541db372008-04-24 23:57:27 +00001348// Dead symbols.
1349
1350void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1351 GRExprEngine& Eng,
1352 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001353 ExplodedNode<ValueState>* Pred,
1354 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001355 ValueState* St,
1356 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001357
Ted Kremenek541db372008-04-24 23:57:27 +00001358 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1359
1360 RefBindings B = GetRefBindings(*St);
1361 llvm::SmallVector<SymbolID, 10> Leaked;
1362
1363 for (ValueStateManager::DeadSymbolsTy::const_iterator
1364 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1365
1366 RefBindings::TreeTy* T = B.SlimFind(*I);
1367
1368 if (!T)
1369 continue;
1370
1371 bool hasLeak = false;
1372
1373 St = HandleSymbolDeath(Eng.getStateManager(), St,
1374 *I, T->getValue().second, hasLeak);
1375
1376 if (hasLeak) Leaked.push_back(*I);
1377 }
1378
1379 if (Leaked.empty())
1380 return;
1381
1382 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1383
1384 if (!N)
1385 return;
1386
1387 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1388 assert (!LeaksAtNode);
1389 LeaksAtNode = new std::vector<SymbolID>();
1390
1391 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1392 E = Leaked.end(); I != E; ++I)
1393 (*LeaksAtNode).push_back(*I);
1394}
1395
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001396 // Return statements.
1397
1398void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1399 GRExprEngine& Eng,
1400 GRStmtNodeBuilder<ValueState>& Builder,
1401 ReturnStmt* S,
1402 ExplodedNode<ValueState>* Pred) {
1403
1404 Expr* RetE = S->getRetValue();
1405 if (!RetE) return;
1406
1407 ValueStateManager& StateMgr = Eng.getStateManager();
1408 ValueState* St = Builder.GetState(Pred);
1409 RVal V = StateMgr.GetRVal(St, RetE);
1410
1411 if (!isa<lval::SymbolVal>(V))
1412 return;
1413
1414 // Get the reference count binding (if any).
1415 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1416 RefBindings B = GetRefBindings(*St);
1417 RefBindings::TreeTy* T = B.SlimFind(Sym);
1418
1419 if (!T)
1420 return;
1421
1422 // Change the reference count.
1423
1424 RefVal X = T->getValue().second;
1425
1426 switch (X.getKind()) {
1427
1428 case RefVal::Owned: {
1429 unsigned cnt = X.getCount();
1430 X = RefVal::makeReturnedOwned(cnt);
1431 break;
1432 }
1433
1434 case RefVal::NotOwned: {
1435 unsigned cnt = X.getCount();
1436 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1437 : RefVal::makeReturnedNotOwned();
1438 break;
1439 }
1440
1441 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001442 return;
1443 }
1444
1445 // Update the binding.
1446
1447 ValueState StImpl = *St;
1448 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1449 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1450}
1451
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001452// Assumptions.
1453
1454ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1455 RVal Cond, bool Assumption,
1456 bool& isFeasible) {
1457
1458 // FIXME: We may add to the interface of EvalAssume the list of symbols
1459 // whose assumptions have changed. For now we just iterate through the
1460 // bindings and check if any of the tracked symbols are NULL. This isn't
1461 // too bad since the number of symbols we will track in practice are
1462 // probably small and EvalAssume is only called at branches and a few
1463 // other places.
1464
1465 RefBindings B = GetRefBindings(*St);
1466
1467 if (B.isEmpty())
1468 return St;
1469
1470 bool changed = false;
1471
1472 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1473
1474 // Check if the symbol is null (or equal to any constant).
1475 // If this is the case, stop tracking the symbol.
1476
1477 if (St->getSymVal(I.getKey())) {
1478 changed = true;
1479 B = RefBFactory.Remove(B, I.getKey());
1480 }
1481 }
1482
1483 if (!changed)
1484 return St;
1485
1486 ValueState StImpl = *St;
1487 StImpl.CheckerState = B.getRoot();
1488 return Eng.getStateManager().getPersistentState(StImpl);
1489}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001490
1491CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001492 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001493 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001494
Ted Kremenek0d721572008-03-11 17:48:22 +00001495 // FIXME: This dispatch can potentially be sped up by unifiying it into
1496 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001497
Ted Kremenek0d721572008-03-11 17:48:22 +00001498 switch (E) {
1499 default:
1500 assert (false && "Unhandled CFRef transition.");
1501
1502 case DoNothing:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001503 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001504 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001505 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001506 break;
1507 }
1508
Ted Kremenek0d721572008-03-11 17:48:22 +00001509 return B;
1510
1511 case IncRef:
1512 switch (V.getKind()) {
1513 default:
1514 assert(false);
1515
1516 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001517 V = RefVal::makeOwned(V.getCount()+1);
1518 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001519
Ted Kremenek0d721572008-03-11 17:48:22 +00001520 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001521 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001522 break;
1523
1524 case RefVal::Released:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001525 if (isGCEnabled())
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001526 V = RefVal::makeOwned();
1527 else {
1528 V = RefVal::makeUseAfterRelease();
1529 hasErr = V.getKind();
1530 }
1531
Ted Kremenek0d721572008-03-11 17:48:22 +00001532 break;
1533 }
1534
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001535 break;
1536
Ted Kremenek0d721572008-03-11 17:48:22 +00001537 case DecRef:
1538 switch (V.getKind()) {
1539 default:
1540 assert (false);
1541
1542 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001543 unsigned Count = V.getCount();
1544 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001545 break;
1546 }
1547
Ted Kremenekc4f81022008-04-10 23:09:18 +00001548 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001549 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001550
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001551 if (Count > 0)
1552 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001553 else {
1554 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001555 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001556 }
1557
Ted Kremenek0d721572008-03-11 17:48:22 +00001558 break;
1559 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001560
1561 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001562 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001563 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001564 break;
1565 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001566
1567 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001568 }
1569
1570 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001571}
1572
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001573
1574//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001575// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001576//===----------------------------------------------------------------------===//
1577
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001578namespace {
1579
1580 //===-------------===//
1581 // Bug Descriptions. //
1582 //===-------------===//
1583
Ted Kremeneke3769852008-04-18 20:54:29 +00001584 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001585 protected:
1586 CFRefCount& TF;
1587
1588 public:
1589 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001590
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001591 CFRefCount& getTF() { return TF; }
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001592 const CFRefCount& getTF() const { return TF; }
1593
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001594 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001595 };
1596
1597 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1598 public:
1599 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1600
1601 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001602 return "Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001603 }
1604 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001605 return "Reference-counted object is used"
1606 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001607 }
1608
1609 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001610 };
1611
1612 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1613 public:
1614 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1615
1616 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001617 return "Bad Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001618 }
1619 virtual const char* getDescription() const {
1620 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001621 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001622 "The object is not owned at this point by the caller.";
1623 }
1624
1625 virtual void EmitWarnings(BugReporter& BR);
1626 };
1627
1628 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1629 public:
1630 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1631
1632 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001633 return getTF().isGCEnabled() ? "Memory Leak (GC)" : "Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001634 }
1635
1636 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001637 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001638 }
1639
1640 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001641 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001642 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001643 };
1644
1645 //===---------===//
1646 // Bug Reports. //
1647 //===---------===//
1648
1649 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1650 SymbolID Sym;
1651 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001652 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001653 : RangedBugReport(D, n), Sym(sym) {}
1654
1655 virtual ~CFRefReport() {}
1656
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001657 CFRefBug& getBugType() {
1658 return (CFRefBug&) RangedBugReport::getBugType();
1659 }
1660 const CFRefBug& getBugType() const {
1661 return (const CFRefBug&) RangedBugReport::getBugType();
1662 }
1663
1664 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1665 const SourceRange*& end) {
1666
Ted Kremenek198cae02008-05-02 20:53:50 +00001667 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001668 RangedBugReport::getRanges(BR, beg, end);
1669 else {
1670 beg = 0;
1671 end = 0;
1672 }
1673 }
1674
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001675 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1676 ExplodedNode<ValueState>* N);
1677
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001678 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001679
1680 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1681 ExplodedNode<ValueState>* PrevN,
1682 ExplodedGraph<ValueState>& G,
1683 BugReporter& BR);
1684 };
1685
1686
1687} // end anonymous namespace
1688
1689void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001690 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001691 Eng.Register(new UseAfterRelease(*this));
1692 Eng.Register(new BadRelease(*this));
1693 Eng.Register(new Leak(*this));
1694}
1695
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001696
1697static const char* Msgs[] = {
1698 "Code is compiled in garbage collection only mode" // GC only
1699 " (the bug occurs with garbage collection enabled).",
1700
1701 "Code is compiled without garbage collection.", // No GC.
1702
1703 "Code is compiled for use with and without garbage collection (GC)."
1704 " The bug occurs with GC enabled.", // Hybrid, with GC.
1705
1706 "Code is compiled for use with and without garbage collection (GC)."
1707 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1708};
1709
1710std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1711 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1712
1713 switch (TF.getLangOptions().getGCMode()) {
1714 default:
1715 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001716
1717 case LangOptions::GCOnly:
1718 assert (TF.isGCEnabled());
1719 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001720
1721 case LangOptions::NonGC:
1722 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001723 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1724
1725 case LangOptions::HybridGC:
1726 if (TF.isGCEnabled())
1727 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1728 else
1729 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1730 }
1731}
1732
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001733PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1734 ExplodedNode<ValueState>* PrevN,
1735 ExplodedGraph<ValueState>& G,
1736 BugReporter& BR) {
1737
1738 // Check if the type state has changed.
1739
1740 ValueState* PrevSt = PrevN->getState();
1741 ValueState* CurrSt = N->getState();
1742
1743 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1744 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1745
Ted Kremeneka8503952008-04-18 04:55:01 +00001746 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1747 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001748
Ted Kremeneka8503952008-04-18 04:55:01 +00001749 if (!CurrT)
1750 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001751
Ted Kremeneka8503952008-04-18 04:55:01 +00001752 const char* Msg = NULL;
1753 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001754
Ted Kremeneka8503952008-04-18 04:55:01 +00001755 if (!PrevT) {
1756
Ted Kremenek9363fd92008-05-05 17:53:17 +00001757 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1758
1759 if (CurrV.isOwned()) {
1760
1761 if (isa<CallExpr>(S))
1762 Msg = "Function call returns an object with a +1 retain count"
1763 " (owning reference).";
1764 else {
1765 assert (isa<ObjCMessageExpr>(S));
1766 Msg = "Method returns an object with a +1 retain count"
1767 " (owning reference).";
1768 }
1769 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001770 else {
1771 assert (CurrV.isNotOwned());
Ted Kremenek9363fd92008-05-05 17:53:17 +00001772
1773 if (isa<CallExpr>(S))
1774 Msg = "Function call returns an object with a +0 retain count"
1775 " (non-owning reference).";
1776 else {
1777 assert (isa<ObjCMessageExpr>(S));
1778 Msg = "Method returns an object with a +0 retain count"
1779 " (non-owning reference).";
1780 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001781 }
Ted Kremenek9363fd92008-05-05 17:53:17 +00001782
Ted Kremeneka8503952008-04-18 04:55:01 +00001783 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1784 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1785
1786 if (Expr* Exp = dyn_cast<Expr>(S))
1787 P->addRange(Exp->getSourceRange());
1788
1789 return P;
1790 }
1791
1792 // Determine if the typestate has changed.
1793
1794 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1795
1796 if (PrevV == CurrV)
1797 return NULL;
1798
1799 // The typestate has changed.
1800
1801 std::ostringstream os;
1802
1803 switch (CurrV.getKind()) {
1804 case RefVal::Owned:
1805 case RefVal::NotOwned:
1806 assert (PrevV.getKind() == CurrV.getKind());
1807
1808 if (PrevV.getCount() > CurrV.getCount())
1809 os << "Reference count decremented.";
1810 else
1811 os << "Reference count incremented.";
1812
Ted Kremenek9363fd92008-05-05 17:53:17 +00001813 if (unsigned Count = GetCount(CurrV)) {
1814
1815 os << " Object has +" << Count;
Ted Kremenek752b5842008-04-18 05:32:44 +00001816
Ted Kremenek9363fd92008-05-05 17:53:17 +00001817 if (Count > 1)
1818 os << " retain counts.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001819 else
Ted Kremenek9363fd92008-05-05 17:53:17 +00001820 os << " retain count.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001821 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001822
1823 Msg = os.str().c_str();
1824
1825 break;
1826
1827 case RefVal::Released:
1828 Msg = "Object released.";
1829 break;
1830
1831 case RefVal::ReturnedOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001832 Msg = "Object returned to caller as owning reference (single retain count"
1833 " transferred to caller).";
Ted Kremeneka8503952008-04-18 04:55:01 +00001834 break;
1835
1836 case RefVal::ReturnedNotOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001837 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremeneka8503952008-04-18 04:55:01 +00001838 break;
1839
1840 default:
1841 return NULL;
1842 }
1843
1844 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1845 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1846 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1847
1848 // Add the range by scanning the children of the statement for any bindings
1849 // to Sym.
1850
1851 ValueStateManager& VSM = BR.getEngine().getStateManager();
1852
1853 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1854 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1855 RVal X = VSM.GetRVal(CurrSt, Exp);
1856
1857 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1858 if (SV->getSymbol() == Sym) {
1859 P->addRange(Exp->getSourceRange()); break;
1860 }
1861 }
1862
1863 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001864}
1865
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001866PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremenekea794e92008-05-05 18:50:19 +00001867 ExplodedNode<ValueState>* EndN) {
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001868
1869 if (!getBugType().isLeak())
Ted Kremenekea794e92008-05-05 18:50:19 +00001870 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001871
Ted Kremenek9363fd92008-05-05 17:53:17 +00001872 typedef CFRefCount::RefBindings RefBindings;
1873
1874 // Get the retain count.
1875 unsigned long RetCount = 0;
1876
1877 {
Ted Kremenekea794e92008-05-05 18:50:19 +00001878 ValueState* St = EndN->getState();
Ted Kremenek9363fd92008-05-05 17:53:17 +00001879 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1880 RefBindings::TreeTy* T = B.SlimFind(Sym);
1881 assert (T);
1882 RetCount = GetCount(T->getValue().second);
1883 }
1884
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001885 // We are a leak. Walk up the graph to get to the first node where the
1886 // symbol appeared.
1887
Ted Kremenekea794e92008-05-05 18:50:19 +00001888 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001889 ExplodedNode<ValueState>* Last = N;
Ted Kremenekea794e92008-05-05 18:50:19 +00001890
Ted Kremenek198cae02008-05-02 20:53:50 +00001891 // Find the first node that referred to the tracked symbol. We also
1892 // try and find the first VarDecl the value was stored to.
1893
1894 VarDecl* FirstDecl = 0;
Ted Kremenekea794e92008-05-05 18:50:19 +00001895
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001896 while (N) {
1897 ValueState* St = N->getState();
1898 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001899 RefBindings::TreeTy* T = B.SlimFind(Sym);
1900
1901 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001902 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00001903
1904 VarDecl* VD = 0;
1905
1906 // Determine if there is an LVal binding to the symbol.
1907 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1908 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1909 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1910 continue;
1911
1912 if (VD) { // Multiple decls map to this symbol.
1913 VD = 0;
1914 break;
1915 }
1916
1917 VD = I->first;
1918 }
1919
1920 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001921
1922 Last = N;
1923 N = N->pred_empty() ? NULL : *(N->pred_begin());
1924 }
1925
Ted Kremenekea794e92008-05-05 18:50:19 +00001926 // Get the allocate site.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001927
1928 assert (Last);
1929 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1930
Ted Kremenekea794e92008-05-05 18:50:19 +00001931 SourceManager& SMgr = BR.getContext().getSourceManager();
1932 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001933
Ted Kremenekea794e92008-05-05 18:50:19 +00001934 // Get the leak site. We may have multiple ExplodedNodes (one with the
1935 // leak) that occur on the same line number; if the node with the leak
1936 // has any immediate predecessor nodes with the same line number, find
1937 // any transitive-successors that have a different statement and use that
1938 // line number instead. This avoids emiting a diagnostic like:
1939 //
1940 // // 'y' is leaked.
1941 // int x = foo(y);
1942 //
1943 // instead we want:
1944 //
1945 // int x = foo(y);
1946 // // 'y' is leaked.
1947
1948 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
1949 assert (S);
1950 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
1951
1952 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
1953 // it occur on the same line?
1954
1955 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
1956 N = *(EndN->pred_begin());
1957
1958 do {
1959 ProgramPoint P = N->getLocation();
1960
1961 if (!isa<PostStmt>(P))
1962 break;
1963
1964 // Predecessor at same line?
1965
1966 Stmt* SPred = cast<PostStmt>(P).getStmt();
1967
1968 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine)
1969 break;
1970
1971 // The predecessor (where the object was not yet leaked) is a statement
1972 // on the same line. Get the first successor statement that appears
1973 // on a different line. For this operation, we can traverse the
1974 // non-trimmed graph.
1975
1976 N = getEndNode(); // This is the node where the leak occured in the
1977 // original graph.
1978
1979 while (!N->succ_empty()) {
1980
1981 N = *(N->succ_begin());
1982 ProgramPoint P = N->getLocation();
1983
1984 if (!isa<PostStmt>(P))
1985 continue;
1986
1987 Stmt* SSucc = cast<PostStmt>(P).getStmt();
1988
1989 if (SMgr.getLogicalLineNumber(SSucc->getLocStart()) != EndLine) {
1990 S = SSucc;
1991 break;
1992 }
1993 }
1994 }
1995 while (false);
1996
1997 // Construct the location.
1998
1999 FullSourceLoc L(S->getLocStart(), SMgr);
2000
2001 // Generate the diagnostic.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002002 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00002003
Ted Kremenekea794e92008-05-05 18:50:19 +00002004 os << "Object allocated on line " << AllocLine;
Ted Kremenek198cae02008-05-02 20:53:50 +00002005
2006 if (FirstDecl)
2007 os << " and stored into '" << FirstDecl->getName() << '\'';
2008
Ted Kremenek9363fd92008-05-05 17:53:17 +00002009 os << " is no longer referenced after this point and has a retain count of +"
2010 << RetCount << " (object leaked).";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002011
Ted Kremenekea794e92008-05-05 18:50:19 +00002012 return new PathDiagnosticPiece(L, os.str());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00002013}
2014
Ted Kremenek7d421f32008-04-09 23:49:11 +00002015void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002016
Ted Kremenek7d421f32008-04-09 23:49:11 +00002017 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2018 E = TF.use_after_end(); I != E; ++I) {
2019
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002020 CFRefReport report(*this, I->first, I->second.second);
2021 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00002022 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002023 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00002024}
2025
2026void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002027
Ted Kremenek7d421f32008-04-09 23:49:11 +00002028 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2029 E = TF.bad_release_end(); I != E; ++I) {
2030
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002031 CFRefReport report(*this, I->first, I->second.second);
2032 report.addRange(I->second.first->getSourceRange());
2033 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00002034 }
2035}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00002036
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002037void Leak::EmitWarnings(BugReporter& BR) {
2038
2039 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2040 E = TF.leaks_end(); I != E; ++I) {
2041
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002042 std::vector<SymbolID>& SymV = *(I->second);
2043 unsigned n = SymV.size();
2044
2045 for (unsigned i = 0; i < n; ++i) {
2046 CFRefReport report(*this, I->first, SymV[i]);
2047 BR.EmitWarning(report);
2048 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002049 }
2050}
2051
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00002052void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2053 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2054 I!=E; ++I)
2055 Nodes.push_back(I->first);
2056}
2057
Ted Kremeneka7338b42008-03-11 06:39:11 +00002058//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00002059// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00002060//===----------------------------------------------------------------------===//
2061
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002062GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00002063 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002064 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00002065 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00002066}