blob: 4b23ff47b9beb6b15bfe57d2a9beb41aaf2a96e7 [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000016#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000017#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000019#include "clang/Analysis/PathDiagnostic.h"
20#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000021#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/ImmutableMap.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000024#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000025#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000026#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000027
28using namespace clang;
29
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000030//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-04-17 18:12:53 +000031// Utility functions.
32//===----------------------------------------------------------------------===//
33
34static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
35 IdentifierInfo* II = &Ctx.Idents.get(name);
36 return Ctx.Selectors.getSelector(0, &II);
37}
38
39//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000040// Symbolic Evaluation of Reference Counting Logic
41//===----------------------------------------------------------------------===//
42
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000043namespace {
44 enum ArgEffect { IncRef, DecRef, DoNothing };
45 typedef std::vector<ArgEffect> ArgEffects;
46}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000047
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000048namespace llvm {
49 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000050 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000051 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I)
52 ID.AddInteger((unsigned) *I);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000053 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000054 };
55} // end llvm namespace
56
57namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +000058
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000059class RetEffect {
60public:
Ted Kremenek940b1d82008-04-10 23:44:06 +000061 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
62 NotOwnedSymbol = 0x3 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000063
64private:
65 unsigned Data;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000066 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000067
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000068public:
69
70 Kind getKind() const { return (Kind) (Data & 0x3); }
71
72 unsigned getValue() const {
73 assert(getKind() == Alias);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000074 return Data >> 2;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000075 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +000076
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000077 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000078
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000079 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000080
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000081 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
82
Ted Kremenek940b1d82008-04-10 23:44:06 +000083 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
84
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000085 operator Kind() const { return getKind(); }
86
87 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
88};
89
90
91class CFRefSummary : public llvm::FoldingSetNode {
92 ArgEffects* Args;
93 RetEffect Ret;
94public:
95
96 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
97
98 unsigned getNumArgs() const { return Args->size(); }
99
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000100 ArgEffect getArg(unsigned idx) const {
101 assert (idx < getNumArgs());
102 return (*Args)[idx];
103 }
104
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000105 RetEffect getRet() const {
106 return Ret;
107 }
108
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000109 typedef ArgEffects::const_iterator arg_iterator;
110
111 arg_iterator begin_args() const { return Args->begin(); }
112 arg_iterator end_args() const { return Args->end(); }
113
114 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
115 ID.AddPointer(A);
116 ID.Add(R);
117 }
118
119 void Profile(llvm::FoldingSetNodeID& ID) const {
120 Profile(ID, Args, Ret);
121 }
122};
123
124
125class CFRefSummaryManager {
126 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
127 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
128 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
129
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000130 ASTContext& Ctx;
131 SummarySetTy SummarySet;
132 SummaryMapTy SummaryMap;
133 AESetTy AESet;
134 llvm::BumpPtrAllocator BPAlloc;
135 ArgEffects ScratchArgs;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000136
137
138 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000139
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000140 CFRefSummary* getCannedCFSummary(FunctionTypeProto* FT, bool isRetain);
141
142 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
143
144 CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
145 CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);
146
147 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
148
Ted Kremenek940b1d82008-04-10 23:44:06 +0000149 void FillDoNothing(unsigned Args);
150
151
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000152public:
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000153 CFRefSummaryManager(ASTContext& ctx) : Ctx(ctx) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000154 ~CFRefSummaryManager();
155
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000156 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000157};
158
159} // end anonymous namespace
160
161//===----------------------------------------------------------------------===//
162// Implementation of checker data structures.
163//===----------------------------------------------------------------------===//
164
165CFRefSummaryManager::~CFRefSummaryManager() {
166
167 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
168 // mitigating the need to do explicit cleanup of the
169 // Argument-Effect summaries.
170
171 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
172 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000173}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000174
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000175ArgEffects* CFRefSummaryManager::getArgEffects() {
176
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000177 llvm::FoldingSetNodeID profile;
178 profile.Add(ScratchArgs);
179 void* InsertPos;
180
181 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
182 AESet.FindNodeOrInsertPos(profile, InsertPos);
183
184 if (E) {
185 ScratchArgs.clear();
186 return &E->getValue();
187 }
188
189 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
190 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
191
192 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
193 AESet.InsertNode(E, InsertPos);
194
195 ScratchArgs.clear();
196 return &E->getValue();
197}
198
199CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
200 RetEffect RE) {
201
202 llvm::FoldingSetNodeID profile;
203 CFRefSummary::Profile(profile, AE, RE);
204 void* InsertPos;
205
206 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
207
208 if (Summ)
209 return Summ;
210
211 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
212 new (Summ) CFRefSummary(AE, RE);
213 SummarySet.InsertNode(Summ, InsertPos);
214
215 return Summ;
216}
217
218
219CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
220 ASTContext& Ctx) {
221
222 SourceLocation Loc = FD->getLocation();
223
224 if (!Loc.isFileID())
225 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000226
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000227 { // Look into our cache of summaries to see if we have already computed
228 // a summary for this FunctionDecl.
229
230 SummaryMapTy::iterator I = SummaryMap.find(FD);
231
232 if (I != SummaryMap.end())
233 return I->second;
234 }
235
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000236#if 0
237 SourceManager& SrcMgr = Ctx.getSourceManager();
238 unsigned fid = Loc.getFileID();
239 const FileEntry* FE = SrcMgr.getFileEntryForID(fid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000240
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000241 if (!FE)
242 return NULL;
243
244 const char* DirName = FE->getDir()->getName();
245 assert (DirName);
246 assert (strlen(DirName) > 0);
247
248 if (!strstr(DirName, "CoreFoundation")) {
249 SummaryMap[FD] = NULL;
250 return NULL;
251 }
252#endif
253
254 const char* FName = FD->getIdentifier()->getName();
255
256 if (FName[0] == 'C' && FName[1] == 'F') {
257 CFRefSummary* S = getCFSummary(FD, FName);
258 SummaryMap[FD] = S;
259 return S;
260 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000261
262 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000263}
264
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000265CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
266 const char* FName) {
267
268 // For now, only generate summaries for functions that have a prototype.
269
270 FunctionTypeProto* FT =
271 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
272
273 if (!FT)
274 return NULL;
275
276 FName += 2;
277
278 if (strcmp(FName, "Retain") == 0)
279 return getCannedCFSummary(FT, true);
280
281 if (strcmp(FName, "Release") == 0)
282 return getCannedCFSummary(FT, false);
283
284 assert (ScratchArgs.empty());
285 bool usesCreateRule = false;
286
287 if (strstr(FName, "Create"))
288 usesCreateRule = true;
289
290 if (!usesCreateRule && strstr(FName, "Copy"))
291 usesCreateRule = true;
292
293 if (usesCreateRule)
294 return getCFSummaryCreateRule(FT);
295
296 if (strstr(FName, "Get"))
297 return getCFSummaryGetRule(FT);
298
299 return NULL;
300}
301
302CFRefSummary* CFRefSummaryManager::getCannedCFSummary(FunctionTypeProto* FT,
303 bool isRetain) {
304
305 if (FT->getNumArgs() != 1)
306 return NULL;
307
308 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
309
310 if (!ArgT)
311 return NULL;
312
313 // For CFRetain/CFRelease, the first (and only) argument is of type
314 // "CFTypeRef".
315
316 const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
317 assert (TDName);
318
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000319 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000320 return NULL;
321
322 if (!ArgT->isPointerType())
323 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000324
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000325 QualType RetTy = FT->getResultType();
326
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000327 if (isRetain) {
328 // CFRetain: the return type should also be "CFTypeRef".
329 if (RetTy.getTypePtr() != ArgT)
330 return NULL;
Ted Kremenek940b1d82008-04-10 23:44:06 +0000331
332 // The function's interface checks out. Generate a canned summary.
333 assert (ScratchArgs.empty());
334 ScratchArgs.push_back(IncRef);
335 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000336 }
337 else {
338 // CFRelease: the return type should be void.
339
340 if (RetTy != Ctx.VoidTy)
341 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000342
Ted Kremenek940b1d82008-04-10 23:44:06 +0000343 assert (ScratchArgs.empty());
344 ScratchArgs.push_back(DecRef);
345 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
346 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000347}
348
349static bool isCFRefType(QualType T) {
350
351 if (!T->isPointerType())
352 return false;
353
354 // Check the typedef for the name "CF" and the substring "Ref".
355
356 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
357
358 if (!TD)
359 return false;
360
361 const char* TDName = TD->getDecl()->getIdentifier()->getName();
362 assert (TDName);
363
364 if (TDName[0] != 'C' || TDName[1] != 'F')
365 return false;
366
367 if (strstr(TDName, "Ref") == 0)
368 return false;
369
370 return true;
371}
372
Ted Kremenek940b1d82008-04-10 23:44:06 +0000373void CFRefSummaryManager::FillDoNothing(unsigned Args) {
374 for (unsigned i = 0; i != Args; ++i)
375 ScratchArgs.push_back(DoNothing);
376}
377
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000378
379CFRefSummary*
380CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
381
382 if (!isCFRefType(FT->getResultType()))
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000383 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000384
385 assert (ScratchArgs.empty());
386
387 // FIXME: Add special-cases for functions that retain/release. For now
388 // just handle the default case.
389
Ted Kremenek940b1d82008-04-10 23:44:06 +0000390 FillDoNothing(FT->getNumArgs());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000391 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
392}
393
394CFRefSummary*
395CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
396
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000397 QualType RetTy = FT->getResultType();
398
399 // FIXME: For now we assume that all pointer types returned are referenced
400 // counted. Since this is the "Get" rule, we assume non-ownership, which
401 // works fine for things that are not reference counted. We do this because
402 // some generic data structures return "void*". We need something better
403 // in the future.
404
405 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
406 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000407
408 assert (ScratchArgs.empty());
409
410 // FIXME: Add special-cases for functions that retain/release. For now
411 // just handle the default case.
412
Ted Kremenek940b1d82008-04-10 23:44:06 +0000413 FillDoNothing(FT->getNumArgs());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000414 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
415}
416
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000417//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000418// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000419//===----------------------------------------------------------------------===//
420
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000421namespace {
422
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000423class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000424public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000425
Ted Kremenek4fd88972008-04-17 18:12:53 +0000426 enum Kind {
427 Owned = 0, // Owning reference.
428 NotOwned, // Reference is not owned by still valid (not freed).
429 Released, // Object has been released.
430 ReturnedOwned, // Returned object passes ownership to caller.
431 ReturnedNotOwned, // Return object does not pass ownership to caller.
432 ErrorUseAfterRelease, // Object used after released.
433 ErrorReleaseNotOwned, // Release of an object that was not owned.
434 ErrorLeak // A memory leak due to excessive reference counts.
435 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000436
Ted Kremenek4fd88972008-04-17 18:12:53 +0000437private:
438
439 Kind kind;
440 unsigned Cnt;
441
442 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
443
444 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000445
446public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000447
Ted Kremenek4fd88972008-04-17 18:12:53 +0000448 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000449
Ted Kremenek4fd88972008-04-17 18:12:53 +0000450 unsigned getCount() const { return Cnt; }
451
452 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000453
Ted Kremenek73c750b2008-03-11 18:14:09 +0000454 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
455
Ted Kremenekdb863712008-04-16 22:32:20 +0000456 static bool isLeak(Kind k) { return k == ErrorLeak; }
457
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000458 bool isOwned() const {
459 return getKind() == Owned;
460 }
461
Ted Kremenekdb863712008-04-16 22:32:20 +0000462 bool isNotOwned() const {
463 return getKind() == NotOwned;
464 }
465
Ted Kremenek4fd88972008-04-17 18:12:53 +0000466 bool isReturnedOwned() const {
467 return getKind() == ReturnedOwned;
468 }
469
470 bool isReturnedNotOwned() const {
471 return getKind() == ReturnedNotOwned;
472 }
473
474 bool isNonLeakError() const {
475 Kind k = getKind();
476 return isError(k) && !isLeak(k);
477 }
478
479 // State creation: normal state.
480
Ted Kremenek61b9f872008-04-10 23:09:18 +0000481 static RefVal makeOwned(unsigned Count = 0) {
482 return RefVal(Owned, Count);
483 }
484
485 static RefVal makeNotOwned(unsigned Count = 0) {
486 return RefVal(NotOwned, Count);
487 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000488
489 static RefVal makeReturnedOwned(unsigned Count) {
490 return RefVal(ReturnedOwned, Count);
491 }
492
493 static RefVal makeReturnedNotOwned() {
494 return RefVal(ReturnedNotOwned);
495 }
496
497 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000498
Ted Kremenekdb863712008-04-16 22:32:20 +0000499 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000500 static RefVal makeReleased() { return RefVal(Released); }
501 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
502 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000503
504 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000505
Ted Kremenek4fd88972008-04-17 18:12:53 +0000506 bool operator==(const RefVal& X) const {
507 return kind == X.kind && Cnt == X.Cnt;
508 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000509
Ted Kremenek4fd88972008-04-17 18:12:53 +0000510 void Profile(llvm::FoldingSetNodeID& ID) const {
511 ID.AddInteger((unsigned) kind);
512 ID.AddInteger(Cnt);
513 }
514
Ted Kremenekf3948042008-03-11 19:44:10 +0000515 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000516};
Ted Kremenekf3948042008-03-11 19:44:10 +0000517
518void RefVal::print(std::ostream& Out) const {
519 switch (getKind()) {
520 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000521 case Owned: {
522 Out << "Owned";
523 unsigned cnt = getCount();
524 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000525 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000526 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000527
Ted Kremenek61b9f872008-04-10 23:09:18 +0000528 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000529 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000530 unsigned cnt = getCount();
531 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000532 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000533 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000534
Ted Kremenek4fd88972008-04-17 18:12:53 +0000535 case ReturnedOwned: {
536 Out << "ReturnedOwned";
537 unsigned cnt = getCount();
538 if (cnt) Out << " (+ " << cnt << ")";
539 break;
540 }
541
542 case ReturnedNotOwned: {
543 Out << "ReturnedNotOwned";
544 unsigned cnt = getCount();
545 if (cnt) Out << " (+ " << cnt << ")";
546 break;
547 }
548
Ted Kremenekf3948042008-03-11 19:44:10 +0000549 case Released:
550 Out << "Released";
551 break;
552
Ted Kremenekdb863712008-04-16 22:32:20 +0000553 case ErrorLeak:
554 Out << "Leaked";
555 break;
556
Ted Kremenekf3948042008-03-11 19:44:10 +0000557 case ErrorUseAfterRelease:
558 Out << "Use-After-Release [ERROR]";
559 break;
560
561 case ErrorReleaseNotOwned:
562 Out << "Release of Not-Owned [ERROR]";
563 break;
564 }
565}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000566
Ted Kremenek13922612008-04-16 20:40:59 +0000567//===----------------------------------------------------------------------===//
568// Transfer functions.
569//===----------------------------------------------------------------------===//
570
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000571class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000572public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000573 // Type definitions.
574
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000575 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000576 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000577
Ted Kremenek8dd56462008-04-18 03:39:05 +0000578 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
579 ReleasesNotOwnedTy;
580
581 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
582
583 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000584 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000585
Ted Kremenekf3948042008-03-11 19:44:10 +0000586 class BindingsPrinter : public ValueState::CheckerStatePrinter {
587 public:
588 virtual void PrintCheckerState(std::ostream& Out, void* State,
589 const char* nl, const char* sep);
590 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000591
592private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000593 // Instance variables.
594
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000595 CFRefSummaryManager Summaries;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000596 RefBFactoryTy RefBFactory;
597
Ted Kremenek73c750b2008-03-11 18:14:09 +0000598 UseAfterReleasesTy UseAfterReleases;
599 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000600 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000601
Ted Kremenekf3948042008-03-11 19:44:10 +0000602 BindingsPrinter Printer;
603
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000604 Selector RetainSelector;
605 Selector ReleaseSelector;
606
Ted Kremenek8dd56462008-04-18 03:39:05 +0000607public:
608
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000609 static RefBindings GetRefBindings(ValueState& StImpl) {
610 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
611 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000612
Ted Kremenek8dd56462008-04-18 03:39:05 +0000613private:
614
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000615 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
616 StImpl.CheckerState = B.getRoot();
617 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000618
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000619 RefBindings Remove(RefBindings B, SymbolID sym) {
620 return RefBFactory.Remove(B, sym);
621 }
622
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000623 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000624 RefVal::Kind& hasErr);
625
Ted Kremenekdb863712008-04-16 22:32:20 +0000626 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
627 GRStmtNodeBuilder<ValueState>& Builder,
628 Expr* NodeExpr, Expr* ErrorExpr,
629 ExplodedNode<ValueState>* Pred,
630 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000631 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000632
633 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
634 SymbolID sid, RefVal V, bool& hasLeak);
635
636 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
637 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000638
639public:
Ted Kremenek13922612008-04-16 20:40:59 +0000640
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000641 CFRefCount(ASTContext& Ctx)
642 : Summaries(Ctx),
643 RetainSelector(GetUnarySelector("retain", Ctx)),
644 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
645
Ted Kremenek8dd56462008-04-18 03:39:05 +0000646 virtual ~CFRefCount() {
647 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
648 delete I->second;
649 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000650
651 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000652
653 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
654 return &Printer;
655 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000656
657 // Calls.
658
659 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000660 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000661 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000662 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000663 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000664
Ted Kremenek85348202008-04-15 23:44:31 +0000665 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
666 GRExprEngine& Engine,
667 GRStmtNodeBuilder<ValueState>& Builder,
668 ObjCMessageExpr* ME,
669 ExplodedNode<ValueState>* Pred);
670
671 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
672 GRExprEngine& Engine,
673 GRStmtNodeBuilder<ValueState>& Builder,
674 ObjCMessageExpr* ME,
675 ExplodedNode<ValueState>* Pred);
676
Ted Kremenek13922612008-04-16 20:40:59 +0000677 // Stores.
678
679 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
680 GRExprEngine& Engine,
681 GRStmtNodeBuilder<ValueState>& Builder,
682 Expr* E, ExplodedNode<ValueState>* Pred,
683 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000684 // End-of-path.
685
686 virtual void EvalEndPath(GRExprEngine& Engine,
687 GREndPathNodeBuilder<ValueState>& Builder);
688
Ted Kremenek4fd88972008-04-17 18:12:53 +0000689 // Return statements.
690
691 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
692 GRExprEngine& Engine,
693 GRStmtNodeBuilder<ValueState>& Builder,
694 ReturnStmt* S,
695 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +0000696
697 // Assumptions.
698
699 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
700 RVal Cond, bool Assumption, bool& isFeasible);
701
Ted Kremenekfa34b332008-04-09 01:10:13 +0000702 // Error iterators.
703
704 typedef UseAfterReleasesTy::iterator use_after_iterator;
705 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000706 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000707
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000708 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
709 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000710
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000711 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
712 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000713
714 leaks_iterator leaks_begin() { return Leaks.begin(); }
715 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000716};
717
718} // end anonymous namespace
719
Ted Kremenek8dd56462008-04-18 03:39:05 +0000720
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000721
722
Ted Kremenekf3948042008-03-11 19:44:10 +0000723void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
724 void* State, const char* nl,
725 const char* sep) {
726 RefBindings B((RefBindings::TreeTy*) State);
727
728 if (State)
729 Out << sep << nl;
730
731 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
732 Out << (*I).first << " : ";
733 (*I).second.print(Out);
734 Out << nl;
735 }
736}
737
Ted Kremenekf9561e52008-04-11 20:23:24 +0000738static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
739 return Summ ? Summ->getArg(idx) : DoNothing;
740}
741
742static inline RetEffect GetRetE(CFRefSummary* Summ) {
743 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
744}
745
Ted Kremenekdb863712008-04-16 22:32:20 +0000746void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
747 GRStmtNodeBuilder<ValueState>& Builder,
748 Expr* NodeExpr, Expr* ErrorExpr,
749 ExplodedNode<ValueState>* Pred,
750 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000751 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000752 Builder.BuildSinks = true;
753 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
754
755 if (!N) return;
756
757 switch (hasErr) {
758 default: assert(false);
759 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000760 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000761 break;
762
763 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000764 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000765 break;
766 }
767}
768
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000769void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000770 GRExprEngine& Eng,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000771 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000772 CallExpr* CE, RVal L,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000773 ExplodedNode<ValueState>* Pred) {
774
Ted Kremenek199e1a02008-03-12 21:06:49 +0000775 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000776
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000777 CFRefSummary* Summ = NULL;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000778
779 // Get the summary.
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000780
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000781 if (isa<lval::FuncVal>(L)) {
782 lval::FuncVal FV = cast<lval::FuncVal>(L);
783 FunctionDecl* FD = FV.getDecl();
784 Summ = Summaries.getSummary(FD, Eng.getContext());
785 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000786
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000787 // Get the state.
788
789 ValueState* St = Builder.GetState(Pred);
790
791 // Evaluate the effects of the call.
792
793 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000794 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekf9561e52008-04-11 20:23:24 +0000795
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000796 // This function has a summary. Evaluate the effect of the arguments.
797
798 unsigned idx = 0;
799
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000800 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000801 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000802
803 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
804 I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000805
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000806 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000807
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000808 if (isa<lval::SymbolVal>(V)) {
809 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +0000810 RefBindings B = GetRefBindings(StVals);
811
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000812 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000813 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000814 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000815
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000816 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000817 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000818 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000819 break;
820 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000821 }
Ted Kremenekb8873552008-04-11 20:51:02 +0000822 }
823 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
824
825 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
826 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000827 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +0000828 }
Ted Kremeneka5488462008-04-22 21:39:21 +0000829 else if (isa<nonlval::LValAsInteger>(V))
830 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000831 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000832
833 St = StateMgr.getPersistentState(StVals);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000834
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000835 if (hasErr) {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000836 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
837 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000838 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000839 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000840
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000841 // Finally, consult the summary for the return value.
842
Ted Kremenekf9561e52008-04-11 20:23:24 +0000843 RetEffect RE = GetRetE(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000844
845 switch (RE.getKind()) {
846 default:
847 assert (false && "Unhandled RetEffect."); break;
848
Ted Kremenek940b1d82008-04-10 23:44:06 +0000849 case RetEffect::NoRet:
Ted Kremenekf9561e52008-04-11 20:23:24 +0000850
851 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +0000852 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
853 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000854
855 if (CE->getType() != Eng.getContext().VoidTy) {
856 unsigned Count = Builder.getCurrentBlockCount();
857 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
858
859 RVal X = CE->getType()->isPointerType()
860 ? cast<RVal>(lval::SymbolVal(Sym))
861 : cast<RVal>(nonlval::SymbolVal(Sym));
862
863 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
864 }
865
Ted Kremenek940b1d82008-04-10 23:44:06 +0000866 break;
867
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000868 case RetEffect::Alias: {
869 unsigned idx = RE.getValue();
870 assert (idx < CE->getNumArgs());
871 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenek199e1a02008-03-12 21:06:49 +0000872 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000873 break;
874 }
875
876 case RetEffect::OwnedSymbol: {
877 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000878 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000879
880 ValueState StImpl = *St;
881 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000882 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000883
884 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
885 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000886 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000887
888 break;
889 }
890
891 case RetEffect::NotOwnedSymbol: {
892 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000893 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000894
895 ValueState StImpl = *St;
896 RefBindings B = GetRefBindings(StImpl);
897 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
898
899 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
900 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000901 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000902
903 break;
904 }
905 }
906
Ted Kremenek0e561a32008-03-21 21:30:14 +0000907 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000908}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000909
Ted Kremenek85348202008-04-15 23:44:31 +0000910
911void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
912 GRExprEngine& Eng,
913 GRStmtNodeBuilder<ValueState>& Builder,
914 ObjCMessageExpr* ME,
915 ExplodedNode<ValueState>* Pred) {
916
917 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
918 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
919}
920
921bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
922 GRExprEngine& Eng,
923 GRStmtNodeBuilder<ValueState>& Builder,
924 ObjCMessageExpr* ME,
925 ExplodedNode<ValueState>* Pred) {
926
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000927 // Handle "toll-free bridging" of calls to "Release" and "Retain".
928
929 // FIXME: track the underlying object type associated so that we can
930 // flag illegal uses of toll-free bridging (or at least handle it
931 // at casts).
Ted Kremenek85348202008-04-15 23:44:31 +0000932
933 Selector S = ME->getSelector();
934
935 if (!S.isUnarySelector())
936 return true;
937
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000938 Expr* Receiver = ME->getReceiver();
939
940 if (!Receiver)
941 return true;
942
943 // Check if we are calling "Retain" or "Release".
944
945 bool isRetain = false;
946
947 if (S == RetainSelector)
948 isRetain = true;
949 else if (S != ReleaseSelector)
950 return true;
951
952 // We have "Retain" or "Release". Get the reference binding.
953
954 ValueStateManager& StateMgr = Eng.getStateManager();
955 ValueState* St = Builder.GetState(Pred);
956 RVal V = StateMgr.GetRVal(St, Receiver);
957
958 if (!isa<lval::SymbolVal>(V))
959 return true;
960
961 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
962 RefBindings B = GetRefBindings(*St);
963
964 RefBindings::TreeTy* T = B.SlimFind(Sym);
965
966 if (!T)
967 return true;
968
969 RefVal::Kind hasErr = (RefVal::Kind) 0;
970 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
971
972 // Create a new state with the updated bindings.
973
974 ValueState StVals = *St;
975 SetRefBindings(StVals, B);
976 St = StateMgr.getPersistentState(StVals);
977
978 // Create an error node if it exists.
979
980 if (hasErr)
Ted Kremenek8dd56462008-04-18 03:39:05 +0000981 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000982 else
983 Builder.MakeNode(Dst, ME, Pred, St);
984
985 return false;
Ted Kremenek85348202008-04-15 23:44:31 +0000986}
987
Ted Kremenek13922612008-04-16 20:40:59 +0000988// Stores.
989
990void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
991 GRExprEngine& Eng,
992 GRStmtNodeBuilder<ValueState>& Builder,
993 Expr* E, ExplodedNode<ValueState>* Pred,
994 ValueState* St, RVal TargetLV, RVal Val) {
995
996 // Check if we have a binding for "Val" and if we are storing it to something
997 // we don't understand or otherwise the value "escapes" the function.
998
999 if (!isa<lval::SymbolVal>(Val))
1000 return;
1001
1002 // Are we storing to something that causes the value to "escape"?
1003
1004 bool escapes = false;
1005
1006 if (!isa<lval::DeclVal>(TargetLV))
1007 escapes = true;
1008 else
1009 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1010
1011 if (!escapes)
1012 return;
1013
1014 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1015 RefBindings B = GetRefBindings(*St);
1016 RefBindings::TreeTy* T = B.SlimFind(Sym);
1017
1018 if (!T)
1019 return;
1020
Ted Kremenekdb863712008-04-16 22:32:20 +00001021 // Nuke the binding.
1022 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001023
1024 // Hand of the remaining logic to the parent implementation.
1025 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1026}
1027
Ted Kremenekdb863712008-04-16 22:32:20 +00001028
1029ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1030 SymbolID sid) {
1031 ValueState StImpl = *St;
1032 RefBindings B = GetRefBindings(StImpl);
1033 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1034 return VMgr.getPersistentState(StImpl);
1035}
1036
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001037// End-of-path.
1038
Ted Kremenekdb863712008-04-16 22:32:20 +00001039ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1040 ValueState* St, SymbolID sid,
1041 RefVal V, bool& hasLeak) {
1042
Ted Kremenek4fd88972008-04-17 18:12:53 +00001043 hasLeak = V.isOwned() ||
1044 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001045
1046 if (!hasLeak)
1047 return NukeBinding(VMgr, St, sid);
1048
1049 RefBindings B = GetRefBindings(*St);
1050 ValueState StImpl = *St;
1051 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1052 return VMgr.getPersistentState(StImpl);
1053}
1054
1055void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001056 GREndPathNodeBuilder<ValueState>& Builder) {
1057
Ted Kremenekdb863712008-04-16 22:32:20 +00001058 ValueState* St = Builder.getState();
1059 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001060
Ted Kremenekdb863712008-04-16 22:32:20 +00001061 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001062
Ted Kremenekdb863712008-04-16 22:32:20 +00001063 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1064 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001065
Ted Kremenekdb863712008-04-16 22:32:20 +00001066 St = HandleSymbolDeath(Eng.getStateManager(), St,
1067 (*I).first, (*I).second, hasLeak);
1068
1069 if (hasLeak) Leaked.push_back((*I).first);
1070 }
1071
Ted Kremenek8dd56462008-04-18 03:39:05 +00001072 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001073
Ted Kremenekcb612922008-04-18 19:23:43 +00001074 if (!N || Leaked.empty())
Ted Kremenek4f285152008-04-18 16:30:14 +00001075 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001076
Ted Kremenek8dd56462008-04-18 03:39:05 +00001077 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1078 assert (!LeaksAtNode);
1079 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001080
1081 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1082 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001083 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001084}
1085
Ted Kremenek4fd88972008-04-17 18:12:53 +00001086 // Return statements.
1087
1088void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1089 GRExprEngine& Eng,
1090 GRStmtNodeBuilder<ValueState>& Builder,
1091 ReturnStmt* S,
1092 ExplodedNode<ValueState>* Pred) {
1093
1094 Expr* RetE = S->getRetValue();
1095 if (!RetE) return;
1096
1097 ValueStateManager& StateMgr = Eng.getStateManager();
1098 ValueState* St = Builder.GetState(Pred);
1099 RVal V = StateMgr.GetRVal(St, RetE);
1100
1101 if (!isa<lval::SymbolVal>(V))
1102 return;
1103
1104 // Get the reference count binding (if any).
1105 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1106 RefBindings B = GetRefBindings(*St);
1107 RefBindings::TreeTy* T = B.SlimFind(Sym);
1108
1109 if (!T)
1110 return;
1111
1112 // Change the reference count.
1113
1114 RefVal X = T->getValue().second;
1115
1116 switch (X.getKind()) {
1117
1118 case RefVal::Owned: {
1119 unsigned cnt = X.getCount();
1120 X = RefVal::makeReturnedOwned(cnt);
1121 break;
1122 }
1123
1124 case RefVal::NotOwned: {
1125 unsigned cnt = X.getCount();
1126 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1127 : RefVal::makeReturnedNotOwned();
1128 break;
1129 }
1130
1131 default:
1132 // None of the error states should be possible at this point.
1133 // A symbol could not have been leaked (yet) if we are returning it
1134 // (and thus it is still live), and the other errors are hard errors.
1135 assert(false);
1136 return;
1137 }
1138
1139 // Update the binding.
1140
1141 ValueState StImpl = *St;
1142 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1143 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1144}
1145
Ted Kremenekcb612922008-04-18 19:23:43 +00001146// Assumptions.
1147
1148ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1149 RVal Cond, bool Assumption,
1150 bool& isFeasible) {
1151
1152 // FIXME: We may add to the interface of EvalAssume the list of symbols
1153 // whose assumptions have changed. For now we just iterate through the
1154 // bindings and check if any of the tracked symbols are NULL. This isn't
1155 // too bad since the number of symbols we will track in practice are
1156 // probably small and EvalAssume is only called at branches and a few
1157 // other places.
1158
1159 RefBindings B = GetRefBindings(*St);
1160
1161 if (B.isEmpty())
1162 return St;
1163
1164 bool changed = false;
1165
1166 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1167
1168 // Check if the symbol is null (or equal to any constant).
1169 // If this is the case, stop tracking the symbol.
1170
1171 if (St->getSymVal(I.getKey())) {
1172 changed = true;
1173 B = RefBFactory.Remove(B, I.getKey());
1174 }
1175 }
1176
1177 if (!changed)
1178 return St;
1179
1180 ValueState StImpl = *St;
1181 StImpl.CheckerState = B.getRoot();
1182 return Eng.getStateManager().getPersistentState(StImpl);
1183}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001184
1185CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001186 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001187 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001188
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001189 // FIXME: This dispatch can potentially be sped up by unifiying it into
1190 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001191
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001192 switch (E) {
1193 default:
1194 assert (false && "Unhandled CFRef transition.");
1195
1196 case DoNothing:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001197 if (V.getKind() == RefVal::Released) {
1198 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001199 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001200 break;
1201 }
1202
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001203 return B;
1204
1205 case IncRef:
1206 switch (V.getKind()) {
1207 default:
1208 assert(false);
1209
1210 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001211 V = RefVal::makeOwned(V.getCount()+1);
1212 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001213
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001214 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001215 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001216 break;
1217
1218 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001219 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001220 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001221 break;
1222 }
1223
Ted Kremenek940b1d82008-04-10 23:44:06 +00001224 break;
1225
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001226 case DecRef:
1227 switch (V.getKind()) {
1228 default:
1229 assert (false);
1230
1231 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001232 unsigned Count = V.getCount();
1233 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001234 break;
1235 }
1236
Ted Kremenek61b9f872008-04-10 23:09:18 +00001237 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001238 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001239
Ted Kremenek4fd88972008-04-17 18:12:53 +00001240 if (Count > 0)
1241 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001242 else {
1243 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001244 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001245 }
1246
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001247 break;
1248 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001249
1250 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001251 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001252 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001253 break;
1254 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001255
1256 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001257 }
1258
1259 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001260}
1261
Ted Kremenekfa34b332008-04-09 01:10:13 +00001262
1263//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001264// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001265//===----------------------------------------------------------------------===//
1266
Ted Kremenek8dd56462008-04-18 03:39:05 +00001267namespace {
1268
1269 //===-------------===//
1270 // Bug Descriptions. //
1271 //===-------------===//
1272
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001273 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001274 protected:
1275 CFRefCount& TF;
1276
1277 public:
1278 CFRefBug(CFRefCount& tf) : TF(tf) {}
1279 };
1280
1281 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1282 public:
1283 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1284
1285 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001286 return "Core Foundation: Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001287 }
1288 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001289 return "Reference-counted object is used"
1290 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001291 }
1292
1293 virtual void EmitWarnings(BugReporter& BR);
1294
1295 };
1296
1297 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1298 public:
1299 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1300
1301 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001302 return "Core Foundation: Release of non-owned object";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001303 }
1304 virtual const char* getDescription() const {
1305 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001306 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001307 "The object is not owned at this point by the caller.";
1308 }
1309
1310 virtual void EmitWarnings(BugReporter& BR);
1311 };
1312
1313 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1314 public:
1315 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1316
1317 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001318 return "Core Foundation: Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001319 }
1320
1321 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001322 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001323 }
1324
1325 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekcb612922008-04-18 19:23:43 +00001326 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001327 };
1328
1329 //===---------===//
1330 // Bug Reports. //
1331 //===---------===//
1332
1333 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1334 SymbolID Sym;
1335 public:
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001336 CFRefReport(BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001337 : RangedBugReport(D, n), Sym(sym) {}
1338
1339 virtual ~CFRefReport() {}
1340
1341
1342 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1343 ExplodedNode<ValueState>* PrevN,
1344 ExplodedGraph<ValueState>& G,
1345 BugReporter& BR);
1346 };
1347
1348
1349} // end anonymous namespace
1350
1351void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1352 GRSimpleVals::RegisterChecks(Eng);
1353 Eng.Register(new UseAfterRelease(*this));
1354 Eng.Register(new BadRelease(*this));
1355 Eng.Register(new Leak(*this));
1356}
1357
1358PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1359 ExplodedNode<ValueState>* PrevN,
1360 ExplodedGraph<ValueState>& G,
1361 BugReporter& BR) {
1362
1363 // Check if the type state has changed.
1364
1365 ValueState* PrevSt = PrevN->getState();
1366 ValueState* CurrSt = N->getState();
1367
1368 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1369 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1370
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001371 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1372 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001373
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001374 if (!CurrT)
1375 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001376
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001377 const char* Msg = NULL;
1378 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001379
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001380 if (!PrevT) {
1381
1382 // Check for the point where we start tracking the value.
1383
1384 if (CurrV.isOwned())
1385 Msg = "Function call returns 'Owned' Core Foundation object.";
1386 else {
1387 assert (CurrV.isNotOwned());
1388 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1389 }
1390
1391 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1392 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1393 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1394
1395 if (Expr* Exp = dyn_cast<Expr>(S))
1396 P->addRange(Exp->getSourceRange());
1397
1398 return P;
1399 }
1400
1401 // Determine if the typestate has changed.
1402
1403 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1404
1405 if (PrevV == CurrV)
1406 return NULL;
1407
1408 // The typestate has changed.
1409
1410 std::ostringstream os;
1411
1412 switch (CurrV.getKind()) {
1413 case RefVal::Owned:
1414 case RefVal::NotOwned:
1415 assert (PrevV.getKind() == CurrV.getKind());
1416
1417 if (PrevV.getCount() > CurrV.getCount())
1418 os << "Reference count decremented.";
1419 else
1420 os << "Reference count incremented.";
1421
Ted Kremenek79c140b2008-04-18 05:32:44 +00001422 if (CurrV.getCount()) {
1423 os << " Object has +" << CurrV.getCount();
1424
1425 if (CurrV.getCount() > 1)
1426 os << " reference counts.";
1427 else
1428 os << " reference count.";
1429 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001430
1431 Msg = os.str().c_str();
1432
1433 break;
1434
1435 case RefVal::Released:
1436 Msg = "Object released.";
1437 break;
1438
1439 case RefVal::ReturnedOwned:
1440 Msg = "Object returned to caller. "
1441 "Caller gets ownership of object.";
1442 break;
1443
1444 case RefVal::ReturnedNotOwned:
1445 Msg = "Object returned to caller. "
1446 "Caller does not get ownership of object.";
1447 break;
1448
1449 default:
1450 return NULL;
1451 }
1452
1453 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1454 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1455 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1456
1457 // Add the range by scanning the children of the statement for any bindings
1458 // to Sym.
1459
1460 ValueStateManager& VSM = BR.getEngine().getStateManager();
1461
1462 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1463 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1464 RVal X = VSM.GetRVal(CurrSt, Exp);
1465
1466 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1467 if (SV->getSymbol() == Sym) {
1468 P->addRange(Exp->getSourceRange()); break;
1469 }
1470 }
1471
1472 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001473}
1474
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001475void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001476
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001477 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1478 E = TF.use_after_end(); I != E; ++I) {
1479
Ted Kremenek8dd56462008-04-18 03:39:05 +00001480 CFRefReport report(*this, I->first, I->second.second);
1481 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00001482 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001483 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001484}
1485
1486void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001487
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001488 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1489 E = TF.bad_release_end(); I != E; ++I) {
1490
Ted Kremenek8dd56462008-04-18 03:39:05 +00001491 CFRefReport report(*this, I->first, I->second.second);
1492 report.addRange(I->second.first->getSourceRange());
1493 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001494 }
1495}
Ted Kremenekfa34b332008-04-09 01:10:13 +00001496
Ted Kremenek989d5192008-04-17 23:43:50 +00001497void Leak::EmitWarnings(BugReporter& BR) {
1498
1499 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1500 E = TF.leaks_end(); I != E; ++I) {
1501
Ted Kremenek8dd56462008-04-18 03:39:05 +00001502 std::vector<SymbolID>& SymV = *(I->second);
1503 unsigned n = SymV.size();
1504
1505 for (unsigned i = 0; i < n; ++i) {
1506 CFRefReport report(*this, I->first, SymV[i]);
1507 BR.EmitWarning(report);
1508 }
Ted Kremenek989d5192008-04-17 23:43:50 +00001509 }
1510}
1511
Ted Kremenekcb612922008-04-18 19:23:43 +00001512void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1513 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1514 I!=E; ++I)
1515 Nodes.push_back(I->first);
1516}
1517
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001518//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00001519// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001520//===----------------------------------------------------------------------===//
1521
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00001522GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx) {
1523 return new CFRefCount(Ctx);
1524}