blob: 4d86dd5d6dd5f3a2cb31171379114f518e16044a [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 Kremenek827f93b2008-03-06 00:08:09 +000016#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenekdd0126b2008-03-31 18:26:32 +000017#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000018#include "clang/Analysis/LocalCheckers.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000019#include "clang/Analysis/PathDiagnostic.h"
20#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremeneka7338b42008-03-11 06:39:11 +000021#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000024#include "llvm/Support/Compiler.h"
Ted Kremenek3b11f7a2008-03-11 19:44:10 +000025#include <ostream>
Ted Kremenek827f93b2008-03-06 00:08:09 +000026
27using namespace clang;
28
Ted Kremenek7d421f32008-04-09 23:49:11 +000029//===----------------------------------------------------------------------===//
30// Symbolic Evaluation of Reference Counting Logic
31//===----------------------------------------------------------------------===//
32
Ted Kremeneka7338b42008-03-11 06:39:11 +000033namespace {
34 enum ArgEffect { IncRef, DecRef, DoNothing };
35 typedef std::vector<ArgEffect> ArgEffects;
36}
Ted Kremenek827f93b2008-03-06 00:08:09 +000037
Ted Kremeneka7338b42008-03-11 06:39:11 +000038namespace llvm {
39 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +000040 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremeneka7338b42008-03-11 06:39:11 +000041 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I)
42 ID.AddInteger((unsigned) *I);
Ted Kremeneka4c74292008-04-10 22:58:08 +000043 }
Ted Kremeneka7338b42008-03-11 06:39:11 +000044 };
45} // end llvm namespace
46
47namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +000048
Ted Kremeneka7338b42008-03-11 06:39:11 +000049class RetEffect {
50public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000051 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
52 NotOwnedSymbol = 0x3 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000053
54private:
55 unsigned Data;
Ted Kremeneka4c74292008-04-10 22:58:08 +000056 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000057
Ted Kremeneka7338b42008-03-11 06:39:11 +000058public:
59
60 Kind getKind() const { return (Kind) (Data & 0x3); }
61
62 unsigned getValue() const {
63 assert(getKind() == Alias);
Ted Kremeneka4c74292008-04-10 22:58:08 +000064 return Data >> 2;
Ted Kremeneka7338b42008-03-11 06:39:11 +000065 }
Ted Kremenekffefc352008-04-11 22:25:11 +000066
Ted Kremeneka7338b42008-03-11 06:39:11 +000067 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000068
Ted Kremeneka7338b42008-03-11 06:39:11 +000069 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000070
Ted Kremeneka7338b42008-03-11 06:39:11 +000071 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
72
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000073 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
74
Ted Kremeneka7338b42008-03-11 06:39:11 +000075 operator Kind() const { return getKind(); }
76
77 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
78};
79
80
81class CFRefSummary : public llvm::FoldingSetNode {
82 ArgEffects* Args;
83 RetEffect Ret;
84public:
85
86 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
87
88 unsigned getNumArgs() const { return Args->size(); }
89
Ted Kremenek0d721572008-03-11 17:48:22 +000090 ArgEffect getArg(unsigned idx) const {
91 assert (idx < getNumArgs());
92 return (*Args)[idx];
93 }
94
Ted Kremenekce3ed1e2008-03-12 01:21:45 +000095 RetEffect getRet() const {
96 return Ret;
97 }
98
Ted Kremeneka7338b42008-03-11 06:39:11 +000099 typedef ArgEffects::const_iterator arg_iterator;
100
101 arg_iterator begin_args() const { return Args->begin(); }
102 arg_iterator end_args() const { return Args->end(); }
103
104 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
105 ID.AddPointer(A);
106 ID.Add(R);
107 }
108
109 void Profile(llvm::FoldingSetNodeID& ID) const {
110 Profile(ID, Args, Ret);
111 }
112};
113
114
115class CFRefSummaryManager {
116 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
117 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
118 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
119
Ted Kremeneka4c74292008-04-10 22:58:08 +0000120 ASTContext& Ctx;
121 SummarySetTy SummarySet;
122 SummaryMapTy SummaryMap;
123 AESetTy AESet;
124 llvm::BumpPtrAllocator BPAlloc;
125 ArgEffects ScratchArgs;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000126
127
128 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000129
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000130 CFRefSummary* getCannedCFSummary(FunctionTypeProto* FT, bool isRetain);
131
132 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
133
134 CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
135 CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);
136
137 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
138
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000139 void FillDoNothing(unsigned Args);
140
141
Ted Kremeneka7338b42008-03-11 06:39:11 +0000142public:
Ted Kremeneka4c74292008-04-10 22:58:08 +0000143 CFRefSummaryManager(ASTContext& ctx) : Ctx(ctx) {}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000144 ~CFRefSummaryManager();
145
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000146 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000147};
148
149} // end anonymous namespace
150
151//===----------------------------------------------------------------------===//
152// Implementation of checker data structures.
153//===----------------------------------------------------------------------===//
154
155CFRefSummaryManager::~CFRefSummaryManager() {
156
157 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
158 // mitigating the need to do explicit cleanup of the
159 // Argument-Effect summaries.
160
161 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
162 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000163}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000164
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000165ArgEffects* CFRefSummaryManager::getArgEffects() {
166
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000167 llvm::FoldingSetNodeID profile;
168 profile.Add(ScratchArgs);
169 void* InsertPos;
170
171 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
172 AESet.FindNodeOrInsertPos(profile, InsertPos);
173
174 if (E) {
175 ScratchArgs.clear();
176 return &E->getValue();
177 }
178
179 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
180 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
181
182 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
183 AESet.InsertNode(E, InsertPos);
184
185 ScratchArgs.clear();
186 return &E->getValue();
187}
188
189CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
190 RetEffect RE) {
191
192 llvm::FoldingSetNodeID profile;
193 CFRefSummary::Profile(profile, AE, RE);
194 void* InsertPos;
195
196 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
197
198 if (Summ)
199 return Summ;
200
201 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
202 new (Summ) CFRefSummary(AE, RE);
203 SummarySet.InsertNode(Summ, InsertPos);
204
205 return Summ;
206}
207
208
209CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
210 ASTContext& Ctx) {
211
212 SourceLocation Loc = FD->getLocation();
213
214 if (!Loc.isFileID())
215 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000216
Ted Kremeneka7338b42008-03-11 06:39:11 +0000217 { // Look into our cache of summaries to see if we have already computed
218 // a summary for this FunctionDecl.
219
220 SummaryMapTy::iterator I = SummaryMap.find(FD);
221
222 if (I != SummaryMap.end())
223 return I->second;
224 }
225
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000226#if 0
227 SourceManager& SrcMgr = Ctx.getSourceManager();
228 unsigned fid = Loc.getFileID();
229 const FileEntry* FE = SrcMgr.getFileEntryForID(fid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000230
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000231 if (!FE)
232 return NULL;
233
234 const char* DirName = FE->getDir()->getName();
235 assert (DirName);
236 assert (strlen(DirName) > 0);
237
238 if (!strstr(DirName, "CoreFoundation")) {
239 SummaryMap[FD] = NULL;
240 return NULL;
241 }
242#endif
243
244 const char* FName = FD->getIdentifier()->getName();
245
246 if (FName[0] == 'C' && FName[1] == 'F') {
247 CFRefSummary* S = getCFSummary(FD, FName);
248 SummaryMap[FD] = S;
249 return S;
250 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000251
252 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000253}
254
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000255CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
256 const char* FName) {
257
258 // For now, only generate summaries for functions that have a prototype.
259
260 FunctionTypeProto* FT =
261 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
262
263 if (!FT)
264 return NULL;
265
266 FName += 2;
267
268 if (strcmp(FName, "Retain") == 0)
269 return getCannedCFSummary(FT, true);
270
271 if (strcmp(FName, "Release") == 0)
272 return getCannedCFSummary(FT, false);
273
274 assert (ScratchArgs.empty());
275 bool usesCreateRule = false;
276
277 if (strstr(FName, "Create"))
278 usesCreateRule = true;
279
280 if (!usesCreateRule && strstr(FName, "Copy"))
281 usesCreateRule = true;
282
283 if (usesCreateRule)
284 return getCFSummaryCreateRule(FT);
285
286 if (strstr(FName, "Get"))
287 return getCFSummaryGetRule(FT);
288
289 return NULL;
290}
291
292CFRefSummary* CFRefSummaryManager::getCannedCFSummary(FunctionTypeProto* FT,
293 bool isRetain) {
294
295 if (FT->getNumArgs() != 1)
296 return NULL;
297
298 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
299
300 if (!ArgT)
301 return NULL;
302
303 // For CFRetain/CFRelease, the first (and only) argument is of type
304 // "CFTypeRef".
305
306 const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
307 assert (TDName);
308
Ted Kremeneka4c74292008-04-10 22:58:08 +0000309 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000310 return NULL;
311
312 if (!ArgT->isPointerType())
313 return NULL;
Ted Kremeneka4c74292008-04-10 22:58:08 +0000314
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000315 QualType RetTy = FT->getResultType();
316
Ted Kremeneka4c74292008-04-10 22:58:08 +0000317 if (isRetain) {
318 // CFRetain: the return type should also be "CFTypeRef".
319 if (RetTy.getTypePtr() != ArgT)
320 return NULL;
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000321
322 // The function's interface checks out. Generate a canned summary.
323 assert (ScratchArgs.empty());
324 ScratchArgs.push_back(IncRef);
325 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremeneka4c74292008-04-10 22:58:08 +0000326 }
327 else {
328 // CFRelease: the return type should be void.
329
330 if (RetTy != Ctx.VoidTy)
331 return NULL;
Ted Kremeneka4c74292008-04-10 22:58:08 +0000332
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000333 assert (ScratchArgs.empty());
334 ScratchArgs.push_back(DecRef);
335 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
336 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000337}
338
339static bool isCFRefType(QualType T) {
340
341 if (!T->isPointerType())
342 return false;
343
344 // Check the typedef for the name "CF" and the substring "Ref".
345
346 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
347
348 if (!TD)
349 return false;
350
351 const char* TDName = TD->getDecl()->getIdentifier()->getName();
352 assert (TDName);
353
354 if (TDName[0] != 'C' || TDName[1] != 'F')
355 return false;
356
357 if (strstr(TDName, "Ref") == 0)
358 return false;
359
360 return true;
361}
362
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000363void CFRefSummaryManager::FillDoNothing(unsigned Args) {
364 for (unsigned i = 0; i != Args; ++i)
365 ScratchArgs.push_back(DoNothing);
366}
367
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000368
369CFRefSummary*
370CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
371
372 if (!isCFRefType(FT->getResultType()))
Ted Kremenekd4244d42008-04-11 20:11:19 +0000373 return NULL;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000374
375 assert (ScratchArgs.empty());
376
377 // FIXME: Add special-cases for functions that retain/release. For now
378 // just handle the default case.
379
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000380 FillDoNothing(FT->getNumArgs());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000381 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
382}
383
384CFRefSummary*
385CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
386
Ted Kremenekd4244d42008-04-11 20:11:19 +0000387 QualType RetTy = FT->getResultType();
388
389 // FIXME: For now we assume that all pointer types returned are referenced
390 // counted. Since this is the "Get" rule, we assume non-ownership, which
391 // works fine for things that are not reference counted. We do this because
392 // some generic data structures return "void*". We need something better
393 // in the future.
394
395 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
396 return NULL;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000397
398 assert (ScratchArgs.empty());
399
400 // FIXME: Add special-cases for functions that retain/release. For now
401 // just handle the default case.
402
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000403 FillDoNothing(FT->getNumArgs());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000404 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
405}
406
Ted Kremeneka7338b42008-03-11 06:39:11 +0000407//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +0000408// Bug Descriptions.
409//===----------------------------------------------------------------------===//
410
411namespace {
412
413 class CFRefCount;
414
415 class VISIBILITY_HIDDEN CFRefBug : public BugType {
416 protected:
417 CFRefCount& TF;
418
419 public:
420 CFRefBug(CFRefCount& tf) : TF(tf) {}
421 };
422
423 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
424 public:
425 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
426
427 virtual const char* getName() const {
428 return "(CoreFoundation) use-after-release";
429 }
430 virtual const char* getDescription() const {
431 return "(CoreFoundation) Reference-counted object is used"
432 " after it is released.";
433 }
434
435 virtual void EmitWarnings(BugReporter& BR);
436
437 };
438
439 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
440 public:
441 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
442
443 virtual const char* getName() const {
444 return "(CoreFoundation) release of non-owned object";
445 }
446 virtual const char* getDescription() const {
447 return "Incorrect decrement of the reference count of a "
448 "CoreFoundation object:\n"
449 "The object is not owned at this point by the caller.";
450 }
451
452 virtual void EmitWarnings(BugReporter& BR);
453 };
454
455} // end anonymous namespace
456
457//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000458// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000459//===----------------------------------------------------------------------===//
460
Ted Kremeneka7338b42008-03-11 06:39:11 +0000461namespace {
462
Ted Kremenek7d421f32008-04-09 23:49:11 +0000463class VISIBILITY_HIDDEN RefVal {
Ted Kremenek0d721572008-03-11 17:48:22 +0000464 unsigned Data;
465
466 RefVal(unsigned K, unsigned D) : Data((D << 3) | K) {
Ted Kremeneka4c74292008-04-10 22:58:08 +0000467 assert ((K & ~0x7) == 0x0);
Ted Kremenek0d721572008-03-11 17:48:22 +0000468 }
469
470 RefVal(unsigned K) : Data(K) {
Ted Kremeneka4c74292008-04-10 22:58:08 +0000471 assert ((K & ~0x7) == 0x0);
Ted Kremenek0d721572008-03-11 17:48:22 +0000472 }
473
474public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000475
Ted Kremenekc4f81022008-04-10 23:09:18 +0000476 enum Kind { Owned = 0, NotOwned = 1, Released = 2,
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000477 ErrorUseAfterRelease = 3, ErrorReleaseNotOwned = 4,
478 ErrorLeak = 5 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000479
Ted Kremenekc4f81022008-04-10 23:09:18 +0000480 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000481
482 unsigned getCount() const {
Ted Kremenekc4f81022008-04-10 23:09:18 +0000483 assert (getKind() == Owned || getKind() == NotOwned);
Ted Kremenek0d721572008-03-11 17:48:22 +0000484 return Data >> 3;
485 }
486
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000487 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
488
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000489 static bool isLeak(Kind k) { return k == ErrorLeak; }
490
Ted Kremenekffefc352008-04-11 22:25:11 +0000491 bool isOwned() const {
492 return getKind() == Owned;
493 }
494
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000495 bool isNotOwned() const {
496 return getKind() == NotOwned;
497 }
498
Ted Kremenekc4f81022008-04-10 23:09:18 +0000499 static RefVal makeOwned(unsigned Count = 0) {
500 return RefVal(Owned, Count);
501 }
502
503 static RefVal makeNotOwned(unsigned Count = 0) {
504 return RefVal(NotOwned, Count);
505 }
506
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000507 static RefVal makeLeak() { return RefVal(ErrorLeak); }
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); }
511
512 bool operator==(const RefVal& X) const { return Data == X.Data; }
513 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000514
515 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000516};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000517
518void RefVal::print(std::ostream& Out) const {
519 switch (getKind()) {
520 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000521 case Owned: {
522 Out << "Owned";
523 unsigned cnt = getCount();
524 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000525 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000526 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000527
Ted Kremenekc4f81022008-04-10 23:09:18 +0000528 case NotOwned: {
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000529 Out << "Not-Owned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000530 unsigned cnt = getCount();
531 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000532 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000533 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000534
535 case Released:
536 Out << "Released";
537 break;
538
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000539 case ErrorLeak:
540 Out << "Leaked";
541 break;
542
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000543 case ErrorUseAfterRelease:
544 Out << "Use-After-Release [ERROR]";
545 break;
546
547 case ErrorReleaseNotOwned:
548 Out << "Release of Not-Owned [ERROR]";
549 break;
550 }
551}
Ted Kremenek0d721572008-03-11 17:48:22 +0000552
Ted Kremenek7aef4842008-04-16 20:40:59 +0000553//===----------------------------------------------------------------------===//
554// Transfer functions.
555//===----------------------------------------------------------------------===//
556
557static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
558 IdentifierInfo* II = &Ctx.Idents.get(name);
559 return Ctx.Selectors.getSelector(0, &II);
560}
561
Ted Kremenek7d421f32008-04-09 23:49:11 +0000562class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000563
564 // Type definitions.
565
Ted Kremenek0d721572008-03-11 17:48:22 +0000566 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000567 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000568
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000569 typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> UseAfterReleasesTy;
570 typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> ReleasesNotOwnedTy;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000571
572 typedef llvm::SmallVector<std::pair<SymbolID, ExplodedNode<ValueState>*>, 2>
573 LeaksTy;
574
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000575
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000576 class BindingsPrinter : public ValueState::CheckerStatePrinter {
577 public:
578 virtual void PrintCheckerState(std::ostream& Out, void* State,
579 const char* nl, const char* sep);
580 };
581
582 // Instance variables.
583
Ted Kremeneka7338b42008-03-11 06:39:11 +0000584 CFRefSummaryManager Summaries;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000585 RefBFactoryTy RefBFactory;
586
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000587 UseAfterReleasesTy UseAfterReleases;
588 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000589 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000590
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000591 BindingsPrinter Printer;
592
Ted Kremenek1feab292008-04-16 04:28:53 +0000593 Selector RetainSelector;
594 Selector ReleaseSelector;
595
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000596 // Private methods.
Ted Kremenek1feab292008-04-16 04:28:53 +0000597
Ted Kremeneka7338b42008-03-11 06:39:11 +0000598 static RefBindings GetRefBindings(ValueState& StImpl) {
599 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
600 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000601
Ted Kremeneka7338b42008-03-11 06:39:11 +0000602 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
603 StImpl.CheckerState = B.getRoot();
604 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000605
Ted Kremeneka7338b42008-03-11 06:39:11 +0000606 RefBindings Remove(RefBindings B, SymbolID sym) {
607 return RefBFactory.Remove(B, sym);
608 }
609
Ted Kremenek0d721572008-03-11 17:48:22 +0000610 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000611 RefVal::Kind& hasErr);
612
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000613 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
614 GRStmtNodeBuilder<ValueState>& Builder,
615 Expr* NodeExpr, Expr* ErrorExpr,
616 ExplodedNode<ValueState>* Pred,
617 ValueState* St,
618 RefVal::Kind hasErr);
619
620 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
621 SymbolID sid, RefVal V, bool& hasLeak);
622
623 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
624 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000625
626public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000627
Ted Kremenek1feab292008-04-16 04:28:53 +0000628 CFRefCount(ASTContext& Ctx)
629 : Summaries(Ctx),
630 RetainSelector(GetUnarySelector("retain", Ctx)),
631 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
632
Ted Kremeneka7338b42008-03-11 06:39:11 +0000633 virtual ~CFRefCount() {}
Ted Kremenek7d421f32008-04-09 23:49:11 +0000634
635 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000636
637 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
638 return &Printer;
639 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000640
641 // Calls.
642
643 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000644 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000645 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000646 CallExpr* CE, LVal L,
647 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000648
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000649 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
650 GRExprEngine& Engine,
651 GRStmtNodeBuilder<ValueState>& Builder,
652 ObjCMessageExpr* ME,
653 ExplodedNode<ValueState>* Pred);
654
655 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
656 GRExprEngine& Engine,
657 GRStmtNodeBuilder<ValueState>& Builder,
658 ObjCMessageExpr* ME,
659 ExplodedNode<ValueState>* Pred);
660
Ted Kremenek7aef4842008-04-16 20:40:59 +0000661 // Stores.
662
663 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
664 GRExprEngine& Engine,
665 GRStmtNodeBuilder<ValueState>& Builder,
666 Expr* E, ExplodedNode<ValueState>* Pred,
667 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000668 // End-of-path.
669
670 virtual void EvalEndPath(GRExprEngine& Engine,
671 GREndPathNodeBuilder<ValueState>& Builder);
672
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000673 // Error iterators.
674
675 typedef UseAfterReleasesTy::iterator use_after_iterator;
676 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
677
Ted Kremenek7d421f32008-04-09 23:49:11 +0000678 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
679 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000680
Ted Kremenek7d421f32008-04-09 23:49:11 +0000681 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
682 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000683};
684
685} // end anonymous namespace
686
Ted Kremenek7d421f32008-04-09 23:49:11 +0000687void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
688 GRSimpleVals::RegisterChecks(Eng);
689 Eng.Register(new UseAfterRelease(*this));
690 Eng.Register(new BadRelease(*this));
691}
692
693
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000694void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
695 void* State, const char* nl,
696 const char* sep) {
697 RefBindings B((RefBindings::TreeTy*) State);
698
699 if (State)
700 Out << sep << nl;
701
702 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
703 Out << (*I).first << " : ";
704 (*I).second.print(Out);
705 Out << nl;
706 }
707}
708
Ted Kremenek455dd862008-04-11 20:23:24 +0000709static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
710 return Summ ? Summ->getArg(idx) : DoNothing;
711}
712
713static inline RetEffect GetRetE(CFRefSummary* Summ) {
714 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
715}
716
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000717void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
718 GRStmtNodeBuilder<ValueState>& Builder,
719 Expr* NodeExpr, Expr* ErrorExpr,
720 ExplodedNode<ValueState>* Pred,
721 ValueState* St,
722 RefVal::Kind hasErr) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000723 Builder.BuildSinks = true;
724 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
725
726 if (!N) return;
727
728 switch (hasErr) {
729 default: assert(false);
730 case RefVal::ErrorUseAfterRelease:
731 UseAfterReleases[N] = ErrorExpr;
732 break;
733
734 case RefVal::ErrorReleaseNotOwned:
735 ReleasesNotOwned[N] = ErrorExpr;
736 break;
737 }
738}
739
Ted Kremenek827f93b2008-03-06 00:08:09 +0000740void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000741 GRExprEngine& Eng,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000742 GRStmtNodeBuilder<ValueState>& Builder,
743 CallExpr* CE, LVal L,
744 ExplodedNode<ValueState>* Pred) {
745
Ted Kremenekce0767f2008-03-12 21:06:49 +0000746 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000747
Ted Kremenek73ba0472008-04-14 17:45:13 +0000748 CFRefSummary* Summ = NULL;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000749
750 // Get the summary.
Ted Kremenek827f93b2008-03-06 00:08:09 +0000751
Ted Kremenek73ba0472008-04-14 17:45:13 +0000752 if (isa<lval::FuncVal>(L)) {
753 lval::FuncVal FV = cast<lval::FuncVal>(L);
754 FunctionDecl* FD = FV.getDecl();
755 Summ = Summaries.getSummary(FD, Eng.getContext());
756 }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000757
Ted Kremeneka7338b42008-03-11 06:39:11 +0000758 // Get the state.
759
760 ValueState* St = Builder.GetState(Pred);
761
762 // Evaluate the effects of the call.
763
764 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000765 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek455dd862008-04-11 20:23:24 +0000766
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000767 // This function has a summary. Evaluate the effect of the arguments.
768
769 unsigned idx = 0;
770
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000771 Expr* ErrorExpr = NULL;
772
773 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
774 I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000775
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000776 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000777
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000778 if (isa<lval::SymbolVal>(V)) {
779 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000780 RefBindings B = GetRefBindings(StVals);
781
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000782 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000783 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000784 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000785
Ted Kremenek1feab292008-04-16 04:28:53 +0000786 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000787 ErrorExpr = *I;
788 break;
789 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000790 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000791 }
792 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
793
794 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
795 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000796 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000797 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000798 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000799
800 St = StateMgr.getPersistentState(StVals);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000801
Ted Kremenek1feab292008-04-16 04:28:53 +0000802 if (hasErr) {
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000803 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St, hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000804 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000805 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000806
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000807 // Finally, consult the summary for the return value.
808
Ted Kremenek455dd862008-04-11 20:23:24 +0000809 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000810
811 switch (RE.getKind()) {
812 default:
813 assert (false && "Unhandled RetEffect."); break;
814
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000815 case RetEffect::NoRet:
Ted Kremenek455dd862008-04-11 20:23:24 +0000816
817 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000818 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
819 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000820
821 if (CE->getType() != Eng.getContext().VoidTy) {
822 unsigned Count = Builder.getCurrentBlockCount();
823 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
824
825 RVal X = CE->getType()->isPointerType()
826 ? cast<RVal>(lval::SymbolVal(Sym))
827 : cast<RVal>(nonlval::SymbolVal(Sym));
828
829 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
830 }
831
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000832 break;
833
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000834 case RetEffect::Alias: {
835 unsigned idx = RE.getValue();
836 assert (idx < CE->getNumArgs());
837 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenekce0767f2008-03-12 21:06:49 +0000838 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000839 break;
840 }
841
842 case RetEffect::OwnedSymbol: {
843 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000844 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000845
846 ValueState StImpl = *St;
847 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000848 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000849
850 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
851 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000852 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000853
854 break;
855 }
856
857 case RetEffect::NotOwnedSymbol: {
858 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000859 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000860
861 ValueState StImpl = *St;
862 RefBindings B = GetRefBindings(StImpl);
863 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
864
865 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
866 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000867 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000868
869 break;
870 }
871 }
872
Ted Kremenekf10f2882008-03-21 21:30:14 +0000873 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek827f93b2008-03-06 00:08:09 +0000874}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000875
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000876
877void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
878 GRExprEngine& Eng,
879 GRStmtNodeBuilder<ValueState>& Builder,
880 ObjCMessageExpr* ME,
881 ExplodedNode<ValueState>* Pred) {
882
883 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
884 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
885}
886
887bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
888 GRExprEngine& Eng,
889 GRStmtNodeBuilder<ValueState>& Builder,
890 ObjCMessageExpr* ME,
891 ExplodedNode<ValueState>* Pred) {
892
Ted Kremenek1feab292008-04-16 04:28:53 +0000893 // Handle "toll-free bridging" of calls to "Release" and "Retain".
894
895 // FIXME: track the underlying object type associated so that we can
896 // flag illegal uses of toll-free bridging (or at least handle it
897 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000898
899 Selector S = ME->getSelector();
900
901 if (!S.isUnarySelector())
902 return true;
903
Ted Kremenek1feab292008-04-16 04:28:53 +0000904 Expr* Receiver = ME->getReceiver();
905
906 if (!Receiver)
907 return true;
908
909 // Check if we are calling "Retain" or "Release".
910
911 bool isRetain = false;
912
913 if (S == RetainSelector)
914 isRetain = true;
915 else if (S != ReleaseSelector)
916 return true;
917
918 // We have "Retain" or "Release". Get the reference binding.
919
920 ValueStateManager& StateMgr = Eng.getStateManager();
921 ValueState* St = Builder.GetState(Pred);
922 RVal V = StateMgr.GetRVal(St, Receiver);
923
924 if (!isa<lval::SymbolVal>(V))
925 return true;
926
927 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
928 RefBindings B = GetRefBindings(*St);
929
930 RefBindings::TreeTy* T = B.SlimFind(Sym);
931
932 if (!T)
933 return true;
934
935 RefVal::Kind hasErr = (RefVal::Kind) 0;
936 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
937
938 // Create a new state with the updated bindings.
939
940 ValueState StVals = *St;
941 SetRefBindings(StVals, B);
942 St = StateMgr.getPersistentState(StVals);
943
944 // Create an error node if it exists.
945
946 if (hasErr)
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000947 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr);
Ted Kremenek1feab292008-04-16 04:28:53 +0000948 else
949 Builder.MakeNode(Dst, ME, Pred, St);
950
951 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000952}
953
Ted Kremenek7aef4842008-04-16 20:40:59 +0000954// Stores.
955
956void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
957 GRExprEngine& Eng,
958 GRStmtNodeBuilder<ValueState>& Builder,
959 Expr* E, ExplodedNode<ValueState>* Pred,
960 ValueState* St, RVal TargetLV, RVal Val) {
961
962 // Check if we have a binding for "Val" and if we are storing it to something
963 // we don't understand or otherwise the value "escapes" the function.
964
965 if (!isa<lval::SymbolVal>(Val))
966 return;
967
968 // Are we storing to something that causes the value to "escape"?
969
970 bool escapes = false;
971
972 if (!isa<lval::DeclVal>(TargetLV))
973 escapes = true;
974 else
975 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
976
977 if (!escapes)
978 return;
979
980 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
981 RefBindings B = GetRefBindings(*St);
982 RefBindings::TreeTy* T = B.SlimFind(Sym);
983
984 if (!T)
985 return;
986
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000987 // Nuke the binding.
988 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +0000989
990 // Hand of the remaining logic to the parent implementation.
991 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
992}
993
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000994
995ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
996 SymbolID sid) {
997 ValueState StImpl = *St;
998 RefBindings B = GetRefBindings(StImpl);
999 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1000 return VMgr.getPersistentState(StImpl);
1001}
1002
Ted Kremenekffefc352008-04-11 22:25:11 +00001003// End-of-path.
1004
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001005
1006
1007ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1008 ValueState* St, SymbolID sid,
1009 RefVal V, bool& hasLeak) {
1010
1011 hasLeak = V.isOwned() || V.isNotOwned() && V.getCount() > 0;
1012
1013 if (!hasLeak)
1014 return NukeBinding(VMgr, St, sid);
1015
1016 RefBindings B = GetRefBindings(*St);
1017 ValueState StImpl = *St;
1018 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1019 return VMgr.getPersistentState(StImpl);
1020}
1021
1022void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001023 GREndPathNodeBuilder<ValueState>& Builder) {
1024
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001025 ValueState* St = Builder.getState();
1026 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001027
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001028 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001029
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001030 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1031 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001032
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001033 St = HandleSymbolDeath(Eng.getStateManager(), St,
1034 (*I).first, (*I).second, hasLeak);
1035
1036 if (hasLeak) Leaked.push_back((*I).first);
1037 }
1038
1039 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
1040
1041 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1042 E = Leaked.end(); I != E; ++I)
1043 Leaks.push_back(std::make_pair(*I, N));
Ted Kremenekffefc352008-04-11 22:25:11 +00001044}
1045
Ted Kremeneka7338b42008-03-11 06:39:11 +00001046
1047CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001048 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001049 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001050
Ted Kremenek0d721572008-03-11 17:48:22 +00001051 // FIXME: This dispatch can potentially be sped up by unifiying it into
1052 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001053
Ted Kremenek0d721572008-03-11 17:48:22 +00001054 switch (E) {
1055 default:
1056 assert (false && "Unhandled CFRef transition.");
1057
1058 case DoNothing:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001059 if (V.getKind() == RefVal::Released) {
1060 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001061 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001062 break;
1063 }
1064
Ted Kremenek0d721572008-03-11 17:48:22 +00001065 return B;
1066
1067 case IncRef:
1068 switch (V.getKind()) {
1069 default:
1070 assert(false);
1071
1072 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001073 V = RefVal::makeOwned(V.getCount()+1);
1074 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001075
Ted Kremenek0d721572008-03-11 17:48:22 +00001076 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001077 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001078 break;
1079
1080 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001081 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001082 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001083 break;
1084 }
1085
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001086 break;
1087
Ted Kremenek0d721572008-03-11 17:48:22 +00001088 case DecRef:
1089 switch (V.getKind()) {
1090 default:
1091 assert (false);
1092
1093 case RefVal::Owned: {
Ted Kremenekc4f81022008-04-10 23:09:18 +00001094 signed Count = ((signed) V.getCount()) - 1;
1095 V = Count >= 0 ? RefVal::makeOwned(Count) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001096 break;
1097 }
1098
Ted Kremenekc4f81022008-04-10 23:09:18 +00001099 case RefVal::NotOwned: {
1100 signed Count = ((signed) V.getCount()) - 1;
1101
1102 if (Count >= 0)
1103 V = RefVal::makeNotOwned(Count);
1104 else {
1105 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001106 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001107 }
1108
Ted Kremenek0d721572008-03-11 17:48:22 +00001109 break;
1110 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001111
1112 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001113 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001114 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001115 break;
1116 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001117
1118 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001119 }
1120
1121 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001122}
1123
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001124
1125//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001126// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001127//===----------------------------------------------------------------------===//
1128
Ted Kremenek7d421f32008-04-09 23:49:11 +00001129void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001130
Ted Kremenek7d421f32008-04-09 23:49:11 +00001131 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1132 E = TF.use_after_end(); I != E; ++I) {
1133
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001134 RangedBugReport report(*this, I->first);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001135 report.addRange(I->second->getSourceRange());
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001136 BR.EmitPathWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001137 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001138}
1139
1140void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001141
Ted Kremenek7d421f32008-04-09 23:49:11 +00001142 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1143 E = TF.bad_release_end(); I != E; ++I) {
1144
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001145 RangedBugReport report(*this, I->first);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001146 report.addRange(I->second->getSourceRange());
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001147 BR.EmitPathWarning(report);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001148
Ted Kremenek7d421f32008-04-09 23:49:11 +00001149 }
1150}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001151
Ted Kremeneka7338b42008-03-11 06:39:11 +00001152//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001153// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001154//===----------------------------------------------------------------------===//
1155
Ted Kremeneka4c74292008-04-10 22:58:08 +00001156GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx) {
1157 return new CFRefCount(Ctx);
1158}