blob: 0cfd5771fa009502d20e7bad96c03689b7587d04 [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000016#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000017#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000019#include "clang/Analysis/PathDiagnostic.h"
20#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000021#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/ImmutableMap.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000024#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000025#include <ostream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000026
27using namespace clang;
28
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000029//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-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 Kremenek05cbe1a2008-04-09 23:49:11 +000039// Symbolic Evaluation of Reference Counting Logic
40//===----------------------------------------------------------------------===//
41
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000042namespace {
43 enum ArgEffect { IncRef, DecRef, DoNothing };
44 typedef std::vector<ArgEffect> ArgEffects;
45}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000046
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000047namespace llvm {
48 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000049 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek6b3a0f72008-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 Kremenek3ea0b6a2008-04-10 22:58:08 +000052 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000053 };
54} // end llvm namespace
55
56namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +000057
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000058class RetEffect {
59public:
Ted Kremenek940b1d82008-04-10 23:44:06 +000060 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
61 NotOwnedSymbol = 0x3 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000062
63private:
64 unsigned Data;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000065 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000066
Ted Kremenek6b3a0f72008-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 Kremenek3ea0b6a2008-04-10 22:58:08 +000073 return Data >> 2;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000074 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +000075
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000076 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000077
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000078 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000079
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000080 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
81
Ted Kremenek940b1d82008-04-10 23:44:06 +000082 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
83
Ted Kremenek6b3a0f72008-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 Kremenek1ac08d62008-03-11 17:48:22 +000099 ArgEffect getArg(unsigned idx) const {
100 assert (idx < getNumArgs());
101 return (*Args)[idx];
102 }
103
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000104 RetEffect getRet() const {
105 return Ret;
106 }
107
Ted Kremenek6b3a0f72008-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 Kremenek3ea0b6a2008-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 Kremenek00a3a5f2008-03-12 01:21:45 +0000135
136
137 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000138
Ted Kremenek00a3a5f2008-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 Kremenek940b1d82008-04-10 23:44:06 +0000148 void FillDoNothing(unsigned Args);
149
150
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000151public:
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000152 CFRefSummaryManager(ASTContext& ctx) : Ctx(ctx) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000153 ~CFRefSummaryManager();
154
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000155 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremenek6b3a0f72008-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 Kremenek2fff37e2008-03-06 00:08:09 +0000172}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000173
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000174ArgEffects* CFRefSummaryManager::getArgEffects() {
175
Ted Kremenek00a3a5f2008-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 Kremenek2fff37e2008-03-06 00:08:09 +0000225
Ted Kremenek6b3a0f72008-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 Kremenek00a3a5f2008-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 Kremenek6b3a0f72008-03-11 06:39:11 +0000239
Ted Kremenek00a3a5f2008-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 Kremenek6b3a0f72008-03-11 06:39:11 +0000260
261 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000262}
263
Ted Kremenek00a3a5f2008-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 Kremenek3ea0b6a2008-04-10 22:58:08 +0000318 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000319 return NULL;
320
321 if (!ArgT->isPointerType())
322 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000323
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000324 QualType RetTy = FT->getResultType();
325
Ted Kremenek3ea0b6a2008-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 Kremenek940b1d82008-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 Kremenek3ea0b6a2008-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 Kremenek3ea0b6a2008-04-10 22:58:08 +0000341
Ted Kremenek940b1d82008-04-10 23:44:06 +0000342 assert (ScratchArgs.empty());
343 ScratchArgs.push_back(DecRef);
344 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
345 }
Ted Kremenek00a3a5f2008-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 Kremenek940b1d82008-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 Kremenek00a3a5f2008-03-12 01:21:45 +0000377
378CFRefSummary*
379CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
380
381 if (!isCFRefType(FT->getResultType()))
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000382 return NULL;
Ted Kremenek00a3a5f2008-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 Kremenek940b1d82008-04-10 23:44:06 +0000389 FillDoNothing(FT->getNumArgs());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000390 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
391}
392
393CFRefSummary*
394CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
395
Ted Kremeneka0df99f2008-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 Kremenek00a3a5f2008-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 Kremenek940b1d82008-04-10 23:44:06 +0000412 FillDoNothing(FT->getNumArgs());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000413 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
414}
415
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000416//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-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 Kremenek4fd88972008-04-17 18:12:53 +0000441 " after it is released.";
Ted Kremenek05cbe1a2008-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 Kremenek4fd88972008-04-17 18:12:53 +0000457 "CoreFoundation object:\n"
458 "The object is not owned at this point by the caller.";
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000459 }
460
461 virtual void EmitWarnings(BugReporter& BR);
462 };
463
Ted Kremenek989d5192008-04-17 23:43:50 +0000464 class VISIBILITY_HIDDEN Leak : public CFRefBug {
465 public:
466 Leak(CFRefCount& tf) : CFRefBug(tf) {}
467
468 virtual const char* getName() const {
469 return "(CoreFoundation) Memory Leak";
470 }
471
472 virtual const char* getDescription() const {
473 return "The CoreFoundation object has an excessive reference count and"
474 "\nis leaked after this statement.";
475 }
476
477 virtual void EmitWarnings(BugReporter& BR);
478 };
479
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000480} // end anonymous namespace
481
482//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000483// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000484//===----------------------------------------------------------------------===//
485
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000486namespace {
487
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000488class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000489public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000490
Ted Kremenek4fd88972008-04-17 18:12:53 +0000491 enum Kind {
492 Owned = 0, // Owning reference.
493 NotOwned, // Reference is not owned by still valid (not freed).
494 Released, // Object has been released.
495 ReturnedOwned, // Returned object passes ownership to caller.
496 ReturnedNotOwned, // Return object does not pass ownership to caller.
497 ErrorUseAfterRelease, // Object used after released.
498 ErrorReleaseNotOwned, // Release of an object that was not owned.
499 ErrorLeak // A memory leak due to excessive reference counts.
500 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000501
Ted Kremenek4fd88972008-04-17 18:12:53 +0000502private:
503
504 Kind kind;
505 unsigned Cnt;
506
507 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
508
509 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000510
511public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000512
Ted Kremenek4fd88972008-04-17 18:12:53 +0000513 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000514
Ted Kremenek4fd88972008-04-17 18:12:53 +0000515 unsigned getCount() const { return Cnt; }
516
517 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000518
Ted Kremenek73c750b2008-03-11 18:14:09 +0000519 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
520
Ted Kremenekdb863712008-04-16 22:32:20 +0000521 static bool isLeak(Kind k) { return k == ErrorLeak; }
522
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000523 bool isOwned() const {
524 return getKind() == Owned;
525 }
526
Ted Kremenekdb863712008-04-16 22:32:20 +0000527 bool isNotOwned() const {
528 return getKind() == NotOwned;
529 }
530
Ted Kremenek4fd88972008-04-17 18:12:53 +0000531 bool isReturnedOwned() const {
532 return getKind() == ReturnedOwned;
533 }
534
535 bool isReturnedNotOwned() const {
536 return getKind() == ReturnedNotOwned;
537 }
538
539 bool isNonLeakError() const {
540 Kind k = getKind();
541 return isError(k) && !isLeak(k);
542 }
543
544 // State creation: normal state.
545
Ted Kremenek61b9f872008-04-10 23:09:18 +0000546 static RefVal makeOwned(unsigned Count = 0) {
547 return RefVal(Owned, Count);
548 }
549
550 static RefVal makeNotOwned(unsigned Count = 0) {
551 return RefVal(NotOwned, Count);
552 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000553
554 static RefVal makeReturnedOwned(unsigned Count) {
555 return RefVal(ReturnedOwned, Count);
556 }
557
558 static RefVal makeReturnedNotOwned() {
559 return RefVal(ReturnedNotOwned);
560 }
561
562 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000563
Ted Kremenekdb863712008-04-16 22:32:20 +0000564 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000565 static RefVal makeReleased() { return RefVal(Released); }
566 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
567 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000568
569 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000570
Ted Kremenek4fd88972008-04-17 18:12:53 +0000571 bool operator==(const RefVal& X) const {
572 return kind == X.kind && Cnt == X.Cnt;
573 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000574
Ted Kremenek4fd88972008-04-17 18:12:53 +0000575 void Profile(llvm::FoldingSetNodeID& ID) const {
576 ID.AddInteger((unsigned) kind);
577 ID.AddInteger(Cnt);
578 }
579
Ted Kremenekf3948042008-03-11 19:44:10 +0000580 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000581};
Ted Kremenekf3948042008-03-11 19:44:10 +0000582
583void RefVal::print(std::ostream& Out) const {
584 switch (getKind()) {
585 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000586 case Owned: {
587 Out << "Owned";
588 unsigned cnt = getCount();
589 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000590 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000591 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000592
Ted Kremenek61b9f872008-04-10 23:09:18 +0000593 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000594 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000595 unsigned cnt = getCount();
596 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000597 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000598 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000599
Ted Kremenek4fd88972008-04-17 18:12:53 +0000600 case ReturnedOwned: {
601 Out << "ReturnedOwned";
602 unsigned cnt = getCount();
603 if (cnt) Out << " (+ " << cnt << ")";
604 break;
605 }
606
607 case ReturnedNotOwned: {
608 Out << "ReturnedNotOwned";
609 unsigned cnt = getCount();
610 if (cnt) Out << " (+ " << cnt << ")";
611 break;
612 }
613
Ted Kremenekf3948042008-03-11 19:44:10 +0000614 case Released:
615 Out << "Released";
616 break;
617
Ted Kremenekdb863712008-04-16 22:32:20 +0000618 case ErrorLeak:
619 Out << "Leaked";
620 break;
621
Ted Kremenekf3948042008-03-11 19:44:10 +0000622 case ErrorUseAfterRelease:
623 Out << "Use-After-Release [ERROR]";
624 break;
625
626 case ErrorReleaseNotOwned:
627 Out << "Release of Not-Owned [ERROR]";
628 break;
629 }
630}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000631
Ted Kremenek13922612008-04-16 20:40:59 +0000632//===----------------------------------------------------------------------===//
633// Transfer functions.
634//===----------------------------------------------------------------------===//
635
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000636class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenekf3948042008-03-11 19:44:10 +0000637
638 // Type definitions.
639
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000640 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000641 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000642
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000643 typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> UseAfterReleasesTy;
644 typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> ReleasesNotOwnedTy;
Ted Kremenekdb863712008-04-16 22:32:20 +0000645
646 typedef llvm::SmallVector<std::pair<SymbolID, ExplodedNode<ValueState>*>, 2>
647 LeaksTy;
648
Ted Kremenek73c750b2008-03-11 18:14:09 +0000649
Ted Kremenekf3948042008-03-11 19:44:10 +0000650 class BindingsPrinter : public ValueState::CheckerStatePrinter {
651 public:
652 virtual void PrintCheckerState(std::ostream& Out, void* State,
653 const char* nl, const char* sep);
654 };
655
656 // Instance variables.
657
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000658 CFRefSummaryManager Summaries;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000659 RefBFactoryTy RefBFactory;
660
Ted Kremenek73c750b2008-03-11 18:14:09 +0000661 UseAfterReleasesTy UseAfterReleases;
662 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000663 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000664
Ted Kremenekf3948042008-03-11 19:44:10 +0000665 BindingsPrinter Printer;
666
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000667 Selector RetainSelector;
668 Selector ReleaseSelector;
669
Ted Kremenekf3948042008-03-11 19:44:10 +0000670 // Private methods.
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000671
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000672 static RefBindings GetRefBindings(ValueState& StImpl) {
673 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
674 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000675
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000676 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
677 StImpl.CheckerState = B.getRoot();
678 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000679
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000680 RefBindings Remove(RefBindings B, SymbolID sym) {
681 return RefBFactory.Remove(B, sym);
682 }
683
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000684 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000685 RefVal::Kind& hasErr);
686
Ted Kremenekdb863712008-04-16 22:32:20 +0000687 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
688 GRStmtNodeBuilder<ValueState>& Builder,
689 Expr* NodeExpr, Expr* ErrorExpr,
690 ExplodedNode<ValueState>* Pred,
691 ValueState* St,
692 RefVal::Kind hasErr);
693
694 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
695 SymbolID sid, RefVal V, bool& hasLeak);
696
697 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
698 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000699
700public:
Ted Kremenek13922612008-04-16 20:40:59 +0000701
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000702 CFRefCount(ASTContext& Ctx)
703 : Summaries(Ctx),
704 RetainSelector(GetUnarySelector("retain", Ctx)),
705 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
706
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000707 virtual ~CFRefCount() {}
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000708
709 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000710
711 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
712 return &Printer;
713 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000714
715 // Calls.
716
717 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000718 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000719 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000720 CallExpr* CE, LVal L,
721 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000722
Ted Kremenek85348202008-04-15 23:44:31 +0000723 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
724 GRExprEngine& Engine,
725 GRStmtNodeBuilder<ValueState>& Builder,
726 ObjCMessageExpr* ME,
727 ExplodedNode<ValueState>* Pred);
728
729 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
730 GRExprEngine& Engine,
731 GRStmtNodeBuilder<ValueState>& Builder,
732 ObjCMessageExpr* ME,
733 ExplodedNode<ValueState>* Pred);
734
Ted Kremenek13922612008-04-16 20:40:59 +0000735 // Stores.
736
737 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
738 GRExprEngine& Engine,
739 GRStmtNodeBuilder<ValueState>& Builder,
740 Expr* E, ExplodedNode<ValueState>* Pred,
741 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000742 // End-of-path.
743
744 virtual void EvalEndPath(GRExprEngine& Engine,
745 GREndPathNodeBuilder<ValueState>& Builder);
746
Ted Kremenek4fd88972008-04-17 18:12:53 +0000747 // Return statements.
748
749 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
750 GRExprEngine& Engine,
751 GRStmtNodeBuilder<ValueState>& Builder,
752 ReturnStmt* S,
753 ExplodedNode<ValueState>* Pred);
754
Ted Kremenekfa34b332008-04-09 01:10:13 +0000755 // Error iterators.
756
757 typedef UseAfterReleasesTy::iterator use_after_iterator;
758 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000759 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000760
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000761 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
762 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000763
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000764 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
765 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000766
767 leaks_iterator leaks_begin() { return Leaks.begin(); }
768 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000769};
770
771} // end anonymous namespace
772
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000773void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
774 GRSimpleVals::RegisterChecks(Eng);
775 Eng.Register(new UseAfterRelease(*this));
776 Eng.Register(new BadRelease(*this));
Ted Kremenek989d5192008-04-17 23:43:50 +0000777 Eng.Register(new Leak(*this));
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000778}
779
780
Ted Kremenekf3948042008-03-11 19:44:10 +0000781void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
782 void* State, const char* nl,
783 const char* sep) {
784 RefBindings B((RefBindings::TreeTy*) State);
785
786 if (State)
787 Out << sep << nl;
788
789 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
790 Out << (*I).first << " : ";
791 (*I).second.print(Out);
792 Out << nl;
793 }
794}
795
Ted Kremenekf9561e52008-04-11 20:23:24 +0000796static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
797 return Summ ? Summ->getArg(idx) : DoNothing;
798}
799
800static inline RetEffect GetRetE(CFRefSummary* Summ) {
801 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
802}
803
Ted Kremenekdb863712008-04-16 22:32:20 +0000804void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
805 GRStmtNodeBuilder<ValueState>& Builder,
806 Expr* NodeExpr, Expr* ErrorExpr,
807 ExplodedNode<ValueState>* Pred,
808 ValueState* St,
809 RefVal::Kind hasErr) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000810 Builder.BuildSinks = true;
811 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
812
813 if (!N) return;
814
815 switch (hasErr) {
816 default: assert(false);
817 case RefVal::ErrorUseAfterRelease:
818 UseAfterReleases[N] = ErrorExpr;
819 break;
820
821 case RefVal::ErrorReleaseNotOwned:
822 ReleasesNotOwned[N] = ErrorExpr;
823 break;
824 }
825}
826
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000827void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000828 GRExprEngine& Eng,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000829 GRStmtNodeBuilder<ValueState>& Builder,
830 CallExpr* CE, LVal L,
831 ExplodedNode<ValueState>* Pred) {
832
Ted Kremenek199e1a02008-03-12 21:06:49 +0000833 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000834
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000835 CFRefSummary* Summ = NULL;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000836
837 // Get the summary.
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000838
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000839 if (isa<lval::FuncVal>(L)) {
840 lval::FuncVal FV = cast<lval::FuncVal>(L);
841 FunctionDecl* FD = FV.getDecl();
842 Summ = Summaries.getSummary(FD, Eng.getContext());
843 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000844
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000845 // Get the state.
846
847 ValueState* St = Builder.GetState(Pred);
848
849 // Evaluate the effects of the call.
850
851 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000852 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekf9561e52008-04-11 20:23:24 +0000853
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000854 // This function has a summary. Evaluate the effect of the arguments.
855
856 unsigned idx = 0;
857
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000858 Expr* ErrorExpr = NULL;
859
860 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
861 I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000862
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000863 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000864
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000865 if (isa<lval::SymbolVal>(V)) {
866 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +0000867 RefBindings B = GetRefBindings(StVals);
868
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000869 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000870 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000871 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000872
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000873 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000874 ErrorExpr = *I;
875 break;
876 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000877 }
Ted Kremenekb8873552008-04-11 20:51:02 +0000878 }
879 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
880
881 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
882 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000883 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +0000884 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000885 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000886
887 St = StateMgr.getPersistentState(StVals);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000888
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000889 if (hasErr) {
Ted Kremenekdb863712008-04-16 22:32:20 +0000890 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St, hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000891 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000892 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000893
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000894 // Finally, consult the summary for the return value.
895
Ted Kremenekf9561e52008-04-11 20:23:24 +0000896 RetEffect RE = GetRetE(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000897
898 switch (RE.getKind()) {
899 default:
900 assert (false && "Unhandled RetEffect."); break;
901
Ted Kremenek940b1d82008-04-10 23:44:06 +0000902 case RetEffect::NoRet:
Ted Kremenekf9561e52008-04-11 20:23:24 +0000903
904 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +0000905 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
906 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000907
908 if (CE->getType() != Eng.getContext().VoidTy) {
909 unsigned Count = Builder.getCurrentBlockCount();
910 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
911
912 RVal X = CE->getType()->isPointerType()
913 ? cast<RVal>(lval::SymbolVal(Sym))
914 : cast<RVal>(nonlval::SymbolVal(Sym));
915
916 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
917 }
918
Ted Kremenek940b1d82008-04-10 23:44:06 +0000919 break;
920
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000921 case RetEffect::Alias: {
922 unsigned idx = RE.getValue();
923 assert (idx < CE->getNumArgs());
924 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenek199e1a02008-03-12 21:06:49 +0000925 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000926 break;
927 }
928
929 case RetEffect::OwnedSymbol: {
930 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000931 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000932
933 ValueState StImpl = *St;
934 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000935 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000936
937 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
938 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000939 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000940
941 break;
942 }
943
944 case RetEffect::NotOwnedSymbol: {
945 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000946 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000947
948 ValueState StImpl = *St;
949 RefBindings B = GetRefBindings(StImpl);
950 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
951
952 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
953 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000954 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000955
956 break;
957 }
958 }
959
Ted Kremenek0e561a32008-03-21 21:30:14 +0000960 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000961}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000962
Ted Kremenek85348202008-04-15 23:44:31 +0000963
964void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
965 GRExprEngine& Eng,
966 GRStmtNodeBuilder<ValueState>& Builder,
967 ObjCMessageExpr* ME,
968 ExplodedNode<ValueState>* Pred) {
969
970 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
971 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
972}
973
974bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
975 GRExprEngine& Eng,
976 GRStmtNodeBuilder<ValueState>& Builder,
977 ObjCMessageExpr* ME,
978 ExplodedNode<ValueState>* Pred) {
979
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000980 // Handle "toll-free bridging" of calls to "Release" and "Retain".
981
982 // FIXME: track the underlying object type associated so that we can
983 // flag illegal uses of toll-free bridging (or at least handle it
984 // at casts).
Ted Kremenek85348202008-04-15 23:44:31 +0000985
986 Selector S = ME->getSelector();
987
988 if (!S.isUnarySelector())
989 return true;
990
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000991 Expr* Receiver = ME->getReceiver();
992
993 if (!Receiver)
994 return true;
995
996 // Check if we are calling "Retain" or "Release".
997
998 bool isRetain = false;
999
1000 if (S == RetainSelector)
1001 isRetain = true;
1002 else if (S != ReleaseSelector)
1003 return true;
1004
1005 // We have "Retain" or "Release". Get the reference binding.
1006
1007 ValueStateManager& StateMgr = Eng.getStateManager();
1008 ValueState* St = Builder.GetState(Pred);
1009 RVal V = StateMgr.GetRVal(St, Receiver);
1010
1011 if (!isa<lval::SymbolVal>(V))
1012 return true;
1013
1014 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1015 RefBindings B = GetRefBindings(*St);
1016
1017 RefBindings::TreeTy* T = B.SlimFind(Sym);
1018
1019 if (!T)
1020 return true;
1021
1022 RefVal::Kind hasErr = (RefVal::Kind) 0;
1023 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
1024
1025 // Create a new state with the updated bindings.
1026
1027 ValueState StVals = *St;
1028 SetRefBindings(StVals, B);
1029 St = StateMgr.getPersistentState(StVals);
1030
1031 // Create an error node if it exists.
1032
1033 if (hasErr)
Ted Kremenekdb863712008-04-16 22:32:20 +00001034 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001035 else
1036 Builder.MakeNode(Dst, ME, Pred, St);
1037
1038 return false;
Ted Kremenek85348202008-04-15 23:44:31 +00001039}
1040
Ted Kremenek13922612008-04-16 20:40:59 +00001041// Stores.
1042
1043void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1044 GRExprEngine& Eng,
1045 GRStmtNodeBuilder<ValueState>& Builder,
1046 Expr* E, ExplodedNode<ValueState>* Pred,
1047 ValueState* St, RVal TargetLV, RVal Val) {
1048
1049 // Check if we have a binding for "Val" and if we are storing it to something
1050 // we don't understand or otherwise the value "escapes" the function.
1051
1052 if (!isa<lval::SymbolVal>(Val))
1053 return;
1054
1055 // Are we storing to something that causes the value to "escape"?
1056
1057 bool escapes = false;
1058
1059 if (!isa<lval::DeclVal>(TargetLV))
1060 escapes = true;
1061 else
1062 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1063
1064 if (!escapes)
1065 return;
1066
1067 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1068 RefBindings B = GetRefBindings(*St);
1069 RefBindings::TreeTy* T = B.SlimFind(Sym);
1070
1071 if (!T)
1072 return;
1073
Ted Kremenekdb863712008-04-16 22:32:20 +00001074 // Nuke the binding.
1075 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001076
1077 // Hand of the remaining logic to the parent implementation.
1078 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1079}
1080
Ted Kremenekdb863712008-04-16 22:32:20 +00001081
1082ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1083 SymbolID sid) {
1084 ValueState StImpl = *St;
1085 RefBindings B = GetRefBindings(StImpl);
1086 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1087 return VMgr.getPersistentState(StImpl);
1088}
1089
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001090// End-of-path.
1091
Ted Kremenekdb863712008-04-16 22:32:20 +00001092
1093
1094ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1095 ValueState* St, SymbolID sid,
1096 RefVal V, bool& hasLeak) {
1097
Ted Kremenek4fd88972008-04-17 18:12:53 +00001098 hasLeak = V.isOwned() ||
1099 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001100
1101 if (!hasLeak)
1102 return NukeBinding(VMgr, St, sid);
1103
1104 RefBindings B = GetRefBindings(*St);
1105 ValueState StImpl = *St;
1106 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1107 return VMgr.getPersistentState(StImpl);
1108}
1109
1110void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001111 GREndPathNodeBuilder<ValueState>& Builder) {
1112
Ted Kremenekdb863712008-04-16 22:32:20 +00001113 ValueState* St = Builder.getState();
1114 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001115
Ted Kremenekdb863712008-04-16 22:32:20 +00001116 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001117
Ted Kremenekdb863712008-04-16 22:32:20 +00001118 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1119 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001120
Ted Kremenekdb863712008-04-16 22:32:20 +00001121 St = HandleSymbolDeath(Eng.getStateManager(), St,
1122 (*I).first, (*I).second, hasLeak);
1123
1124 if (hasLeak) Leaked.push_back((*I).first);
1125 }
1126
1127 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
1128
1129 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1130 E = Leaked.end(); I != E; ++I)
1131 Leaks.push_back(std::make_pair(*I, N));
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001132}
1133
Ted Kremenek4fd88972008-04-17 18:12:53 +00001134 // Return statements.
1135
1136void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1137 GRExprEngine& Eng,
1138 GRStmtNodeBuilder<ValueState>& Builder,
1139 ReturnStmt* S,
1140 ExplodedNode<ValueState>* Pred) {
1141
1142 Expr* RetE = S->getRetValue();
1143 if (!RetE) return;
1144
1145 ValueStateManager& StateMgr = Eng.getStateManager();
1146 ValueState* St = Builder.GetState(Pred);
1147 RVal V = StateMgr.GetRVal(St, RetE);
1148
1149 if (!isa<lval::SymbolVal>(V))
1150 return;
1151
1152 // Get the reference count binding (if any).
1153 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1154 RefBindings B = GetRefBindings(*St);
1155 RefBindings::TreeTy* T = B.SlimFind(Sym);
1156
1157 if (!T)
1158 return;
1159
1160 // Change the reference count.
1161
1162 RefVal X = T->getValue().second;
1163
1164 switch (X.getKind()) {
1165
1166 case RefVal::Owned: {
1167 unsigned cnt = X.getCount();
1168 X = RefVal::makeReturnedOwned(cnt);
1169 break;
1170 }
1171
1172 case RefVal::NotOwned: {
1173 unsigned cnt = X.getCount();
1174 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1175 : RefVal::makeReturnedNotOwned();
1176 break;
1177 }
1178
1179 default:
1180 // None of the error states should be possible at this point.
1181 // A symbol could not have been leaked (yet) if we are returning it
1182 // (and thus it is still live), and the other errors are hard errors.
1183 assert(false);
1184 return;
1185 }
1186
1187 // Update the binding.
1188
1189 ValueState StImpl = *St;
1190 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1191 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1192}
1193
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001194
1195CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001196 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001197 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001198
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001199 // FIXME: This dispatch can potentially be sped up by unifiying it into
1200 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001201
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001202 switch (E) {
1203 default:
1204 assert (false && "Unhandled CFRef transition.");
1205
1206 case DoNothing:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001207 if (V.getKind() == RefVal::Released) {
1208 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001209 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001210 break;
1211 }
1212
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001213 return B;
1214
1215 case IncRef:
1216 switch (V.getKind()) {
1217 default:
1218 assert(false);
1219
1220 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001221 V = RefVal::makeOwned(V.getCount()+1);
1222 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001223
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001224 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001225 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001226 break;
1227
1228 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001229 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001230 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001231 break;
1232 }
1233
Ted Kremenek940b1d82008-04-10 23:44:06 +00001234 break;
1235
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001236 case DecRef:
1237 switch (V.getKind()) {
1238 default:
1239 assert (false);
1240
1241 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001242 unsigned Count = V.getCount();
1243 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001244 break;
1245 }
1246
Ted Kremenek61b9f872008-04-10 23:09:18 +00001247 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001248 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001249
Ted Kremenek4fd88972008-04-17 18:12:53 +00001250 if (Count > 0)
1251 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001252 else {
1253 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001254 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001255 }
1256
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001257 break;
1258 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001259
1260 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001261 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001262 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001263 break;
1264 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001265
1266 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001267 }
1268
1269 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001270}
1271
Ted Kremenekfa34b332008-04-09 01:10:13 +00001272
1273//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001274// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001275//===----------------------------------------------------------------------===//
1276
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001277void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001278
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001279 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1280 E = TF.use_after_end(); I != E; ++I) {
1281
Ted Kremenekd2f642b2008-04-14 17:39:48 +00001282 RangedBugReport report(*this, I->first);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001283 report.addRange(I->second->getSourceRange());
Ted Kremenekd2f642b2008-04-14 17:39:48 +00001284 BR.EmitPathWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001285 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001286}
1287
1288void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001289
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001290 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1291 E = TF.bad_release_end(); I != E; ++I) {
1292
Ted Kremenekd2f642b2008-04-14 17:39:48 +00001293 RangedBugReport report(*this, I->first);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001294 report.addRange(I->second->getSourceRange());
Ted Kremenekd2f642b2008-04-14 17:39:48 +00001295 BR.EmitPathWarning(report);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001296
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001297 }
1298}
Ted Kremenekfa34b332008-04-09 01:10:13 +00001299
Ted Kremenek989d5192008-04-17 23:43:50 +00001300void Leak::EmitWarnings(BugReporter& BR) {
1301
1302 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1303 E = TF.leaks_end(); I != E; ++I) {
1304
1305 BugReport report(*this, I->second);
1306 BR.EmitPathWarning(report);
1307 }
1308}
1309
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001310//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00001311// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001312//===----------------------------------------------------------------------===//
1313
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00001314GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx) {
1315 return new CFRefCount(Ctx);
1316}