blob: d6027f9f6be5515162c3b02681d8285f12405036 [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
41//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +000042// Symbolic Evaluation of Reference Counting Logic
43//===----------------------------------------------------------------------===//
44
Ted Kremeneka7338b42008-03-11 06:39:11 +000045namespace {
46 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenekae855d42008-04-24 17:22:33 +000047 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremeneka7338b42008-03-11 06:39:11 +000048}
Ted Kremenek827f93b2008-03-06 00:08:09 +000049
Ted Kremeneka7338b42008-03-11 06:39:11 +000050namespace llvm {
51 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +000052 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenekae855d42008-04-24 17:22:33 +000053 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
54 ID.AddInteger(I->first);
55 ID.AddInteger((unsigned) I->second);
56 }
Ted Kremeneka4c74292008-04-10 22:58:08 +000057 }
Ted Kremeneka7338b42008-03-11 06:39:11 +000058 };
59} // end llvm namespace
60
61namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +000062
Ted Kremeneka7338b42008-03-11 06:39:11 +000063class RetEffect {
64public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000065 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
66 NotOwnedSymbol = 0x3 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000067
68private:
69 unsigned Data;
Ted Kremeneka4c74292008-04-10 22:58:08 +000070 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000071
Ted Kremeneka7338b42008-03-11 06:39:11 +000072public:
73
74 Kind getKind() const { return (Kind) (Data & 0x3); }
75
76 unsigned getValue() const {
77 assert(getKind() == Alias);
Ted Kremeneka4c74292008-04-10 22:58:08 +000078 return Data >> 2;
Ted Kremeneka7338b42008-03-11 06:39:11 +000079 }
Ted Kremenekffefc352008-04-11 22:25:11 +000080
Ted Kremeneka7338b42008-03-11 06:39:11 +000081 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000082
Ted Kremeneka7338b42008-03-11 06:39:11 +000083 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000084
Ted Kremeneka7338b42008-03-11 06:39:11 +000085 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
86
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000087 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
88
Ted Kremeneka7338b42008-03-11 06:39:11 +000089 operator Kind() const { return getKind(); }
90
91 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
92};
93
94
95class CFRefSummary : public llvm::FoldingSetNode {
96 ArgEffects* Args;
97 RetEffect Ret;
98public:
99
100 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
101
102 unsigned getNumArgs() const { return Args->size(); }
103
Ted Kremenek0d721572008-03-11 17:48:22 +0000104 ArgEffect getArg(unsigned idx) const {
Ted Kremenekae855d42008-04-24 17:22:33 +0000105 if (!Args)
106 return DoNothing;
107
108 // If Args is present, it is likely to contain only 1 element.
109 // Just do a linear search. Do it from the back because functions with
110 // large numbers of arguments will be tail heavy with respect to which
111 // argument they actually modify with respect to the reference count.
112
113 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
114 I!=E; ++I) {
115
116 if (idx > I->first)
117 return DoNothing;
118
119 if (idx == I->first)
120 return I->second;
121 }
122
123 return DoNothing;
Ted Kremenek0d721572008-03-11 17:48:22 +0000124 }
125
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000126 RetEffect getRet() const {
127 return Ret;
128 }
129
Ted Kremeneka7338b42008-03-11 06:39:11 +0000130 typedef ArgEffects::const_iterator arg_iterator;
131
132 arg_iterator begin_args() const { return Args->begin(); }
133 arg_iterator end_args() const { return Args->end(); }
134
135 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
136 ID.AddPointer(A);
137 ID.Add(R);
138 }
139
140 void Profile(llvm::FoldingSetNodeID& ID) const {
141 Profile(ID, Args, Ret);
142 }
143};
144
145
146class CFRefSummaryManager {
147 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
148 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
149 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
150
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000151 ASTContext& Ctx;
152 const bool GCEnabled;
153
Ted Kremeneka4c74292008-04-10 22:58:08 +0000154 SummarySetTy SummarySet;
155 SummaryMapTy SummaryMap;
156 AESetTy AESet;
157 llvm::BumpPtrAllocator BPAlloc;
Ted Kremenekae855d42008-04-24 17:22:33 +0000158 ArgEffects ScratchArgs;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000159
160 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000161
Ted Kremenek562c1302008-05-05 16:51:50 +0000162 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
163 CFRefSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000164
Ted Kremenek562c1302008-05-05 16:51:50 +0000165 CFRefSummary* getNSSummary(FunctionDecl* FD, const char* FName);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000166 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
167
Ted Kremenek562c1302008-05-05 16:51:50 +0000168 CFRefSummary* getCFSummaryCreateRule(FunctionDecl* FD);
169 CFRefSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000170
171 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenekae855d42008-04-24 17:22:33 +0000172
Ted Kremeneka7338b42008-03-11 06:39:11 +0000173public:
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000174 CFRefSummaryManager(ASTContext& ctx, bool gcenabled)
175 : Ctx(ctx), GCEnabled(gcenabled) {}
176
Ted Kremeneka7338b42008-03-11 06:39:11 +0000177 ~CFRefSummaryManager();
178
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000179 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000180};
181
182} // end anonymous namespace
183
184//===----------------------------------------------------------------------===//
185// Implementation of checker data structures.
186//===----------------------------------------------------------------------===//
187
188CFRefSummaryManager::~CFRefSummaryManager() {
189
190 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
191 // mitigating the need to do explicit cleanup of the
192 // Argument-Effect summaries.
193
194 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
195 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000196}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000197
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000198ArgEffects* CFRefSummaryManager::getArgEffects() {
199
Ted Kremenekae855d42008-04-24 17:22:33 +0000200 if (ScratchArgs.empty())
201 return NULL;
202
203 // Compute a profile for a non-empty ScratchArgs.
204
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000205 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000206
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000207 profile.Add(ScratchArgs);
208 void* InsertPos;
209
Ted Kremenekae855d42008-04-24 17:22:33 +0000210 // Look up the uniqued copy, or create a new one.
211
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000212 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
213 AESet.FindNodeOrInsertPos(profile, InsertPos);
214
Ted Kremenekae855d42008-04-24 17:22:33 +0000215 if (E) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000216 ScratchArgs.clear();
217 return &E->getValue();
218 }
219
220 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
221 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
222
223 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
224 AESet.InsertNode(E, InsertPos);
225
226 ScratchArgs.clear();
227 return &E->getValue();
228}
229
230CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
231 RetEffect RE) {
232
Ted Kremenekae855d42008-04-24 17:22:33 +0000233 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000234 llvm::FoldingSetNodeID profile;
235 CFRefSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000236
Ted Kremenekae855d42008-04-24 17:22:33 +0000237 // Look up the uniqued summary, or create one if it doesn't exist.
238 void* InsertPos;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000239 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
240
241 if (Summ)
242 return Summ;
243
Ted Kremenekae855d42008-04-24 17:22:33 +0000244 // Create the summary and return it.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000245 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
246 new (Summ) CFRefSummary(AE, RE);
247 SummarySet.InsertNode(Summ, InsertPos);
248
249 return Summ;
250}
251
252
253CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
254 ASTContext& Ctx) {
255
256 SourceLocation Loc = FD->getLocation();
257
258 if (!Loc.isFileID())
259 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000260
Ted Kremenekae855d42008-04-24 17:22:33 +0000261 // Look up a summary in our cache of FunctionDecls -> Summaries.
262 SummaryMapTy::iterator I = SummaryMap.find(FD);
263
264 if (I != SummaryMap.end())
265 return I->second;
266
267 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000268 const char* FName = FD->getIdentifier()->getName();
269
Ted Kremenek562c1302008-05-05 16:51:50 +0000270 CFRefSummary *S = 0;
271
272 if (FName[0] == 'C' && FName[1] == 'F')
273 S = getCFSummary(FD, FName);
274 else if (FName[0] == 'N' && FName[1] == 'S')
275 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000276
Ted Kremenek562c1302008-05-05 16:51:50 +0000277 SummaryMap[FD] = S;
278 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000279}
280
Ted Kremenek562c1302008-05-05 16:51:50 +0000281CFRefSummary* CFRefSummaryManager::getNSSummary(FunctionDecl* FD,
282 const char* FName) {
283 FName += 2;
284
285 if (strcmp(FName, "MakeCollectable") == 0)
286 return getUnarySummary(FD, cfmakecollectable);
287
288 return 0;
289}
290
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000291CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
292 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000293
294 FName += 2;
295
296 if (strcmp(FName, "Retain") == 0)
297 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000298
Ted Kremenek562c1302008-05-05 16:51:50 +0000299 if (strcmp(FName, "Release") == 0)
300 return getUnarySummary(FD, cfrelease);
301
302 if (strcmp(FName, "MakeCollectable") == 0)
303 return getUnarySummary(FD, cfmakecollectable);
304
305 if (strstr(FName, "Create") || strstr(FName, "Copy"))
306 return getCFSummaryCreateRule(FD);
307
308 if (strstr(FName, "Get"))
309 return getCFSummaryGetRule(FD);
310
311 return 0;
312}
313
314CFRefSummary*
315CFRefSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000316
317 FunctionTypeProto* FT =
318 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
319
Ted Kremenek562c1302008-05-05 16:51:50 +0000320 if (FT) {
321
322 if (FT->getNumArgs() != 1)
323 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000324
Ted Kremenek562c1302008-05-05 16:51:50 +0000325 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
326
327 if (!ArgT)
328 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000329
Ted Kremenek562c1302008-05-05 16:51:50 +0000330 if (!ArgT->isPointerType())
331 return NULL;
332 }
Ted Kremenek33661802008-05-01 21:31:50 +0000333
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000334 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000335
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000336 switch (func) {
337 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000338 ScratchArgs.push_back(std::make_pair(0, IncRef));
339 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
340 }
341
342 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000343 ScratchArgs.push_back(std::make_pair(0, DecRef));
344 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
345 }
346
347 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000348 if (GCEnabled)
349 ScratchArgs.push_back(std::make_pair(0, DecRef));
350
Ted Kremenek562c1302008-05-05 16:51:50 +0000351 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000352 }
353
354 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000355 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000356 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000357}
358
359static bool isCFRefType(QualType T) {
360
361 if (!T->isPointerType())
362 return false;
363
364 // Check the typedef for the name "CF" and the substring "Ref".
365
366 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
367
368 if (!TD)
369 return false;
370
371 const char* TDName = TD->getDecl()->getIdentifier()->getName();
372 assert (TDName);
373
374 if (TDName[0] != 'C' || TDName[1] != 'F')
375 return false;
376
377 if (strstr(TDName, "Ref") == 0)
378 return false;
379
380 return true;
381}
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000382
383CFRefSummary*
Ted Kremenek562c1302008-05-05 16:51:50 +0000384CFRefSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000385
Ted Kremenek562c1302008-05-05 16:51:50 +0000386 FunctionTypeProto* FT =
387 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
388
389 if (FT && !isCFRefType(FT->getResultType()))
390 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000391
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000392 // FIXME: Add special-cases for functions that retain/release. For now
393 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000394
395 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000396 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
397}
398
399CFRefSummary*
Ted Kremenek562c1302008-05-05 16:51:50 +0000400CFRefSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000401
Ted Kremenek562c1302008-05-05 16:51:50 +0000402 FunctionTypeProto* FT =
403 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000404
Ted Kremenek562c1302008-05-05 16:51:50 +0000405 if (FT) {
406 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000407
Ted Kremenek562c1302008-05-05 16:51:50 +0000408 // FIXME: For now we assume that all pointer types returned are referenced
409 // counted. Since this is the "Get" rule, we assume non-ownership, which
410 // works fine for things that are not reference counted. We do this because
411 // some generic data structures return "void*". We need something better
412 // in the future.
413
414 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
415 return 0;
416 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000417
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000418 // FIXME: Add special-cases for functions that retain/release. For now
419 // just handle the default case.
420
Ted Kremenekae855d42008-04-24 17:22:33 +0000421 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000422 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
423}
424
Ted Kremeneka7338b42008-03-11 06:39:11 +0000425//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000426// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000427//===----------------------------------------------------------------------===//
428
Ted Kremeneka7338b42008-03-11 06:39:11 +0000429namespace {
430
Ted Kremenek7d421f32008-04-09 23:49:11 +0000431class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000432public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000433
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000434 enum Kind {
435 Owned = 0, // Owning reference.
436 NotOwned, // Reference is not owned by still valid (not freed).
437 Released, // Object has been released.
438 ReturnedOwned, // Returned object passes ownership to caller.
439 ReturnedNotOwned, // Return object does not pass ownership to caller.
440 ErrorUseAfterRelease, // Object used after released.
441 ErrorReleaseNotOwned, // Release of an object that was not owned.
442 ErrorLeak // A memory leak due to excessive reference counts.
443 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000444
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000445private:
446
447 Kind kind;
448 unsigned Cnt;
449
450 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
451
452 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000453
454public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000455
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000456 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000457
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000458 unsigned getCount() const { return Cnt; }
459
460 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000461
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000462 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
463
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000464 static bool isLeak(Kind k) { return k == ErrorLeak; }
465
Ted Kremenekffefc352008-04-11 22:25:11 +0000466 bool isOwned() const {
467 return getKind() == Owned;
468 }
469
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000470 bool isNotOwned() const {
471 return getKind() == NotOwned;
472 }
473
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000474 bool isReturnedOwned() const {
475 return getKind() == ReturnedOwned;
476 }
477
478 bool isReturnedNotOwned() const {
479 return getKind() == ReturnedNotOwned;
480 }
481
482 bool isNonLeakError() const {
483 Kind k = getKind();
484 return isError(k) && !isLeak(k);
485 }
486
487 // State creation: normal state.
488
Ted Kremenekc4f81022008-04-10 23:09:18 +0000489 static RefVal makeOwned(unsigned Count = 0) {
490 return RefVal(Owned, Count);
491 }
492
493 static RefVal makeNotOwned(unsigned Count = 0) {
494 return RefVal(NotOwned, Count);
495 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000496
497 static RefVal makeReturnedOwned(unsigned Count) {
498 return RefVal(ReturnedOwned, Count);
499 }
500
501 static RefVal makeReturnedNotOwned() {
502 return RefVal(ReturnedNotOwned);
503 }
504
505 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000506
Ted Kremenek9363fd92008-05-05 17:53:17 +0000507 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000508 static RefVal makeReleased() { return RefVal(Released); }
509 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
510 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000511
512 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000513
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000514 bool operator==(const RefVal& X) const {
515 return kind == X.kind && Cnt == X.Cnt;
516 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000517
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000518 void Profile(llvm::FoldingSetNodeID& ID) const {
519 ID.AddInteger((unsigned) kind);
520 ID.AddInteger(Cnt);
521 }
522
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000523 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000524};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000525
526void RefVal::print(std::ostream& Out) const {
527 switch (getKind()) {
528 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000529 case Owned: {
530 Out << "Owned";
531 unsigned cnt = getCount();
532 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000533 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000534 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000535
Ted Kremenekc4f81022008-04-10 23:09:18 +0000536 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000537 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000538 unsigned cnt = getCount();
539 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000540 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000541 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000542
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000543 case ReturnedOwned: {
544 Out << "ReturnedOwned";
545 unsigned cnt = getCount();
546 if (cnt) Out << " (+ " << cnt << ")";
547 break;
548 }
549
550 case ReturnedNotOwned: {
551 Out << "ReturnedNotOwned";
552 unsigned cnt = getCount();
553 if (cnt) Out << " (+ " << cnt << ")";
554 break;
555 }
556
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000557 case Released:
558 Out << "Released";
559 break;
560
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000561 case ErrorLeak:
562 Out << "Leaked";
563 break;
564
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000565 case ErrorUseAfterRelease:
566 Out << "Use-After-Release [ERROR]";
567 break;
568
569 case ErrorReleaseNotOwned:
570 Out << "Release of Not-Owned [ERROR]";
571 break;
572 }
573}
Ted Kremenek0d721572008-03-11 17:48:22 +0000574
Ted Kremenek9363fd92008-05-05 17:53:17 +0000575static inline unsigned GetCount(RefVal V) {
576 switch (V.getKind()) {
577 default:
578 return V.getCount();
579
580 case RefVal::Owned:
581 return V.getCount()+1;
582 }
583}
584
Ted Kremenek7aef4842008-04-16 20:40:59 +0000585//===----------------------------------------------------------------------===//
586// Transfer functions.
587//===----------------------------------------------------------------------===//
588
Ted Kremenek7d421f32008-04-09 23:49:11 +0000589class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000590public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000591 // Type definitions.
592
Ted Kremenek0d721572008-03-11 17:48:22 +0000593 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000594 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000595
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000596 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
597 ReleasesNotOwnedTy;
598
599 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
600
601 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000602 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000603
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000604 class BindingsPrinter : public ValueState::CheckerStatePrinter {
605 public:
606 virtual void PrintCheckerState(std::ostream& Out, void* State,
607 const char* nl, const char* sep);
608 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000609
610private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000611 // Instance variables.
612
Ted Kremenek102d42e2008-04-29 05:13:59 +0000613 CFRefSummaryManager Summaries;
Ted Kremenek2f62f352008-05-02 18:01:49 +0000614 const bool GCEnabled;
615 const bool EmitStandardWarnings;
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000616 const LangOptions& LOpts;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000617 RefBFactoryTy RefBFactory;
618
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000619 UseAfterReleasesTy UseAfterReleases;
620 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000621 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000622
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000623 BindingsPrinter Printer;
624
Ted Kremenek1feab292008-04-16 04:28:53 +0000625 Selector RetainSelector;
626 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000627 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000628
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000629public:
630
Ted Kremeneka7338b42008-03-11 06:39:11 +0000631 static RefBindings GetRefBindings(ValueState& StImpl) {
632 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
633 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000634
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000635private:
636
Ted Kremeneka7338b42008-03-11 06:39:11 +0000637 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
638 StImpl.CheckerState = B.getRoot();
639 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000640
Ted Kremeneka7338b42008-03-11 06:39:11 +0000641 RefBindings Remove(RefBindings B, SymbolID sym) {
642 return RefBFactory.Remove(B, sym);
643 }
644
Ted Kremenek0d721572008-03-11 17:48:22 +0000645 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000646 RefVal::Kind& hasErr);
647
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000648 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
649 GRStmtNodeBuilder<ValueState>& Builder,
650 Expr* NodeExpr, Expr* ErrorExpr,
651 ExplodedNode<ValueState>* Pred,
652 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000653 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000654
655 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
656 SymbolID sid, RefVal V, bool& hasLeak);
657
658 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
659 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000660
661public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000662
Ted Kremenek2f62f352008-05-02 18:01:49 +0000663 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
664 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000665 : Summaries(Ctx, gcenabled),
Ted Kremenek102d42e2008-04-29 05:13:59 +0000666 GCEnabled(gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000667 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000668 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000669 RetainSelector(GetNullarySelector("retain", Ctx)),
670 ReleaseSelector(GetNullarySelector("release", Ctx)),
671 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000672
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000673 virtual ~CFRefCount() {
674 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
675 delete I->second;
676 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000677
678 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000679
680 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
681 return &Printer;
682 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000683
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000684 bool isGCEnabled() const { return GCEnabled; }
685 const LangOptions& getLangOptions() const { return LOpts; }
686
Ted Kremeneka7338b42008-03-11 06:39:11 +0000687 // Calls.
688
689 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000690 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000691 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000692 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000693 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000694
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000695 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
696 GRExprEngine& Engine,
697 GRStmtNodeBuilder<ValueState>& Builder,
698 ObjCMessageExpr* ME,
699 ExplodedNode<ValueState>* Pred);
700
701 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
702 GRExprEngine& Engine,
703 GRStmtNodeBuilder<ValueState>& Builder,
704 ObjCMessageExpr* ME,
705 ExplodedNode<ValueState>* Pred);
706
Ted Kremenek7aef4842008-04-16 20:40:59 +0000707 // Stores.
708
709 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
710 GRExprEngine& Engine,
711 GRStmtNodeBuilder<ValueState>& Builder,
712 Expr* E, ExplodedNode<ValueState>* Pred,
713 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000714 // End-of-path.
715
716 virtual void EvalEndPath(GRExprEngine& Engine,
717 GREndPathNodeBuilder<ValueState>& Builder);
718
Ted Kremenek541db372008-04-24 23:57:27 +0000719 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
720 GRExprEngine& Engine,
721 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000722 ExplodedNode<ValueState>* Pred,
723 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000724 ValueState* St,
725 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000726 // Return statements.
727
728 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
729 GRExprEngine& Engine,
730 GRStmtNodeBuilder<ValueState>& Builder,
731 ReturnStmt* S,
732 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +0000733
734 // Assumptions.
735
736 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
737 RVal Cond, bool Assumption, bool& isFeasible);
738
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000739 // Error iterators.
740
741 typedef UseAfterReleasesTy::iterator use_after_iterator;
742 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000743 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000744
Ted Kremenek7d421f32008-04-09 23:49:11 +0000745 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
746 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000747
Ted Kremenek7d421f32008-04-09 23:49:11 +0000748 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
749 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000750
751 leaks_iterator leaks_begin() { return Leaks.begin(); }
752 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000753};
754
755} // end anonymous namespace
756
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000757
Ted Kremenek7d421f32008-04-09 23:49:11 +0000758
759
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000760void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
761 void* State, const char* nl,
762 const char* sep) {
763 RefBindings B((RefBindings::TreeTy*) State);
764
765 if (State)
766 Out << sep << nl;
767
768 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
769 Out << (*I).first << " : ";
770 (*I).second.print(Out);
771 Out << nl;
772 }
773}
774
Ted Kremenek455dd862008-04-11 20:23:24 +0000775static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
776 return Summ ? Summ->getArg(idx) : DoNothing;
777}
778
779static inline RetEffect GetRetE(CFRefSummary* Summ) {
780 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
781}
782
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000783void CFRefCount::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 Kremenek1feab292008-04-16 04:28:53 +0000789 Builder.BuildSinks = true;
790 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
791
792 if (!N) return;
793
794 switch (hasErr) {
795 default: assert(false);
796 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000797 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000798 break;
799
800 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000801 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000802 break;
803 }
804}
805
Ted Kremenek827f93b2008-03-06 00:08:09 +0000806void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000807 GRExprEngine& Eng,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000808 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000809 CallExpr* CE, RVal L,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000810 ExplodedNode<ValueState>* Pred) {
811
Ted Kremenekce0767f2008-03-12 21:06:49 +0000812 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000813
Ted Kremenek73ba0472008-04-14 17:45:13 +0000814 CFRefSummary* Summ = NULL;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000815
816 // Get the summary.
Ted Kremenek827f93b2008-03-06 00:08:09 +0000817
Ted Kremenek73ba0472008-04-14 17:45:13 +0000818 if (isa<lval::FuncVal>(L)) {
819 lval::FuncVal FV = cast<lval::FuncVal>(L);
820 FunctionDecl* FD = FV.getDecl();
821 Summ = Summaries.getSummary(FD, Eng.getContext());
822 }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000823
Ted Kremeneka7338b42008-03-11 06:39:11 +0000824 // Get the state.
825
826 ValueState* St = Builder.GetState(Pred);
827
828 // Evaluate the effects of the call.
829
830 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000831 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek455dd862008-04-11 20:23:24 +0000832
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000833 // This function has a summary. Evaluate the effect of the arguments.
834
835 unsigned idx = 0;
836
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000837 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000838 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000839
840 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
841 I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000842
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000843 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000844
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000845 if (isa<lval::SymbolVal>(V)) {
846 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000847 RefBindings B = GetRefBindings(StVals);
848
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000849 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000850 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000851 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000852
Ted Kremenek1feab292008-04-16 04:28:53 +0000853 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000854 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000855 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000856 break;
857 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000858 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000859 }
860 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
861
862 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
863 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000864 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000865 }
Ted Kremenekbe621292008-04-22 21:39:21 +0000866 else if (isa<nonlval::LValAsInteger>(V))
867 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000868 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000869
870 St = StateMgr.getPersistentState(StVals);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000871
Ted Kremenek1feab292008-04-16 04:28:53 +0000872 if (hasErr) {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000873 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
874 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000875 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000876 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000877
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000878 // Finally, consult the summary for the return value.
879
Ted Kremenek455dd862008-04-11 20:23:24 +0000880 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000881
882 switch (RE.getKind()) {
883 default:
884 assert (false && "Unhandled RetEffect."); break;
885
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000886 case RetEffect::NoRet:
Ted Kremenek455dd862008-04-11 20:23:24 +0000887
888 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000889 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
890 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000891
892 if (CE->getType() != Eng.getContext().VoidTy) {
893 unsigned Count = Builder.getCurrentBlockCount();
894 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
895
896 RVal X = CE->getType()->isPointerType()
897 ? cast<RVal>(lval::SymbolVal(Sym))
898 : cast<RVal>(nonlval::SymbolVal(Sym));
899
900 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
901 }
902
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000903 break;
904
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000905 case RetEffect::Alias: {
906 unsigned idx = RE.getValue();
907 assert (idx < CE->getNumArgs());
908 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenekce0767f2008-03-12 21:06:49 +0000909 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000910 break;
911 }
912
913 case RetEffect::OwnedSymbol: {
914 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000915 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000916
917 ValueState StImpl = *St;
918 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000919 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000920
921 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
922 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000923 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000924
925 break;
926 }
927
928 case RetEffect::NotOwnedSymbol: {
929 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000930 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000931
932 ValueState StImpl = *St;
933 RefBindings B = GetRefBindings(StImpl);
934 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
935
936 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
937 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000938 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000939
940 break;
941 }
942 }
943
Ted Kremenekf10f2882008-03-21 21:30:14 +0000944 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek827f93b2008-03-06 00:08:09 +0000945}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000946
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000947
948void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
949 GRExprEngine& Eng,
950 GRStmtNodeBuilder<ValueState>& Builder,
951 ObjCMessageExpr* ME,
952 ExplodedNode<ValueState>* Pred) {
953
Ted Kremenek33661802008-05-01 21:31:50 +0000954 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
955 return;
956
957 // The basic transfer function logic for message expressions does nothing.
958 // We just invalidate all arguments passed in by references.
959
960 ValueStateManager& StateMgr = Eng.getStateManager();
961 ValueState* St = Builder.GetState(Pred);
962 RefBindings B = GetRefBindings(*St);
963
964 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
965 I != E; ++I) {
966
967 RVal V = StateMgr.GetRVal(St, *I);
968
969 if (isa<LVal>(V)) {
970
971 LVal lv = cast<LVal>(V);
972
973 // Did the lval bind to a symbol?
974 RVal X = StateMgr.GetRVal(St, lv);
975
976 if (isa<lval::SymbolVal>(X)) {
Ted Kremenek6a24ec02008-05-01 23:38:35 +0000977 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
Ted Kremenek33661802008-05-01 21:31:50 +0000978 B = Remove(B, Sym);
979
980 // Create a new state with the updated bindings.
981 ValueState StVals = *St;
982 SetRefBindings(StVals, B);
983 St = StateMgr.getPersistentState(StVals);
984 }
985
986 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
987 }
988 }
989
990 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000991}
992
993bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
994 GRExprEngine& Eng,
995 GRStmtNodeBuilder<ValueState>& Builder,
996 ObjCMessageExpr* ME,
997 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000998
999 if (GCEnabled)
1000 return true;
1001
Ted Kremenek1feab292008-04-16 04:28:53 +00001002 // Handle "toll-free bridging" of calls to "Release" and "Retain".
1003
1004 // FIXME: track the underlying object type associated so that we can
1005 // flag illegal uses of toll-free bridging (or at least handle it
1006 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001007
1008 Selector S = ME->getSelector();
1009
1010 if (!S.isUnarySelector())
1011 return true;
1012
Ted Kremenek1feab292008-04-16 04:28:53 +00001013 Expr* Receiver = ME->getReceiver();
1014
1015 if (!Receiver)
1016 return true;
1017
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001018 // Check if we are calling "autorelease".
1019
1020 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001021
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001022 if (S == AutoreleaseSelector)
1023 mode = IsAutorelease;
1024 else if (S == RetainSelector)
1025 mode = IsRetain;
1026 else if (S == ReleaseSelector)
1027 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001028
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001029 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001030 return true;
1031
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001032 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001033 ValueStateManager& StateMgr = Eng.getStateManager();
1034 ValueState* St = Builder.GetState(Pred);
1035 RVal V = StateMgr.GetRVal(St, Receiver);
1036
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001037 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001038 if (!isa<lval::SymbolVal>(V))
1039 return true;
1040
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001041 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001042 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1043 RefBindings B = GetRefBindings(*St);
1044
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001045 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001046 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001047
Ted Kremenek1feab292008-04-16 04:28:53 +00001048 if (!T)
1049 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001050
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001051 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001052
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001053 // Update the bindings.
1054 switch (mode) {
1055 case IsNone:
1056 assert(false);
1057
1058 case IsRelease:
1059 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1060 break;
1061
1062 case IsRetain:
1063 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1064 break;
1065
1066 case IsAutorelease:
1067 // For now we just stop tracking a value if we see
1068 // it sent "autorelease." In the future we can potentially
1069 // track the associated pool.
1070 B = Remove(B, Sym);
1071 break;
1072 }
1073
1074 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001075 ValueState StVals = *St;
1076 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001077 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001078
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001079 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001080 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001081 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001082 else
1083 Builder.MakeNode(Dst, ME, Pred, St);
1084
1085 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001086}
1087
Ted Kremenek7aef4842008-04-16 20:40:59 +00001088// Stores.
1089
1090void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1091 GRExprEngine& Eng,
1092 GRStmtNodeBuilder<ValueState>& Builder,
1093 Expr* E, ExplodedNode<ValueState>* Pred,
1094 ValueState* St, RVal TargetLV, RVal Val) {
1095
1096 // Check if we have a binding for "Val" and if we are storing it to something
1097 // we don't understand or otherwise the value "escapes" the function.
1098
1099 if (!isa<lval::SymbolVal>(Val))
1100 return;
1101
1102 // Are we storing to something that causes the value to "escape"?
1103
1104 bool escapes = false;
1105
1106 if (!isa<lval::DeclVal>(TargetLV))
1107 escapes = true;
1108 else
1109 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1110
1111 if (!escapes)
1112 return;
1113
1114 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1115 RefBindings B = GetRefBindings(*St);
1116 RefBindings::TreeTy* T = B.SlimFind(Sym);
1117
1118 if (!T)
1119 return;
1120
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001121 // Nuke the binding.
1122 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001123
1124 // Hand of the remaining logic to the parent implementation.
1125 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1126}
1127
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001128
1129ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1130 SymbolID sid) {
1131 ValueState StImpl = *St;
1132 RefBindings B = GetRefBindings(StImpl);
1133 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1134 return VMgr.getPersistentState(StImpl);
1135}
1136
Ted Kremenekffefc352008-04-11 22:25:11 +00001137// End-of-path.
1138
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001139ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1140 ValueState* St, SymbolID sid,
1141 RefVal V, bool& hasLeak) {
1142
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001143 hasLeak = V.isOwned() ||
1144 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001145
1146 if (!hasLeak)
1147 return NukeBinding(VMgr, St, sid);
1148
1149 RefBindings B = GetRefBindings(*St);
1150 ValueState StImpl = *St;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001151
1152 StImpl.CheckerState =
1153 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1154
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001155 return VMgr.getPersistentState(StImpl);
1156}
1157
1158void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001159 GREndPathNodeBuilder<ValueState>& Builder) {
1160
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001161 ValueState* St = Builder.getState();
1162 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001163
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001164 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001165
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001166 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1167 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001168
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001169 St = HandleSymbolDeath(Eng.getStateManager(), St,
1170 (*I).first, (*I).second, hasLeak);
1171
1172 if (hasLeak) Leaked.push_back((*I).first);
1173 }
Ted Kremenek541db372008-04-24 23:57:27 +00001174
1175 if (Leaked.empty())
1176 return;
1177
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001178 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001179
Ted Kremenek541db372008-04-24 23:57:27 +00001180 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001181 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001182
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001183 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1184 assert (!LeaksAtNode);
1185 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001186
1187 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1188 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001189 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001190}
1191
Ted Kremenek541db372008-04-24 23:57:27 +00001192// Dead symbols.
1193
1194void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1195 GRExprEngine& Eng,
1196 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001197 ExplodedNode<ValueState>* Pred,
1198 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001199 ValueState* St,
1200 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001201
Ted Kremenek541db372008-04-24 23:57:27 +00001202 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1203
1204 RefBindings B = GetRefBindings(*St);
1205 llvm::SmallVector<SymbolID, 10> Leaked;
1206
1207 for (ValueStateManager::DeadSymbolsTy::const_iterator
1208 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1209
1210 RefBindings::TreeTy* T = B.SlimFind(*I);
1211
1212 if (!T)
1213 continue;
1214
1215 bool hasLeak = false;
1216
1217 St = HandleSymbolDeath(Eng.getStateManager(), St,
1218 *I, T->getValue().second, hasLeak);
1219
1220 if (hasLeak) Leaked.push_back(*I);
1221 }
1222
1223 if (Leaked.empty())
1224 return;
1225
1226 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1227
1228 if (!N)
1229 return;
1230
1231 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1232 assert (!LeaksAtNode);
1233 LeaksAtNode = new std::vector<SymbolID>();
1234
1235 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1236 E = Leaked.end(); I != E; ++I)
1237 (*LeaksAtNode).push_back(*I);
1238}
1239
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001240 // Return statements.
1241
1242void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1243 GRExprEngine& Eng,
1244 GRStmtNodeBuilder<ValueState>& Builder,
1245 ReturnStmt* S,
1246 ExplodedNode<ValueState>* Pred) {
1247
1248 Expr* RetE = S->getRetValue();
1249 if (!RetE) return;
1250
1251 ValueStateManager& StateMgr = Eng.getStateManager();
1252 ValueState* St = Builder.GetState(Pred);
1253 RVal V = StateMgr.GetRVal(St, RetE);
1254
1255 if (!isa<lval::SymbolVal>(V))
1256 return;
1257
1258 // Get the reference count binding (if any).
1259 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1260 RefBindings B = GetRefBindings(*St);
1261 RefBindings::TreeTy* T = B.SlimFind(Sym);
1262
1263 if (!T)
1264 return;
1265
1266 // Change the reference count.
1267
1268 RefVal X = T->getValue().second;
1269
1270 switch (X.getKind()) {
1271
1272 case RefVal::Owned: {
1273 unsigned cnt = X.getCount();
1274 X = RefVal::makeReturnedOwned(cnt);
1275 break;
1276 }
1277
1278 case RefVal::NotOwned: {
1279 unsigned cnt = X.getCount();
1280 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1281 : RefVal::makeReturnedNotOwned();
1282 break;
1283 }
1284
1285 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001286 return;
1287 }
1288
1289 // Update the binding.
1290
1291 ValueState StImpl = *St;
1292 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1293 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1294}
1295
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001296// Assumptions.
1297
1298ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1299 RVal Cond, bool Assumption,
1300 bool& isFeasible) {
1301
1302 // FIXME: We may add to the interface of EvalAssume the list of symbols
1303 // whose assumptions have changed. For now we just iterate through the
1304 // bindings and check if any of the tracked symbols are NULL. This isn't
1305 // too bad since the number of symbols we will track in practice are
1306 // probably small and EvalAssume is only called at branches and a few
1307 // other places.
1308
1309 RefBindings B = GetRefBindings(*St);
1310
1311 if (B.isEmpty())
1312 return St;
1313
1314 bool changed = false;
1315
1316 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1317
1318 // Check if the symbol is null (or equal to any constant).
1319 // If this is the case, stop tracking the symbol.
1320
1321 if (St->getSymVal(I.getKey())) {
1322 changed = true;
1323 B = RefBFactory.Remove(B, I.getKey());
1324 }
1325 }
1326
1327 if (!changed)
1328 return St;
1329
1330 ValueState StImpl = *St;
1331 StImpl.CheckerState = B.getRoot();
1332 return Eng.getStateManager().getPersistentState(StImpl);
1333}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001334
1335CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001336 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001337 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001338
Ted Kremenek0d721572008-03-11 17:48:22 +00001339 // FIXME: This dispatch can potentially be sped up by unifiying it into
1340 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001341
Ted Kremenek0d721572008-03-11 17:48:22 +00001342 switch (E) {
1343 default:
1344 assert (false && "Unhandled CFRef transition.");
1345
1346 case DoNothing:
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001347 if (!GCEnabled && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001348 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001349 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001350 break;
1351 }
1352
Ted Kremenek0d721572008-03-11 17:48:22 +00001353 return B;
1354
1355 case IncRef:
1356 switch (V.getKind()) {
1357 default:
1358 assert(false);
1359
1360 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001361 V = RefVal::makeOwned(V.getCount()+1);
1362 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001363
Ted Kremenek0d721572008-03-11 17:48:22 +00001364 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001365 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001366 break;
1367
1368 case RefVal::Released:
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001369 if (GCEnabled)
1370 V = RefVal::makeOwned();
1371 else {
1372 V = RefVal::makeUseAfterRelease();
1373 hasErr = V.getKind();
1374 }
1375
Ted Kremenek0d721572008-03-11 17:48:22 +00001376 break;
1377 }
1378
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001379 break;
1380
Ted Kremenek0d721572008-03-11 17:48:22 +00001381 case DecRef:
1382 switch (V.getKind()) {
1383 default:
1384 assert (false);
1385
1386 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001387 unsigned Count = V.getCount();
1388 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001389 break;
1390 }
1391
Ted Kremenekc4f81022008-04-10 23:09:18 +00001392 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001393 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001394
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001395 if (Count > 0)
1396 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001397 else {
1398 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001399 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001400 }
1401
Ted Kremenek0d721572008-03-11 17:48:22 +00001402 break;
1403 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001404
1405 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001406 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001407 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001408 break;
1409 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001410
1411 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001412 }
1413
1414 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001415}
1416
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001417
1418//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001419// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001420//===----------------------------------------------------------------------===//
1421
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001422namespace {
1423
1424 //===-------------===//
1425 // Bug Descriptions. //
1426 //===-------------===//
1427
Ted Kremeneke3769852008-04-18 20:54:29 +00001428 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001429 protected:
1430 CFRefCount& TF;
1431
1432 public:
1433 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001434
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001435 CFRefCount& getTF() { return TF; }
1436
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001437 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001438 };
1439
1440 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1441 public:
1442 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1443
1444 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001445 return "Core Foundation: Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001446 }
1447 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001448 return "Reference-counted object is used"
1449 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001450 }
1451
1452 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001453 };
1454
1455 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1456 public:
1457 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1458
1459 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001460 return "Core Foundation: Release of non-owned object";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001461 }
1462 virtual const char* getDescription() const {
1463 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001464 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001465 "The object is not owned at this point by the caller.";
1466 }
1467
1468 virtual void EmitWarnings(BugReporter& BR);
1469 };
1470
1471 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1472 public:
1473 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1474
1475 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001476 return "Core Foundation: Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001477 }
1478
1479 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001480 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001481 }
1482
1483 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001484 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001485 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001486 };
1487
1488 //===---------===//
1489 // Bug Reports. //
1490 //===---------===//
1491
1492 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1493 SymbolID Sym;
1494 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001495 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001496 : RangedBugReport(D, n), Sym(sym) {}
1497
1498 virtual ~CFRefReport() {}
1499
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001500 CFRefBug& getBugType() {
1501 return (CFRefBug&) RangedBugReport::getBugType();
1502 }
1503 const CFRefBug& getBugType() const {
1504 return (const CFRefBug&) RangedBugReport::getBugType();
1505 }
1506
1507 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1508 const SourceRange*& end) {
1509
Ted Kremenek198cae02008-05-02 20:53:50 +00001510 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001511 RangedBugReport::getRanges(BR, beg, end);
1512 else {
1513 beg = 0;
1514 end = 0;
1515 }
1516 }
1517
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001518 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1519 ExplodedNode<ValueState>* N);
1520
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001521 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001522
1523 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1524 ExplodedNode<ValueState>* PrevN,
1525 ExplodedGraph<ValueState>& G,
1526 BugReporter& BR);
1527 };
1528
1529
1530} // end anonymous namespace
1531
1532void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001533 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001534 Eng.Register(new UseAfterRelease(*this));
1535 Eng.Register(new BadRelease(*this));
1536 Eng.Register(new Leak(*this));
1537}
1538
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001539
1540static const char* Msgs[] = {
1541 "Code is compiled in garbage collection only mode" // GC only
1542 " (the bug occurs with garbage collection enabled).",
1543
1544 "Code is compiled without garbage collection.", // No GC.
1545
1546 "Code is compiled for use with and without garbage collection (GC)."
1547 " The bug occurs with GC enabled.", // Hybrid, with GC.
1548
1549 "Code is compiled for use with and without garbage collection (GC)."
1550 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1551};
1552
1553std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1554 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1555
1556 switch (TF.getLangOptions().getGCMode()) {
1557 default:
1558 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001559
1560 case LangOptions::GCOnly:
1561 assert (TF.isGCEnabled());
1562 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001563
1564 case LangOptions::NonGC:
1565 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001566 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1567
1568 case LangOptions::HybridGC:
1569 if (TF.isGCEnabled())
1570 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1571 else
1572 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1573 }
1574}
1575
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001576PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1577 ExplodedNode<ValueState>* PrevN,
1578 ExplodedGraph<ValueState>& G,
1579 BugReporter& BR) {
1580
1581 // Check if the type state has changed.
1582
1583 ValueState* PrevSt = PrevN->getState();
1584 ValueState* CurrSt = N->getState();
1585
1586 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1587 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1588
Ted Kremeneka8503952008-04-18 04:55:01 +00001589 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1590 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001591
Ted Kremeneka8503952008-04-18 04:55:01 +00001592 if (!CurrT)
1593 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001594
Ted Kremeneka8503952008-04-18 04:55:01 +00001595 const char* Msg = NULL;
1596 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001597
Ted Kremeneka8503952008-04-18 04:55:01 +00001598 if (!PrevT) {
1599
Ted Kremenek9363fd92008-05-05 17:53:17 +00001600 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1601
1602 if (CurrV.isOwned()) {
1603
1604 if (isa<CallExpr>(S))
1605 Msg = "Function call returns an object with a +1 retain count"
1606 " (owning reference).";
1607 else {
1608 assert (isa<ObjCMessageExpr>(S));
1609 Msg = "Method returns an object with a +1 retain count"
1610 " (owning reference).";
1611 }
1612 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001613 else {
1614 assert (CurrV.isNotOwned());
Ted Kremenek9363fd92008-05-05 17:53:17 +00001615
1616 if (isa<CallExpr>(S))
1617 Msg = "Function call returns an object with a +0 retain count"
1618 " (non-owning reference).";
1619 else {
1620 assert (isa<ObjCMessageExpr>(S));
1621 Msg = "Method returns an object with a +0 retain count"
1622 " (non-owning reference).";
1623 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001624 }
Ted Kremenek9363fd92008-05-05 17:53:17 +00001625
Ted Kremeneka8503952008-04-18 04:55:01 +00001626 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1627 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1628
1629 if (Expr* Exp = dyn_cast<Expr>(S))
1630 P->addRange(Exp->getSourceRange());
1631
1632 return P;
1633 }
1634
1635 // Determine if the typestate has changed.
1636
1637 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1638
1639 if (PrevV == CurrV)
1640 return NULL;
1641
1642 // The typestate has changed.
1643
1644 std::ostringstream os;
1645
1646 switch (CurrV.getKind()) {
1647 case RefVal::Owned:
1648 case RefVal::NotOwned:
1649 assert (PrevV.getKind() == CurrV.getKind());
1650
1651 if (PrevV.getCount() > CurrV.getCount())
1652 os << "Reference count decremented.";
1653 else
1654 os << "Reference count incremented.";
1655
Ted Kremenek9363fd92008-05-05 17:53:17 +00001656 if (unsigned Count = GetCount(CurrV)) {
1657
1658 os << " Object has +" << Count;
Ted Kremenek752b5842008-04-18 05:32:44 +00001659
Ted Kremenek9363fd92008-05-05 17:53:17 +00001660 if (Count > 1)
1661 os << " retain counts.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001662 else
Ted Kremenek9363fd92008-05-05 17:53:17 +00001663 os << " retain count.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001664 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001665
1666 Msg = os.str().c_str();
1667
1668 break;
1669
1670 case RefVal::Released:
1671 Msg = "Object released.";
1672 break;
1673
1674 case RefVal::ReturnedOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001675 Msg = "Object returned to caller as owning reference (single retain count"
1676 " transferred to caller).";
Ted Kremeneka8503952008-04-18 04:55:01 +00001677 break;
1678
1679 case RefVal::ReturnedNotOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001680 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremeneka8503952008-04-18 04:55:01 +00001681 break;
1682
1683 default:
1684 return NULL;
1685 }
1686
1687 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1688 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1689 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1690
1691 // Add the range by scanning the children of the statement for any bindings
1692 // to Sym.
1693
1694 ValueStateManager& VSM = BR.getEngine().getStateManager();
1695
1696 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1697 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1698 RVal X = VSM.GetRVal(CurrSt, Exp);
1699
1700 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1701 if (SV->getSymbol() == Sym) {
1702 P->addRange(Exp->getSourceRange()); break;
1703 }
1704 }
1705
1706 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001707}
1708
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001709PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremenekea794e92008-05-05 18:50:19 +00001710 ExplodedNode<ValueState>* EndN) {
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001711
1712 if (!getBugType().isLeak())
Ted Kremenekea794e92008-05-05 18:50:19 +00001713 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001714
Ted Kremenek9363fd92008-05-05 17:53:17 +00001715 typedef CFRefCount::RefBindings RefBindings;
1716
1717 // Get the retain count.
1718 unsigned long RetCount = 0;
1719
1720 {
Ted Kremenekea794e92008-05-05 18:50:19 +00001721 ValueState* St = EndN->getState();
Ted Kremenek9363fd92008-05-05 17:53:17 +00001722 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1723 RefBindings::TreeTy* T = B.SlimFind(Sym);
1724 assert (T);
1725 RetCount = GetCount(T->getValue().second);
1726 }
1727
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001728 // We are a leak. Walk up the graph to get to the first node where the
1729 // symbol appeared.
1730
Ted Kremenekea794e92008-05-05 18:50:19 +00001731 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001732 ExplodedNode<ValueState>* Last = N;
Ted Kremenekea794e92008-05-05 18:50:19 +00001733
Ted Kremenek198cae02008-05-02 20:53:50 +00001734 // Find the first node that referred to the tracked symbol. We also
1735 // try and find the first VarDecl the value was stored to.
1736
1737 VarDecl* FirstDecl = 0;
Ted Kremenekea794e92008-05-05 18:50:19 +00001738
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001739 while (N) {
1740 ValueState* St = N->getState();
1741 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001742 RefBindings::TreeTy* T = B.SlimFind(Sym);
1743
1744 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001745 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00001746
1747 VarDecl* VD = 0;
1748
1749 // Determine if there is an LVal binding to the symbol.
1750 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1751 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1752 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1753 continue;
1754
1755 if (VD) { // Multiple decls map to this symbol.
1756 VD = 0;
1757 break;
1758 }
1759
1760 VD = I->first;
1761 }
1762
1763 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001764
1765 Last = N;
1766 N = N->pred_empty() ? NULL : *(N->pred_begin());
1767 }
1768
Ted Kremenekea794e92008-05-05 18:50:19 +00001769 // Get the allocate site.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001770
1771 assert (Last);
1772 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1773
Ted Kremenekea794e92008-05-05 18:50:19 +00001774 SourceManager& SMgr = BR.getContext().getSourceManager();
1775 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001776
Ted Kremenekea794e92008-05-05 18:50:19 +00001777 // Get the leak site. We may have multiple ExplodedNodes (one with the
1778 // leak) that occur on the same line number; if the node with the leak
1779 // has any immediate predecessor nodes with the same line number, find
1780 // any transitive-successors that have a different statement and use that
1781 // line number instead. This avoids emiting a diagnostic like:
1782 //
1783 // // 'y' is leaked.
1784 // int x = foo(y);
1785 //
1786 // instead we want:
1787 //
1788 // int x = foo(y);
1789 // // 'y' is leaked.
1790
1791 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
1792 assert (S);
1793 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
1794
1795 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
1796 // it occur on the same line?
1797
1798 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
1799 N = *(EndN->pred_begin());
1800
1801 do {
1802 ProgramPoint P = N->getLocation();
1803
1804 if (!isa<PostStmt>(P))
1805 break;
1806
1807 // Predecessor at same line?
1808
1809 Stmt* SPred = cast<PostStmt>(P).getStmt();
1810
1811 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine)
1812 break;
1813
1814 // The predecessor (where the object was not yet leaked) is a statement
1815 // on the same line. Get the first successor statement that appears
1816 // on a different line. For this operation, we can traverse the
1817 // non-trimmed graph.
1818
1819 N = getEndNode(); // This is the node where the leak occured in the
1820 // original graph.
1821
1822 while (!N->succ_empty()) {
1823
1824 N = *(N->succ_begin());
1825 ProgramPoint P = N->getLocation();
1826
1827 if (!isa<PostStmt>(P))
1828 continue;
1829
1830 Stmt* SSucc = cast<PostStmt>(P).getStmt();
1831
1832 if (SMgr.getLogicalLineNumber(SSucc->getLocStart()) != EndLine) {
1833 S = SSucc;
1834 break;
1835 }
1836 }
1837 }
1838 while (false);
1839
1840 // Construct the location.
1841
1842 FullSourceLoc L(S->getLocStart(), SMgr);
1843
1844 // Generate the diagnostic.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001845 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00001846
Ted Kremenekea794e92008-05-05 18:50:19 +00001847 os << "Object allocated on line " << AllocLine;
Ted Kremenek198cae02008-05-02 20:53:50 +00001848
1849 if (FirstDecl)
1850 os << " and stored into '" << FirstDecl->getName() << '\'';
1851
Ted Kremenek9363fd92008-05-05 17:53:17 +00001852 os << " is no longer referenced after this point and has a retain count of +"
1853 << RetCount << " (object leaked).";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001854
Ted Kremenekea794e92008-05-05 18:50:19 +00001855 return new PathDiagnosticPiece(L, os.str());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001856}
1857
Ted Kremenek7d421f32008-04-09 23:49:11 +00001858void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001859
Ted Kremenek7d421f32008-04-09 23:49:11 +00001860 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1861 E = TF.use_after_end(); I != E; ++I) {
1862
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001863 CFRefReport report(*this, I->first, I->second.second);
1864 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00001865 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001866 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001867}
1868
1869void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001870
Ted Kremenek7d421f32008-04-09 23:49:11 +00001871 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1872 E = TF.bad_release_end(); I != E; ++I) {
1873
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001874 CFRefReport report(*this, I->first, I->second.second);
1875 report.addRange(I->second.first->getSourceRange());
1876 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00001877 }
1878}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001879
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001880void Leak::EmitWarnings(BugReporter& BR) {
1881
1882 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1883 E = TF.leaks_end(); I != E; ++I) {
1884
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001885 std::vector<SymbolID>& SymV = *(I->second);
1886 unsigned n = SymV.size();
1887
1888 for (unsigned i = 0; i < n; ++i) {
1889 CFRefReport report(*this, I->first, SymV[i]);
1890 BR.EmitWarning(report);
1891 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001892 }
1893}
1894
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001895void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1896 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1897 I!=E; ++I)
1898 Nodes.push_back(I->first);
1899}
1900
Ted Kremeneka7338b42008-03-11 06:39:11 +00001901//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001902// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001903//===----------------------------------------------------------------------===//
1904
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001905GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00001906 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001907 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001908 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00001909}