blob: 4fcef670d327f741b863b414aadf4c51fdfe41d5 [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//===----------------------------------------------------------------------===//
Ted Kremenekd9ccf682008-04-17 18:12:53 +000030// Utility functions.
31//===----------------------------------------------------------------------===//
32
33static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
34 IdentifierInfo* II = &Ctx.Idents.get(name);
35 return Ctx.Selectors.getSelector(0, &II);
36}
37
38//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +000039// Symbolic Evaluation of Reference Counting Logic
40//===----------------------------------------------------------------------===//
41
Ted Kremeneka7338b42008-03-11 06:39:11 +000042namespace {
43 enum ArgEffect { IncRef, DecRef, DoNothing };
44 typedef std::vector<ArgEffect> ArgEffects;
45}
Ted Kremenek827f93b2008-03-06 00:08:09 +000046
Ted Kremeneka7338b42008-03-11 06:39:11 +000047namespace llvm {
48 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +000049 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremeneka7338b42008-03-11 06:39:11 +000050 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I)
51 ID.AddInteger((unsigned) *I);
Ted Kremeneka4c74292008-04-10 22:58:08 +000052 }
Ted Kremeneka7338b42008-03-11 06:39:11 +000053 };
54} // end llvm namespace
55
56namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +000057
Ted Kremeneka7338b42008-03-11 06:39:11 +000058class RetEffect {
59public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000060 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
61 NotOwnedSymbol = 0x3 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000062
63private:
64 unsigned Data;
Ted Kremeneka4c74292008-04-10 22:58:08 +000065 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000066
Ted Kremeneka7338b42008-03-11 06:39:11 +000067public:
68
69 Kind getKind() const { return (Kind) (Data & 0x3); }
70
71 unsigned getValue() const {
72 assert(getKind() == Alias);
Ted Kremeneka4c74292008-04-10 22:58:08 +000073 return Data >> 2;
Ted Kremeneka7338b42008-03-11 06:39:11 +000074 }
Ted Kremenekffefc352008-04-11 22:25:11 +000075
Ted Kremeneka7338b42008-03-11 06:39:11 +000076 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000077
Ted Kremeneka7338b42008-03-11 06:39:11 +000078 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000079
Ted Kremeneka7338b42008-03-11 06:39:11 +000080 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
81
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000082 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
83
Ted Kremeneka7338b42008-03-11 06:39:11 +000084 operator Kind() const { return getKind(); }
85
86 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
87};
88
89
90class CFRefSummary : public llvm::FoldingSetNode {
91 ArgEffects* Args;
92 RetEffect Ret;
93public:
94
95 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
96
97 unsigned getNumArgs() const { return Args->size(); }
98
Ted Kremenek0d721572008-03-11 17:48:22 +000099 ArgEffect getArg(unsigned idx) const {
100 assert (idx < getNumArgs());
101 return (*Args)[idx];
102 }
103
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000104 RetEffect getRet() const {
105 return Ret;
106 }
107
Ted Kremeneka7338b42008-03-11 06:39:11 +0000108 typedef ArgEffects::const_iterator arg_iterator;
109
110 arg_iterator begin_args() const { return Args->begin(); }
111 arg_iterator end_args() const { return Args->end(); }
112
113 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
114 ID.AddPointer(A);
115 ID.Add(R);
116 }
117
118 void Profile(llvm::FoldingSetNodeID& ID) const {
119 Profile(ID, Args, Ret);
120 }
121};
122
123
124class CFRefSummaryManager {
125 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
126 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
127 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
128
Ted Kremeneka4c74292008-04-10 22:58:08 +0000129 ASTContext& Ctx;
130 SummarySetTy SummarySet;
131 SummaryMapTy SummaryMap;
132 AESetTy AESet;
133 llvm::BumpPtrAllocator BPAlloc;
134 ArgEffects ScratchArgs;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000135
136
137 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000138
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000139 CFRefSummary* getCannedCFSummary(FunctionTypeProto* FT, bool isRetain);
140
141 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
142
143 CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
144 CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);
145
146 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
147
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000148 void FillDoNothing(unsigned Args);
149
150
Ted Kremeneka7338b42008-03-11 06:39:11 +0000151public:
Ted Kremeneka4c74292008-04-10 22:58:08 +0000152 CFRefSummaryManager(ASTContext& ctx) : Ctx(ctx) {}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000153 ~CFRefSummaryManager();
154
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000155 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000156};
157
158} // end anonymous namespace
159
160//===----------------------------------------------------------------------===//
161// Implementation of checker data structures.
162//===----------------------------------------------------------------------===//
163
164CFRefSummaryManager::~CFRefSummaryManager() {
165
166 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
167 // mitigating the need to do explicit cleanup of the
168 // Argument-Effect summaries.
169
170 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
171 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000172}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000173
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000174ArgEffects* CFRefSummaryManager::getArgEffects() {
175
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000176 llvm::FoldingSetNodeID profile;
177 profile.Add(ScratchArgs);
178 void* InsertPos;
179
180 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
181 AESet.FindNodeOrInsertPos(profile, InsertPos);
182
183 if (E) {
184 ScratchArgs.clear();
185 return &E->getValue();
186 }
187
188 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
189 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
190
191 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
192 AESet.InsertNode(E, InsertPos);
193
194 ScratchArgs.clear();
195 return &E->getValue();
196}
197
198CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
199 RetEffect RE) {
200
201 llvm::FoldingSetNodeID profile;
202 CFRefSummary::Profile(profile, AE, RE);
203 void* InsertPos;
204
205 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
206
207 if (Summ)
208 return Summ;
209
210 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
211 new (Summ) CFRefSummary(AE, RE);
212 SummarySet.InsertNode(Summ, InsertPos);
213
214 return Summ;
215}
216
217
218CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
219 ASTContext& Ctx) {
220
221 SourceLocation Loc = FD->getLocation();
222
223 if (!Loc.isFileID())
224 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000225
Ted Kremeneka7338b42008-03-11 06:39:11 +0000226 { // Look into our cache of summaries to see if we have already computed
227 // a summary for this FunctionDecl.
228
229 SummaryMapTy::iterator I = SummaryMap.find(FD);
230
231 if (I != SummaryMap.end())
232 return I->second;
233 }
234
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000235#if 0
236 SourceManager& SrcMgr = Ctx.getSourceManager();
237 unsigned fid = Loc.getFileID();
238 const FileEntry* FE = SrcMgr.getFileEntryForID(fid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000239
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000240 if (!FE)
241 return NULL;
242
243 const char* DirName = FE->getDir()->getName();
244 assert (DirName);
245 assert (strlen(DirName) > 0);
246
247 if (!strstr(DirName, "CoreFoundation")) {
248 SummaryMap[FD] = NULL;
249 return NULL;
250 }
251#endif
252
253 const char* FName = FD->getIdentifier()->getName();
254
255 if (FName[0] == 'C' && FName[1] == 'F') {
256 CFRefSummary* S = getCFSummary(FD, FName);
257 SummaryMap[FD] = S;
258 return S;
259 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000260
261 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000262}
263
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000264CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
265 const char* FName) {
266
267 // For now, only generate summaries for functions that have a prototype.
268
269 FunctionTypeProto* FT =
270 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
271
272 if (!FT)
273 return NULL;
274
275 FName += 2;
276
277 if (strcmp(FName, "Retain") == 0)
278 return getCannedCFSummary(FT, true);
279
280 if (strcmp(FName, "Release") == 0)
281 return getCannedCFSummary(FT, false);
282
283 assert (ScratchArgs.empty());
284 bool usesCreateRule = false;
285
286 if (strstr(FName, "Create"))
287 usesCreateRule = true;
288
289 if (!usesCreateRule && strstr(FName, "Copy"))
290 usesCreateRule = true;
291
292 if (usesCreateRule)
293 return getCFSummaryCreateRule(FT);
294
295 if (strstr(FName, "Get"))
296 return getCFSummaryGetRule(FT);
297
298 return NULL;
299}
300
301CFRefSummary* CFRefSummaryManager::getCannedCFSummary(FunctionTypeProto* FT,
302 bool isRetain) {
303
304 if (FT->getNumArgs() != 1)
305 return NULL;
306
307 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
308
309 if (!ArgT)
310 return NULL;
311
312 // For CFRetain/CFRelease, the first (and only) argument is of type
313 // "CFTypeRef".
314
315 const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
316 assert (TDName);
317
Ted Kremeneka4c74292008-04-10 22:58:08 +0000318 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000319 return NULL;
320
321 if (!ArgT->isPointerType())
322 return NULL;
Ted Kremeneka4c74292008-04-10 22:58:08 +0000323
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000324 QualType RetTy = FT->getResultType();
325
Ted Kremeneka4c74292008-04-10 22:58:08 +0000326 if (isRetain) {
327 // CFRetain: the return type should also be "CFTypeRef".
328 if (RetTy.getTypePtr() != ArgT)
329 return NULL;
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000330
331 // The function's interface checks out. Generate a canned summary.
332 assert (ScratchArgs.empty());
333 ScratchArgs.push_back(IncRef);
334 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremeneka4c74292008-04-10 22:58:08 +0000335 }
336 else {
337 // CFRelease: the return type should be void.
338
339 if (RetTy != Ctx.VoidTy)
340 return NULL;
Ted Kremeneka4c74292008-04-10 22:58:08 +0000341
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000342 assert (ScratchArgs.empty());
343 ScratchArgs.push_back(DecRef);
344 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
345 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000346}
347
348static bool isCFRefType(QualType T) {
349
350 if (!T->isPointerType())
351 return false;
352
353 // Check the typedef for the name "CF" and the substring "Ref".
354
355 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
356
357 if (!TD)
358 return false;
359
360 const char* TDName = TD->getDecl()->getIdentifier()->getName();
361 assert (TDName);
362
363 if (TDName[0] != 'C' || TDName[1] != 'F')
364 return false;
365
366 if (strstr(TDName, "Ref") == 0)
367 return false;
368
369 return true;
370}
371
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000372void CFRefSummaryManager::FillDoNothing(unsigned Args) {
373 for (unsigned i = 0; i != Args; ++i)
374 ScratchArgs.push_back(DoNothing);
375}
376
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000377
378CFRefSummary*
379CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
380
381 if (!isCFRefType(FT->getResultType()))
Ted Kremenekd4244d42008-04-11 20:11:19 +0000382 return NULL;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000383
384 assert (ScratchArgs.empty());
385
386 // FIXME: Add special-cases for functions that retain/release. For now
387 // just handle the default case.
388
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000389 FillDoNothing(FT->getNumArgs());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000390 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
391}
392
393CFRefSummary*
394CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
395
Ted Kremenekd4244d42008-04-11 20:11:19 +0000396 QualType RetTy = FT->getResultType();
397
398 // FIXME: For now we assume that all pointer types returned are referenced
399 // counted. Since this is the "Get" rule, we assume non-ownership, which
400 // works fine for things that are not reference counted. We do this because
401 // some generic data structures return "void*". We need something better
402 // in the future.
403
404 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
405 return NULL;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000406
407 assert (ScratchArgs.empty());
408
409 // FIXME: Add special-cases for functions that retain/release. For now
410 // just handle the default case.
411
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000412 FillDoNothing(FT->getNumArgs());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000413 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
414}
415
Ted Kremeneka7338b42008-03-11 06:39:11 +0000416//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +0000417// Bug Descriptions.
418//===----------------------------------------------------------------------===//
419
420namespace {
421
422 class CFRefCount;
423
424 class VISIBILITY_HIDDEN CFRefBug : public BugType {
425 protected:
426 CFRefCount& TF;
427
428 public:
429 CFRefBug(CFRefCount& tf) : TF(tf) {}
430 };
431
432 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
433 public:
434 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
435
436 virtual const char* getName() const {
437 return "(CoreFoundation) use-after-release";
438 }
439 virtual const char* getDescription() const {
440 return "(CoreFoundation) Reference-counted object is used"
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000441 " after it is released.";
Ted Kremenek7d421f32008-04-09 23:49:11 +0000442 }
443
444 virtual void EmitWarnings(BugReporter& BR);
445
446 };
447
448 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
449 public:
450 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
451
452 virtual const char* getName() const {
453 return "(CoreFoundation) release of non-owned object";
454 }
455 virtual const char* getDescription() const {
456 return "Incorrect decrement of the reference count of a "
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000457 "CoreFoundation object:\n"
458 "The object is not owned at this point by the caller.";
Ted Kremenek7d421f32008-04-09 23:49:11 +0000459 }
460
461 virtual void EmitWarnings(BugReporter& BR);
462 };
463
464} // end anonymous namespace
465
466//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000467// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000468//===----------------------------------------------------------------------===//
469
Ted Kremeneka7338b42008-03-11 06:39:11 +0000470namespace {
471
Ted Kremenek7d421f32008-04-09 23:49:11 +0000472class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000473public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000474
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000475 enum Kind {
476 Owned = 0, // Owning reference.
477 NotOwned, // Reference is not owned by still valid (not freed).
478 Released, // Object has been released.
479 ReturnedOwned, // Returned object passes ownership to caller.
480 ReturnedNotOwned, // Return object does not pass ownership to caller.
481 ErrorUseAfterRelease, // Object used after released.
482 ErrorReleaseNotOwned, // Release of an object that was not owned.
483 ErrorLeak // A memory leak due to excessive reference counts.
484 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000485
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000486private:
487
488 Kind kind;
489 unsigned Cnt;
490
491 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
492
493 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000494
495public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000496
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000497 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000498
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000499 unsigned getCount() const { return Cnt; }
500
501 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000502
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000503 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
504
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000505 static bool isLeak(Kind k) { return k == ErrorLeak; }
506
Ted Kremenekffefc352008-04-11 22:25:11 +0000507 bool isOwned() const {
508 return getKind() == Owned;
509 }
510
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000511 bool isNotOwned() const {
512 return getKind() == NotOwned;
513 }
514
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000515 bool isReturnedOwned() const {
516 return getKind() == ReturnedOwned;
517 }
518
519 bool isReturnedNotOwned() const {
520 return getKind() == ReturnedNotOwned;
521 }
522
523 bool isNonLeakError() const {
524 Kind k = getKind();
525 return isError(k) && !isLeak(k);
526 }
527
528 // State creation: normal state.
529
Ted Kremenekc4f81022008-04-10 23:09:18 +0000530 static RefVal makeOwned(unsigned Count = 0) {
531 return RefVal(Owned, Count);
532 }
533
534 static RefVal makeNotOwned(unsigned Count = 0) {
535 return RefVal(NotOwned, Count);
536 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000537
538 static RefVal makeReturnedOwned(unsigned Count) {
539 return RefVal(ReturnedOwned, Count);
540 }
541
542 static RefVal makeReturnedNotOwned() {
543 return RefVal(ReturnedNotOwned);
544 }
545
546 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000547
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000548 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000549 static RefVal makeReleased() { return RefVal(Released); }
550 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
551 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000552
553 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000554
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000555 bool operator==(const RefVal& X) const {
556 return kind == X.kind && Cnt == X.Cnt;
557 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000558
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000559 void Profile(llvm::FoldingSetNodeID& ID) const {
560 ID.AddInteger((unsigned) kind);
561 ID.AddInteger(Cnt);
562 }
563
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000564 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000565};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000566
567void RefVal::print(std::ostream& Out) const {
568 switch (getKind()) {
569 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000570 case Owned: {
571 Out << "Owned";
572 unsigned cnt = getCount();
573 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000574 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000575 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000576
Ted Kremenekc4f81022008-04-10 23:09:18 +0000577 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000578 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000579 unsigned cnt = getCount();
580 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000581 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000582 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000583
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000584 case ReturnedOwned: {
585 Out << "ReturnedOwned";
586 unsigned cnt = getCount();
587 if (cnt) Out << " (+ " << cnt << ")";
588 break;
589 }
590
591 case ReturnedNotOwned: {
592 Out << "ReturnedNotOwned";
593 unsigned cnt = getCount();
594 if (cnt) Out << " (+ " << cnt << ")";
595 break;
596 }
597
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000598 case Released:
599 Out << "Released";
600 break;
601
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000602 case ErrorLeak:
603 Out << "Leaked";
604 break;
605
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000606 case ErrorUseAfterRelease:
607 Out << "Use-After-Release [ERROR]";
608 break;
609
610 case ErrorReleaseNotOwned:
611 Out << "Release of Not-Owned [ERROR]";
612 break;
613 }
614}
Ted Kremenek0d721572008-03-11 17:48:22 +0000615
Ted Kremenek7aef4842008-04-16 20:40:59 +0000616//===----------------------------------------------------------------------===//
617// Transfer functions.
618//===----------------------------------------------------------------------===//
619
Ted Kremenek7d421f32008-04-09 23:49:11 +0000620class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000621
622 // Type definitions.
623
Ted Kremenek0d721572008-03-11 17:48:22 +0000624 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000625 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000626
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000627 typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> UseAfterReleasesTy;
628 typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> ReleasesNotOwnedTy;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000629
630 typedef llvm::SmallVector<std::pair<SymbolID, ExplodedNode<ValueState>*>, 2>
631 LeaksTy;
632
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000633
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000634 class BindingsPrinter : public ValueState::CheckerStatePrinter {
635 public:
636 virtual void PrintCheckerState(std::ostream& Out, void* State,
637 const char* nl, const char* sep);
638 };
639
640 // Instance variables.
641
Ted Kremeneka7338b42008-03-11 06:39:11 +0000642 CFRefSummaryManager Summaries;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000643 RefBFactoryTy RefBFactory;
644
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000645 UseAfterReleasesTy UseAfterReleases;
646 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000647 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000648
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000649 BindingsPrinter Printer;
650
Ted Kremenek1feab292008-04-16 04:28:53 +0000651 Selector RetainSelector;
652 Selector ReleaseSelector;
653
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000654 // Private methods.
Ted Kremenek1feab292008-04-16 04:28:53 +0000655
Ted Kremeneka7338b42008-03-11 06:39:11 +0000656 static RefBindings GetRefBindings(ValueState& StImpl) {
657 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
658 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000659
Ted Kremeneka7338b42008-03-11 06:39:11 +0000660 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
661 StImpl.CheckerState = B.getRoot();
662 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000663
Ted Kremeneka7338b42008-03-11 06:39:11 +0000664 RefBindings Remove(RefBindings B, SymbolID sym) {
665 return RefBFactory.Remove(B, sym);
666 }
667
Ted Kremenek0d721572008-03-11 17:48:22 +0000668 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000669 RefVal::Kind& hasErr);
670
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000671 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
672 GRStmtNodeBuilder<ValueState>& Builder,
673 Expr* NodeExpr, Expr* ErrorExpr,
674 ExplodedNode<ValueState>* Pred,
675 ValueState* St,
676 RefVal::Kind hasErr);
677
678 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
679 SymbolID sid, RefVal V, bool& hasLeak);
680
681 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
682 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000683
684public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000685
Ted Kremenek1feab292008-04-16 04:28:53 +0000686 CFRefCount(ASTContext& Ctx)
687 : Summaries(Ctx),
688 RetainSelector(GetUnarySelector("retain", Ctx)),
689 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
690
Ted Kremeneka7338b42008-03-11 06:39:11 +0000691 virtual ~CFRefCount() {}
Ted Kremenek7d421f32008-04-09 23:49:11 +0000692
693 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000694
695 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
696 return &Printer;
697 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000698
699 // Calls.
700
701 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000702 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000703 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000704 CallExpr* CE, LVal L,
705 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000706
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000707 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
708 GRExprEngine& Engine,
709 GRStmtNodeBuilder<ValueState>& Builder,
710 ObjCMessageExpr* ME,
711 ExplodedNode<ValueState>* Pred);
712
713 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
714 GRExprEngine& Engine,
715 GRStmtNodeBuilder<ValueState>& Builder,
716 ObjCMessageExpr* ME,
717 ExplodedNode<ValueState>* Pred);
718
Ted Kremenek7aef4842008-04-16 20:40:59 +0000719 // Stores.
720
721 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
722 GRExprEngine& Engine,
723 GRStmtNodeBuilder<ValueState>& Builder,
724 Expr* E, ExplodedNode<ValueState>* Pred,
725 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000726 // End-of-path.
727
728 virtual void EvalEndPath(GRExprEngine& Engine,
729 GREndPathNodeBuilder<ValueState>& Builder);
730
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000731 // Return statements.
732
733 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
734 GRExprEngine& Engine,
735 GRStmtNodeBuilder<ValueState>& Builder,
736 ReturnStmt* S,
737 ExplodedNode<ValueState>* Pred);
738
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000739 // Error iterators.
740
741 typedef UseAfterReleasesTy::iterator use_after_iterator;
742 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
743
Ted Kremenek7d421f32008-04-09 23:49:11 +0000744 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
745 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000746
Ted Kremenek7d421f32008-04-09 23:49:11 +0000747 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
748 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000749};
750
751} // end anonymous namespace
752
Ted Kremenek7d421f32008-04-09 23:49:11 +0000753void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
754 GRSimpleVals::RegisterChecks(Eng);
755 Eng.Register(new UseAfterRelease(*this));
756 Eng.Register(new BadRelease(*this));
757}
758
759
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000760void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
761 void* State, const char* nl,
762 const char* sep) {
763 RefBindings B((RefBindings::TreeTy*) State);
764
765 if (State)
766 Out << sep << nl;
767
768 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
769 Out << (*I).first << " : ";
770 (*I).second.print(Out);
771 Out << nl;
772 }
773}
774
Ted Kremenek455dd862008-04-11 20:23:24 +0000775static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
776 return Summ ? Summ->getArg(idx) : DoNothing;
777}
778
779static inline RetEffect GetRetE(CFRefSummary* Summ) {
780 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
781}
782
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000783void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
784 GRStmtNodeBuilder<ValueState>& Builder,
785 Expr* NodeExpr, Expr* ErrorExpr,
786 ExplodedNode<ValueState>* Pred,
787 ValueState* St,
788 RefVal::Kind hasErr) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000789 Builder.BuildSinks = true;
790 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
791
792 if (!N) return;
793
794 switch (hasErr) {
795 default: assert(false);
796 case RefVal::ErrorUseAfterRelease:
797 UseAfterReleases[N] = ErrorExpr;
798 break;
799
800 case RefVal::ErrorReleaseNotOwned:
801 ReleasesNotOwned[N] = ErrorExpr;
802 break;
803 }
804}
805
Ted Kremenek827f93b2008-03-06 00:08:09 +0000806void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000807 GRExprEngine& Eng,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000808 GRStmtNodeBuilder<ValueState>& Builder,
809 CallExpr* CE, LVal L,
810 ExplodedNode<ValueState>* Pred) {
811
Ted Kremenekce0767f2008-03-12 21:06:49 +0000812 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000813
Ted Kremenek73ba0472008-04-14 17:45:13 +0000814 CFRefSummary* Summ = NULL;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000815
816 // Get the summary.
Ted Kremenek827f93b2008-03-06 00:08:09 +0000817
Ted Kremenek73ba0472008-04-14 17:45:13 +0000818 if (isa<lval::FuncVal>(L)) {
819 lval::FuncVal FV = cast<lval::FuncVal>(L);
820 FunctionDecl* FD = FV.getDecl();
821 Summ = Summaries.getSummary(FD, Eng.getContext());
822 }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000823
Ted Kremeneka7338b42008-03-11 06:39:11 +0000824 // Get the state.
825
826 ValueState* St = Builder.GetState(Pred);
827
828 // Evaluate the effects of the call.
829
830 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000831 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek455dd862008-04-11 20:23:24 +0000832
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000833 // This function has a summary. Evaluate the effect of the arguments.
834
835 unsigned idx = 0;
836
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000837 Expr* ErrorExpr = NULL;
838
839 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
840 I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000841
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000842 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000843
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000844 if (isa<lval::SymbolVal>(V)) {
845 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000846 RefBindings B = GetRefBindings(StVals);
847
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000848 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000849 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000850 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000851
Ted Kremenek1feab292008-04-16 04:28:53 +0000852 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000853 ErrorExpr = *I;
854 break;
855 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000856 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000857 }
858 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
859
860 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
861 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000862 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000863 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000864 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000865
866 St = StateMgr.getPersistentState(StVals);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000867
Ted Kremenek1feab292008-04-16 04:28:53 +0000868 if (hasErr) {
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000869 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St, hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000870 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000871 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000872
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000873 // Finally, consult the summary for the return value.
874
Ted Kremenek455dd862008-04-11 20:23:24 +0000875 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000876
877 switch (RE.getKind()) {
878 default:
879 assert (false && "Unhandled RetEffect."); break;
880
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000881 case RetEffect::NoRet:
Ted Kremenek455dd862008-04-11 20:23:24 +0000882
883 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000884 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
885 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000886
887 if (CE->getType() != Eng.getContext().VoidTy) {
888 unsigned Count = Builder.getCurrentBlockCount();
889 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
890
891 RVal X = CE->getType()->isPointerType()
892 ? cast<RVal>(lval::SymbolVal(Sym))
893 : cast<RVal>(nonlval::SymbolVal(Sym));
894
895 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
896 }
897
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000898 break;
899
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000900 case RetEffect::Alias: {
901 unsigned idx = RE.getValue();
902 assert (idx < CE->getNumArgs());
903 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenekce0767f2008-03-12 21:06:49 +0000904 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000905 break;
906 }
907
908 case RetEffect::OwnedSymbol: {
909 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000910 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000911
912 ValueState StImpl = *St;
913 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000914 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000915
916 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
917 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000918 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000919
920 break;
921 }
922
923 case RetEffect::NotOwnedSymbol: {
924 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000925 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000926
927 ValueState StImpl = *St;
928 RefBindings B = GetRefBindings(StImpl);
929 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
930
931 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
932 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000933 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000934
935 break;
936 }
937 }
938
Ted Kremenekf10f2882008-03-21 21:30:14 +0000939 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek827f93b2008-03-06 00:08:09 +0000940}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000941
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000942
943void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
944 GRExprEngine& Eng,
945 GRStmtNodeBuilder<ValueState>& Builder,
946 ObjCMessageExpr* ME,
947 ExplodedNode<ValueState>* Pred) {
948
949 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
950 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
951}
952
953bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
954 GRExprEngine& Eng,
955 GRStmtNodeBuilder<ValueState>& Builder,
956 ObjCMessageExpr* ME,
957 ExplodedNode<ValueState>* Pred) {
958
Ted Kremenek1feab292008-04-16 04:28:53 +0000959 // Handle "toll-free bridging" of calls to "Release" and "Retain".
960
961 // FIXME: track the underlying object type associated so that we can
962 // flag illegal uses of toll-free bridging (or at least handle it
963 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000964
965 Selector S = ME->getSelector();
966
967 if (!S.isUnarySelector())
968 return true;
969
Ted Kremenek1feab292008-04-16 04:28:53 +0000970 Expr* Receiver = ME->getReceiver();
971
972 if (!Receiver)
973 return true;
974
975 // Check if we are calling "Retain" or "Release".
976
977 bool isRetain = false;
978
979 if (S == RetainSelector)
980 isRetain = true;
981 else if (S != ReleaseSelector)
982 return true;
983
984 // We have "Retain" or "Release". Get the reference binding.
985
986 ValueStateManager& StateMgr = Eng.getStateManager();
987 ValueState* St = Builder.GetState(Pred);
988 RVal V = StateMgr.GetRVal(St, Receiver);
989
990 if (!isa<lval::SymbolVal>(V))
991 return true;
992
993 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
994 RefBindings B = GetRefBindings(*St);
995
996 RefBindings::TreeTy* T = B.SlimFind(Sym);
997
998 if (!T)
999 return true;
1000
1001 RefVal::Kind hasErr = (RefVal::Kind) 0;
1002 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
1003
1004 // Create a new state with the updated bindings.
1005
1006 ValueState StVals = *St;
1007 SetRefBindings(StVals, B);
1008 St = StateMgr.getPersistentState(StVals);
1009
1010 // Create an error node if it exists.
1011
1012 if (hasErr)
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001013 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr);
Ted Kremenek1feab292008-04-16 04:28:53 +00001014 else
1015 Builder.MakeNode(Dst, ME, Pred, St);
1016
1017 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001018}
1019
Ted Kremenek7aef4842008-04-16 20:40:59 +00001020// Stores.
1021
1022void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1023 GRExprEngine& Eng,
1024 GRStmtNodeBuilder<ValueState>& Builder,
1025 Expr* E, ExplodedNode<ValueState>* Pred,
1026 ValueState* St, RVal TargetLV, RVal Val) {
1027
1028 // Check if we have a binding for "Val" and if we are storing it to something
1029 // we don't understand or otherwise the value "escapes" the function.
1030
1031 if (!isa<lval::SymbolVal>(Val))
1032 return;
1033
1034 // Are we storing to something that causes the value to "escape"?
1035
1036 bool escapes = false;
1037
1038 if (!isa<lval::DeclVal>(TargetLV))
1039 escapes = true;
1040 else
1041 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1042
1043 if (!escapes)
1044 return;
1045
1046 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1047 RefBindings B = GetRefBindings(*St);
1048 RefBindings::TreeTy* T = B.SlimFind(Sym);
1049
1050 if (!T)
1051 return;
1052
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001053 // Nuke the binding.
1054 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001055
1056 // Hand of the remaining logic to the parent implementation.
1057 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1058}
1059
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001060
1061ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1062 SymbolID sid) {
1063 ValueState StImpl = *St;
1064 RefBindings B = GetRefBindings(StImpl);
1065 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1066 return VMgr.getPersistentState(StImpl);
1067}
1068
Ted Kremenekffefc352008-04-11 22:25:11 +00001069// End-of-path.
1070
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001071
1072
1073ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1074 ValueState* St, SymbolID sid,
1075 RefVal V, bool& hasLeak) {
1076
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001077 hasLeak = V.isOwned() ||
1078 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001079
1080 if (!hasLeak)
1081 return NukeBinding(VMgr, St, sid);
1082
1083 RefBindings B = GetRefBindings(*St);
1084 ValueState StImpl = *St;
1085 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1086 return VMgr.getPersistentState(StImpl);
1087}
1088
1089void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001090 GREndPathNodeBuilder<ValueState>& Builder) {
1091
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001092 ValueState* St = Builder.getState();
1093 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001094
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001095 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001096
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001097 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1098 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001099
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001100 St = HandleSymbolDeath(Eng.getStateManager(), St,
1101 (*I).first, (*I).second, hasLeak);
1102
1103 if (hasLeak) Leaked.push_back((*I).first);
1104 }
1105
1106 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
1107
1108 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1109 E = Leaked.end(); I != E; ++I)
1110 Leaks.push_back(std::make_pair(*I, N));
Ted Kremenekffefc352008-04-11 22:25:11 +00001111}
1112
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001113 // Return statements.
1114
1115void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1116 GRExprEngine& Eng,
1117 GRStmtNodeBuilder<ValueState>& Builder,
1118 ReturnStmt* S,
1119 ExplodedNode<ValueState>* Pred) {
1120
1121 Expr* RetE = S->getRetValue();
1122 if (!RetE) return;
1123
1124 ValueStateManager& StateMgr = Eng.getStateManager();
1125 ValueState* St = Builder.GetState(Pred);
1126 RVal V = StateMgr.GetRVal(St, RetE);
1127
1128 if (!isa<lval::SymbolVal>(V))
1129 return;
1130
1131 // Get the reference count binding (if any).
1132 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1133 RefBindings B = GetRefBindings(*St);
1134 RefBindings::TreeTy* T = B.SlimFind(Sym);
1135
1136 if (!T)
1137 return;
1138
1139 // Change the reference count.
1140
1141 RefVal X = T->getValue().second;
1142
1143 switch (X.getKind()) {
1144
1145 case RefVal::Owned: {
1146 unsigned cnt = X.getCount();
1147 X = RefVal::makeReturnedOwned(cnt);
1148 break;
1149 }
1150
1151 case RefVal::NotOwned: {
1152 unsigned cnt = X.getCount();
1153 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1154 : RefVal::makeReturnedNotOwned();
1155 break;
1156 }
1157
1158 default:
1159 // None of the error states should be possible at this point.
1160 // A symbol could not have been leaked (yet) if we are returning it
1161 // (and thus it is still live), and the other errors are hard errors.
1162 assert(false);
1163 return;
1164 }
1165
1166 // Update the binding.
1167
1168 ValueState StImpl = *St;
1169 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1170 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1171}
1172
Ted Kremeneka7338b42008-03-11 06:39:11 +00001173
1174CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001175 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001176 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001177
Ted Kremenek0d721572008-03-11 17:48:22 +00001178 // FIXME: This dispatch can potentially be sped up by unifiying it into
1179 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001180
Ted Kremenek0d721572008-03-11 17:48:22 +00001181 switch (E) {
1182 default:
1183 assert (false && "Unhandled CFRef transition.");
1184
1185 case DoNothing:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001186 if (V.getKind() == RefVal::Released) {
1187 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001188 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001189 break;
1190 }
1191
Ted Kremenek0d721572008-03-11 17:48:22 +00001192 return B;
1193
1194 case IncRef:
1195 switch (V.getKind()) {
1196 default:
1197 assert(false);
1198
1199 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001200 V = RefVal::makeOwned(V.getCount()+1);
1201 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001202
Ted Kremenek0d721572008-03-11 17:48:22 +00001203 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001204 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001205 break;
1206
1207 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001208 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001209 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001210 break;
1211 }
1212
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001213 break;
1214
Ted Kremenek0d721572008-03-11 17:48:22 +00001215 case DecRef:
1216 switch (V.getKind()) {
1217 default:
1218 assert (false);
1219
1220 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001221 unsigned Count = V.getCount();
1222 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001223 break;
1224 }
1225
Ted Kremenekc4f81022008-04-10 23:09:18 +00001226 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001227 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001228
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001229 if (Count > 0)
1230 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001231 else {
1232 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001233 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001234 }
1235
Ted Kremenek0d721572008-03-11 17:48:22 +00001236 break;
1237 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001238
1239 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001240 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001241 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001242 break;
1243 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001244
1245 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001246 }
1247
1248 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001249}
1250
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001251
1252//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001253// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001254//===----------------------------------------------------------------------===//
1255
Ted Kremenek7d421f32008-04-09 23:49:11 +00001256void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001257
Ted Kremenek7d421f32008-04-09 23:49:11 +00001258 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1259 E = TF.use_after_end(); I != E; ++I) {
1260
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001261 RangedBugReport report(*this, I->first);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001262 report.addRange(I->second->getSourceRange());
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001263 BR.EmitPathWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001264 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001265}
1266
1267void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001268
Ted Kremenek7d421f32008-04-09 23:49:11 +00001269 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1270 E = TF.bad_release_end(); I != E; ++I) {
1271
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001272 RangedBugReport report(*this, I->first);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001273 report.addRange(I->second->getSourceRange());
Ted Kremeneke3ef1c72008-04-14 17:39:48 +00001274 BR.EmitPathWarning(report);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +00001275
Ted Kremenek7d421f32008-04-09 23:49:11 +00001276 }
1277}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001278
Ted Kremeneka7338b42008-03-11 06:39:11 +00001279//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001280// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001281//===----------------------------------------------------------------------===//
1282
Ted Kremeneka4c74292008-04-10 22:58:08 +00001283GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx) {
1284 return new CFRefCount(Ctx);
1285}