blob: 0c5860ecda95d78b4597b67f70bfdb2d19e6c05c [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 Kremenek7aef4842008-04-16 20:40:59 +0000417// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000418//===----------------------------------------------------------------------===//
419
Ted Kremeneka7338b42008-03-11 06:39:11 +0000420namespace {
421
Ted Kremenek7d421f32008-04-09 23:49:11 +0000422class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000423public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000424
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000425 enum Kind {
426 Owned = 0, // Owning reference.
427 NotOwned, // Reference is not owned by still valid (not freed).
428 Released, // Object has been released.
429 ReturnedOwned, // Returned object passes ownership to caller.
430 ReturnedNotOwned, // Return object does not pass ownership to caller.
431 ErrorUseAfterRelease, // Object used after released.
432 ErrorReleaseNotOwned, // Release of an object that was not owned.
433 ErrorLeak // A memory leak due to excessive reference counts.
434 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000435
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000436private:
437
438 Kind kind;
439 unsigned Cnt;
440
441 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
442
443 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000444
445public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000446
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000447 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000448
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000449 unsigned getCount() const { return Cnt; }
450
451 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000452
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000453 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
454
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000455 static bool isLeak(Kind k) { return k == ErrorLeak; }
456
Ted Kremenekffefc352008-04-11 22:25:11 +0000457 bool isOwned() const {
458 return getKind() == Owned;
459 }
460
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000461 bool isNotOwned() const {
462 return getKind() == NotOwned;
463 }
464
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000465 bool isReturnedOwned() const {
466 return getKind() == ReturnedOwned;
467 }
468
469 bool isReturnedNotOwned() const {
470 return getKind() == ReturnedNotOwned;
471 }
472
473 bool isNonLeakError() const {
474 Kind k = getKind();
475 return isError(k) && !isLeak(k);
476 }
477
478 // State creation: normal state.
479
Ted Kremenekc4f81022008-04-10 23:09:18 +0000480 static RefVal makeOwned(unsigned Count = 0) {
481 return RefVal(Owned, Count);
482 }
483
484 static RefVal makeNotOwned(unsigned Count = 0) {
485 return RefVal(NotOwned, Count);
486 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000487
488 static RefVal makeReturnedOwned(unsigned Count) {
489 return RefVal(ReturnedOwned, Count);
490 }
491
492 static RefVal makeReturnedNotOwned() {
493 return RefVal(ReturnedNotOwned);
494 }
495
496 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000497
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000498 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000499 static RefVal makeReleased() { return RefVal(Released); }
500 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
501 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000502
503 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000504
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000505 bool operator==(const RefVal& X) const {
506 return kind == X.kind && Cnt == X.Cnt;
507 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000508
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000509 void Profile(llvm::FoldingSetNodeID& ID) const {
510 ID.AddInteger((unsigned) kind);
511 ID.AddInteger(Cnt);
512 }
513
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000514 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000515};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000516
517void RefVal::print(std::ostream& Out) const {
518 switch (getKind()) {
519 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000520 case Owned: {
521 Out << "Owned";
522 unsigned cnt = getCount();
523 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000524 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000525 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000526
Ted Kremenekc4f81022008-04-10 23:09:18 +0000527 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000528 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000529 unsigned cnt = getCount();
530 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000531 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000532 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000533
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000534 case ReturnedOwned: {
535 Out << "ReturnedOwned";
536 unsigned cnt = getCount();
537 if (cnt) Out << " (+ " << cnt << ")";
538 break;
539 }
540
541 case ReturnedNotOwned: {
542 Out << "ReturnedNotOwned";
543 unsigned cnt = getCount();
544 if (cnt) Out << " (+ " << cnt << ")";
545 break;
546 }
547
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000548 case Released:
549 Out << "Released";
550 break;
551
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000552 case ErrorLeak:
553 Out << "Leaked";
554 break;
555
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000556 case ErrorUseAfterRelease:
557 Out << "Use-After-Release [ERROR]";
558 break;
559
560 case ErrorReleaseNotOwned:
561 Out << "Release of Not-Owned [ERROR]";
562 break;
563 }
564}
Ted Kremenek0d721572008-03-11 17:48:22 +0000565
Ted Kremenek7aef4842008-04-16 20:40:59 +0000566//===----------------------------------------------------------------------===//
567// Transfer functions.
568//===----------------------------------------------------------------------===//
569
Ted Kremenek7d421f32008-04-09 23:49:11 +0000570class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000571public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000572 // Type definitions.
573
Ted Kremenek0d721572008-03-11 17:48:22 +0000574 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000575 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000576
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000577 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
578 ReleasesNotOwnedTy;
579
580 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
581
582 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000583 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000584
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000585 class BindingsPrinter : public ValueState::CheckerStatePrinter {
586 public:
587 virtual void PrintCheckerState(std::ostream& Out, void* State,
588 const char* nl, const char* sep);
589 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000590
591private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000592 // Instance variables.
593
Ted Kremeneka7338b42008-03-11 06:39:11 +0000594 CFRefSummaryManager Summaries;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000595 RefBFactoryTy RefBFactory;
596
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000597 UseAfterReleasesTy UseAfterReleases;
598 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000599 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000600
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000601 BindingsPrinter Printer;
602
Ted Kremenek1feab292008-04-16 04:28:53 +0000603 Selector RetainSelector;
604 Selector ReleaseSelector;
605
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000606public:
607
Ted Kremeneka7338b42008-03-11 06:39:11 +0000608 static RefBindings GetRefBindings(ValueState& StImpl) {
609 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
610 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000611
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000612private:
613
Ted Kremeneka7338b42008-03-11 06:39:11 +0000614 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
615 StImpl.CheckerState = B.getRoot();
616 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000617
Ted Kremeneka7338b42008-03-11 06:39:11 +0000618 RefBindings Remove(RefBindings B, SymbolID sym) {
619 return RefBFactory.Remove(B, sym);
620 }
621
Ted Kremenek0d721572008-03-11 17:48:22 +0000622 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000623 RefVal::Kind& hasErr);
624
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000625 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
626 GRStmtNodeBuilder<ValueState>& Builder,
627 Expr* NodeExpr, Expr* ErrorExpr,
628 ExplodedNode<ValueState>* Pred,
629 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000630 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000631
632 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
633 SymbolID sid, RefVal V, bool& hasLeak);
634
635 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
636 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000637
638public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000639
Ted Kremenek1feab292008-04-16 04:28:53 +0000640 CFRefCount(ASTContext& Ctx)
641 : Summaries(Ctx),
642 RetainSelector(GetUnarySelector("retain", Ctx)),
643 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
644
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000645 virtual ~CFRefCount() {
646 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
647 delete I->second;
648 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000649
650 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000651
652 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
653 return &Printer;
654 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000655
656 // Calls.
657
658 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000659 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000660 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000661 CallExpr* CE, LVal L,
662 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000663
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000664 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
665 GRExprEngine& Engine,
666 GRStmtNodeBuilder<ValueState>& Builder,
667 ObjCMessageExpr* ME,
668 ExplodedNode<ValueState>* Pred);
669
670 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
671 GRExprEngine& Engine,
672 GRStmtNodeBuilder<ValueState>& Builder,
673 ObjCMessageExpr* ME,
674 ExplodedNode<ValueState>* Pred);
675
Ted Kremenek7aef4842008-04-16 20:40:59 +0000676 // Stores.
677
678 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
679 GRExprEngine& Engine,
680 GRStmtNodeBuilder<ValueState>& Builder,
681 Expr* E, ExplodedNode<ValueState>* Pred,
682 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000683 // End-of-path.
684
685 virtual void EvalEndPath(GRExprEngine& Engine,
686 GREndPathNodeBuilder<ValueState>& Builder);
687
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000688 // Return statements.
689
690 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
691 GRExprEngine& Engine,
692 GRStmtNodeBuilder<ValueState>& Builder,
693 ReturnStmt* S,
694 ExplodedNode<ValueState>* Pred);
695
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000696 // Error iterators.
697
698 typedef UseAfterReleasesTy::iterator use_after_iterator;
699 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000700 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000701
Ted Kremenek7d421f32008-04-09 23:49:11 +0000702 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
703 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000704
Ted Kremenek7d421f32008-04-09 23:49:11 +0000705 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
706 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000707
708 leaks_iterator leaks_begin() { return Leaks.begin(); }
709 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000710};
711
712} // end anonymous namespace
713
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000714
Ted Kremenek7d421f32008-04-09 23:49:11 +0000715
716
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000717void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
718 void* State, const char* nl,
719 const char* sep) {
720 RefBindings B((RefBindings::TreeTy*) State);
721
722 if (State)
723 Out << sep << nl;
724
725 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
726 Out << (*I).first << " : ";
727 (*I).second.print(Out);
728 Out << nl;
729 }
730}
731
Ted Kremenek455dd862008-04-11 20:23:24 +0000732static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
733 return Summ ? Summ->getArg(idx) : DoNothing;
734}
735
736static inline RetEffect GetRetE(CFRefSummary* Summ) {
737 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
738}
739
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000740void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
741 GRStmtNodeBuilder<ValueState>& Builder,
742 Expr* NodeExpr, Expr* ErrorExpr,
743 ExplodedNode<ValueState>* Pred,
744 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000745 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000746 Builder.BuildSinks = true;
747 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
748
749 if (!N) return;
750
751 switch (hasErr) {
752 default: assert(false);
753 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000754 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000755 break;
756
757 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000758 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000759 break;
760 }
761}
762
Ted Kremenek827f93b2008-03-06 00:08:09 +0000763void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000764 GRExprEngine& Eng,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000765 GRStmtNodeBuilder<ValueState>& Builder,
766 CallExpr* CE, LVal L,
767 ExplodedNode<ValueState>* Pred) {
768
Ted Kremenekce0767f2008-03-12 21:06:49 +0000769 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000770
Ted Kremenek73ba0472008-04-14 17:45:13 +0000771 CFRefSummary* Summ = NULL;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000772
773 // Get the summary.
Ted Kremenek827f93b2008-03-06 00:08:09 +0000774
Ted Kremenek73ba0472008-04-14 17:45:13 +0000775 if (isa<lval::FuncVal>(L)) {
776 lval::FuncVal FV = cast<lval::FuncVal>(L);
777 FunctionDecl* FD = FV.getDecl();
778 Summ = Summaries.getSummary(FD, Eng.getContext());
779 }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000780
Ted Kremeneka7338b42008-03-11 06:39:11 +0000781 // Get the state.
782
783 ValueState* St = Builder.GetState(Pred);
784
785 // Evaluate the effects of the call.
786
787 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000788 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek455dd862008-04-11 20:23:24 +0000789
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000790 // This function has a summary. Evaluate the effect of the arguments.
791
792 unsigned idx = 0;
793
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000794 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000795 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000796
797 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
798 I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000799
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000800 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000801
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000802 if (isa<lval::SymbolVal>(V)) {
803 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000804 RefBindings B = GetRefBindings(StVals);
805
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000806 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000807 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000808 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000809
Ted Kremenek1feab292008-04-16 04:28:53 +0000810 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000811 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000812 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000813 break;
814 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000815 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000816 }
817 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
818
819 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
820 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000821 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000822 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000823 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000824
825 St = StateMgr.getPersistentState(StVals);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000826
Ted Kremenek1feab292008-04-16 04:28:53 +0000827 if (hasErr) {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000828 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
829 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000830 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000831 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000832
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000833 // Finally, consult the summary for the return value.
834
Ted Kremenek455dd862008-04-11 20:23:24 +0000835 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000836
837 switch (RE.getKind()) {
838 default:
839 assert (false && "Unhandled RetEffect."); break;
840
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000841 case RetEffect::NoRet:
Ted Kremenek455dd862008-04-11 20:23:24 +0000842
843 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000844 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
845 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000846
847 if (CE->getType() != Eng.getContext().VoidTy) {
848 unsigned Count = Builder.getCurrentBlockCount();
849 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
850
851 RVal X = CE->getType()->isPointerType()
852 ? cast<RVal>(lval::SymbolVal(Sym))
853 : cast<RVal>(nonlval::SymbolVal(Sym));
854
855 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
856 }
857
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000858 break;
859
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000860 case RetEffect::Alias: {
861 unsigned idx = RE.getValue();
862 assert (idx < CE->getNumArgs());
863 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenekce0767f2008-03-12 21:06:49 +0000864 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000865 break;
866 }
867
868 case RetEffect::OwnedSymbol: {
869 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000870 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000871
872 ValueState StImpl = *St;
873 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000874 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000875
876 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
877 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000878 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000879
880 break;
881 }
882
883 case RetEffect::NotOwnedSymbol: {
884 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000885 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000886
887 ValueState StImpl = *St;
888 RefBindings B = GetRefBindings(StImpl);
889 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
890
891 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
892 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000893 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000894
895 break;
896 }
897 }
898
Ted Kremenekf10f2882008-03-21 21:30:14 +0000899 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek827f93b2008-03-06 00:08:09 +0000900}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000901
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000902
903void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
904 GRExprEngine& Eng,
905 GRStmtNodeBuilder<ValueState>& Builder,
906 ObjCMessageExpr* ME,
907 ExplodedNode<ValueState>* Pred) {
908
909 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
910 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
911}
912
913bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
914 GRExprEngine& Eng,
915 GRStmtNodeBuilder<ValueState>& Builder,
916 ObjCMessageExpr* ME,
917 ExplodedNode<ValueState>* Pred) {
918
Ted Kremenek1feab292008-04-16 04:28:53 +0000919 // Handle "toll-free bridging" of calls to "Release" and "Retain".
920
921 // FIXME: track the underlying object type associated so that we can
922 // flag illegal uses of toll-free bridging (or at least handle it
923 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000924
925 Selector S = ME->getSelector();
926
927 if (!S.isUnarySelector())
928 return true;
929
Ted Kremenek1feab292008-04-16 04:28:53 +0000930 Expr* Receiver = ME->getReceiver();
931
932 if (!Receiver)
933 return true;
934
935 // Check if we are calling "Retain" or "Release".
936
937 bool isRetain = false;
938
939 if (S == RetainSelector)
940 isRetain = true;
941 else if (S != ReleaseSelector)
942 return true;
943
944 // We have "Retain" or "Release". Get the reference binding.
945
946 ValueStateManager& StateMgr = Eng.getStateManager();
947 ValueState* St = Builder.GetState(Pred);
948 RVal V = StateMgr.GetRVal(St, Receiver);
949
950 if (!isa<lval::SymbolVal>(V))
951 return true;
952
953 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
954 RefBindings B = GetRefBindings(*St);
955
956 RefBindings::TreeTy* T = B.SlimFind(Sym);
957
958 if (!T)
959 return true;
960
961 RefVal::Kind hasErr = (RefVal::Kind) 0;
962 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
963
964 // Create a new state with the updated bindings.
965
966 ValueState StVals = *St;
967 SetRefBindings(StVals, B);
968 St = StateMgr.getPersistentState(StVals);
969
970 // Create an error node if it exists.
971
972 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000973 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000974 else
975 Builder.MakeNode(Dst, ME, Pred, St);
976
977 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000978}
979
Ted Kremenek7aef4842008-04-16 20:40:59 +0000980// Stores.
981
982void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
983 GRExprEngine& Eng,
984 GRStmtNodeBuilder<ValueState>& Builder,
985 Expr* E, ExplodedNode<ValueState>* Pred,
986 ValueState* St, RVal TargetLV, RVal Val) {
987
988 // Check if we have a binding for "Val" and if we are storing it to something
989 // we don't understand or otherwise the value "escapes" the function.
990
991 if (!isa<lval::SymbolVal>(Val))
992 return;
993
994 // Are we storing to something that causes the value to "escape"?
995
996 bool escapes = false;
997
998 if (!isa<lval::DeclVal>(TargetLV))
999 escapes = true;
1000 else
1001 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1002
1003 if (!escapes)
1004 return;
1005
1006 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1007 RefBindings B = GetRefBindings(*St);
1008 RefBindings::TreeTy* T = B.SlimFind(Sym);
1009
1010 if (!T)
1011 return;
1012
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001013 // Nuke the binding.
1014 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001015
1016 // Hand of the remaining logic to the parent implementation.
1017 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1018}
1019
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001020
1021ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1022 SymbolID sid) {
1023 ValueState StImpl = *St;
1024 RefBindings B = GetRefBindings(StImpl);
1025 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1026 return VMgr.getPersistentState(StImpl);
1027}
1028
Ted Kremenekffefc352008-04-11 22:25:11 +00001029// End-of-path.
1030
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001031
1032
1033ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1034 ValueState* St, SymbolID sid,
1035 RefVal V, bool& hasLeak) {
1036
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001037 hasLeak = V.isOwned() ||
1038 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001039
1040 if (!hasLeak)
1041 return NukeBinding(VMgr, St, sid);
1042
1043 RefBindings B = GetRefBindings(*St);
1044 ValueState StImpl = *St;
1045 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1046 return VMgr.getPersistentState(StImpl);
1047}
1048
1049void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001050 GREndPathNodeBuilder<ValueState>& Builder) {
1051
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001052 ValueState* St = Builder.getState();
1053 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001054
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001055 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001056
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001057 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1058 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001059
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001060 St = HandleSymbolDeath(Eng.getStateManager(), St,
1061 (*I).first, (*I).second, hasLeak);
1062
1063 if (hasLeak) Leaked.push_back((*I).first);
1064 }
1065
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001066 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
1067 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1068 assert (!LeaksAtNode);
1069 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001070
1071 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1072 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001073 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001074}
1075
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001076 // Return statements.
1077
1078void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1079 GRExprEngine& Eng,
1080 GRStmtNodeBuilder<ValueState>& Builder,
1081 ReturnStmt* S,
1082 ExplodedNode<ValueState>* Pred) {
1083
1084 Expr* RetE = S->getRetValue();
1085 if (!RetE) return;
1086
1087 ValueStateManager& StateMgr = Eng.getStateManager();
1088 ValueState* St = Builder.GetState(Pred);
1089 RVal V = StateMgr.GetRVal(St, RetE);
1090
1091 if (!isa<lval::SymbolVal>(V))
1092 return;
1093
1094 // Get the reference count binding (if any).
1095 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1096 RefBindings B = GetRefBindings(*St);
1097 RefBindings::TreeTy* T = B.SlimFind(Sym);
1098
1099 if (!T)
1100 return;
1101
1102 // Change the reference count.
1103
1104 RefVal X = T->getValue().second;
1105
1106 switch (X.getKind()) {
1107
1108 case RefVal::Owned: {
1109 unsigned cnt = X.getCount();
1110 X = RefVal::makeReturnedOwned(cnt);
1111 break;
1112 }
1113
1114 case RefVal::NotOwned: {
1115 unsigned cnt = X.getCount();
1116 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1117 : RefVal::makeReturnedNotOwned();
1118 break;
1119 }
1120
1121 default:
1122 // None of the error states should be possible at this point.
1123 // A symbol could not have been leaked (yet) if we are returning it
1124 // (and thus it is still live), and the other errors are hard errors.
1125 assert(false);
1126 return;
1127 }
1128
1129 // Update the binding.
1130
1131 ValueState StImpl = *St;
1132 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1133 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1134}
1135
Ted Kremeneka7338b42008-03-11 06:39:11 +00001136
1137CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001138 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001139 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001140
Ted Kremenek0d721572008-03-11 17:48:22 +00001141 // FIXME: This dispatch can potentially be sped up by unifiying it into
1142 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001143
Ted Kremenek0d721572008-03-11 17:48:22 +00001144 switch (E) {
1145 default:
1146 assert (false && "Unhandled CFRef transition.");
1147
1148 case DoNothing:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001149 if (V.getKind() == RefVal::Released) {
1150 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001151 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001152 break;
1153 }
1154
Ted Kremenek0d721572008-03-11 17:48:22 +00001155 return B;
1156
1157 case IncRef:
1158 switch (V.getKind()) {
1159 default:
1160 assert(false);
1161
1162 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001163 V = RefVal::makeOwned(V.getCount()+1);
1164 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001165
Ted Kremenek0d721572008-03-11 17:48:22 +00001166 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001167 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001168 break;
1169
1170 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001171 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001172 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001173 break;
1174 }
1175
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001176 break;
1177
Ted Kremenek0d721572008-03-11 17:48:22 +00001178 case DecRef:
1179 switch (V.getKind()) {
1180 default:
1181 assert (false);
1182
1183 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001184 unsigned Count = V.getCount();
1185 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001186 break;
1187 }
1188
Ted Kremenekc4f81022008-04-10 23:09:18 +00001189 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001190 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001191
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001192 if (Count > 0)
1193 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001194 else {
1195 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001196 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001197 }
1198
Ted Kremenek0d721572008-03-11 17:48:22 +00001199 break;
1200 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001201
1202 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001203 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001204 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001205 break;
1206 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001207
1208 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001209 }
1210
1211 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001212}
1213
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001214
1215//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001216// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001217//===----------------------------------------------------------------------===//
1218
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001219namespace {
1220
1221 //===-------------===//
1222 // Bug Descriptions. //
1223 //===-------------===//
1224
1225 class VISIBILITY_HIDDEN CFRefBug : public BugType {
1226 protected:
1227 CFRefCount& TF;
1228
1229 public:
1230 CFRefBug(CFRefCount& tf) : TF(tf) {}
1231 };
1232
1233 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1234 public:
1235 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1236
1237 virtual const char* getName() const {
1238 return "(CoreFoundation) use-after-release";
1239 }
1240 virtual const char* getDescription() const {
1241 return "(CoreFoundation) Reference-counted object is used"
1242 " after it is released.";
1243 }
1244
1245 virtual void EmitWarnings(BugReporter& BR);
1246
1247 };
1248
1249 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1250 public:
1251 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1252
1253 virtual const char* getName() const {
1254 return "(CoreFoundation) release of non-owned object";
1255 }
1256 virtual const char* getDescription() const {
1257 return "Incorrect decrement of the reference count of a "
1258 "CoreFoundation object:\n"
1259 "The object is not owned at this point by the caller.";
1260 }
1261
1262 virtual void EmitWarnings(BugReporter& BR);
1263 };
1264
1265 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1266 public:
1267 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1268
1269 virtual const char* getName() const {
1270 return "(CoreFoundation) Memory Leak";
1271 }
1272
1273 virtual const char* getDescription() const {
1274 return "The CoreFoundation object has an excessive reference count and"
1275 "\nis leaked after this statement.";
1276 }
1277
1278 virtual void EmitWarnings(BugReporter& BR);
1279 };
1280
1281 //===---------===//
1282 // Bug Reports. //
1283 //===---------===//
1284
1285 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1286 SymbolID Sym;
1287 public:
1288 CFRefReport(const BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
1289 : RangedBugReport(D, n), Sym(sym) {}
1290
1291 virtual ~CFRefReport() {}
1292
1293
1294 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1295 ExplodedNode<ValueState>* PrevN,
1296 ExplodedGraph<ValueState>& G,
1297 BugReporter& BR);
1298 };
1299
1300
1301} // end anonymous namespace
1302
1303void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1304 GRSimpleVals::RegisterChecks(Eng);
1305 Eng.Register(new UseAfterRelease(*this));
1306 Eng.Register(new BadRelease(*this));
1307 Eng.Register(new Leak(*this));
1308}
1309
1310PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1311 ExplodedNode<ValueState>* PrevN,
1312 ExplodedGraph<ValueState>& G,
1313 BugReporter& BR) {
1314
1315 // Check if the type state has changed.
1316
1317 ValueState* PrevSt = PrevN->getState();
1318 ValueState* CurrSt = N->getState();
1319
1320 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1321 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1322
1323
1324
1325
1326 return NULL;
1327}
1328
Ted Kremenek7d421f32008-04-09 23:49:11 +00001329void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001330
Ted Kremenek7d421f32008-04-09 23:49:11 +00001331 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1332 E = TF.use_after_end(); I != E; ++I) {
1333
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001334 CFRefReport report(*this, I->first, I->second.second);
1335 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00001336 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001337 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001338}
1339
1340void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001341
Ted Kremenek7d421f32008-04-09 23:49:11 +00001342 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1343 E = TF.bad_release_end(); I != E; ++I) {
1344
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001345 CFRefReport report(*this, I->first, I->second.second);
1346 report.addRange(I->second.first->getSourceRange());
1347 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00001348 }
1349}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001350
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001351void Leak::EmitWarnings(BugReporter& BR) {
1352
1353 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1354 E = TF.leaks_end(); I != E; ++I) {
1355
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001356 std::vector<SymbolID>& SymV = *(I->second);
1357 unsigned n = SymV.size();
1358
1359 for (unsigned i = 0; i < n; ++i) {
1360 CFRefReport report(*this, I->first, SymV[i]);
1361 BR.EmitWarning(report);
1362 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001363 }
1364}
1365
Ted Kremeneka7338b42008-03-11 06:39:11 +00001366//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001367// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001368//===----------------------------------------------------------------------===//
1369
Ted Kremeneka4c74292008-04-10 22:58:08 +00001370GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx) {
1371 return new CFRefCount(Ctx);
1372}