blob: 730c5311f541ba5547da19b4ed89631fe19d0194 [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000016#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000017#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000019#include "clang/Analysis/PathDiagnostic.h"
20#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000021#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/ImmutableMap.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000024#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000025#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000026#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000027
28using namespace clang;
29
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000030//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-04-17 18:12:53 +000031// Utility functions.
32//===----------------------------------------------------------------------===//
33
34static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
35 IdentifierInfo* II = &Ctx.Idents.get(name);
36 return Ctx.Selectors.getSelector(0, &II);
37}
38
39//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000040// Symbolic Evaluation of Reference Counting Logic
41//===----------------------------------------------------------------------===//
42
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000043namespace {
44 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenek891d5cc2008-04-24 17:22:33 +000045 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000046}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000047
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000048namespace llvm {
49 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000050 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +000051 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
52 ID.AddInteger(I->first);
53 ID.AddInteger((unsigned) I->second);
54 }
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000055 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000056 };
57} // end llvm namespace
58
59namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +000060
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000061class RetEffect {
62public:
Ted Kremenek940b1d82008-04-10 23:44:06 +000063 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
64 NotOwnedSymbol = 0x3 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000065
66private:
67 unsigned Data;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000068 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000069
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000070public:
71
72 Kind getKind() const { return (Kind) (Data & 0x3); }
73
74 unsigned getValue() const {
75 assert(getKind() == Alias);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000076 return Data >> 2;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000077 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +000078
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000079 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000080
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000081 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000082
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000083 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
84
Ted Kremenek940b1d82008-04-10 23:44:06 +000085 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
86
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000087 operator Kind() const { return getKind(); }
88
89 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
90};
91
92
93class CFRefSummary : public llvm::FoldingSetNode {
94 ArgEffects* Args;
95 RetEffect Ret;
96public:
97
98 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
99
100 unsigned getNumArgs() const { return Args->size(); }
101
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000102 ArgEffect getArg(unsigned idx) const {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000103 if (!Args)
104 return DoNothing;
105
106 // If Args is present, it is likely to contain only 1 element.
107 // Just do a linear search. Do it from the back because functions with
108 // large numbers of arguments will be tail heavy with respect to which
109 // argument they actually modify with respect to the reference count.
110
111 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
112 I!=E; ++I) {
113
114 if (idx > I->first)
115 return DoNothing;
116
117 if (idx == I->first)
118 return I->second;
119 }
120
121 return DoNothing;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000122 }
123
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000124 RetEffect getRet() const {
125 return Ret;
126 }
127
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000128 typedef ArgEffects::const_iterator arg_iterator;
129
130 arg_iterator begin_args() const { return Args->begin(); }
131 arg_iterator end_args() const { return Args->end(); }
132
133 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
134 ID.AddPointer(A);
135 ID.Add(R);
136 }
137
138 void Profile(llvm::FoldingSetNodeID& ID) const {
139 Profile(ID, Args, Ret);
140 }
141};
142
143
144class CFRefSummaryManager {
145 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
146 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
147 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
148
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000149 ASTContext& Ctx;
150 SummarySetTy SummarySet;
151 SummaryMapTy SummaryMap;
152 AESetTy AESet;
153 llvm::BumpPtrAllocator BPAlloc;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000154 ArgEffects ScratchArgs;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000155
156 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000157
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000158 CFRefSummary* getCannedCFSummary(FunctionTypeProto* FT, bool isRetain);
159
160 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
161
162 CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
163 CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);
164
165 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000166
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000167public:
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000168 CFRefSummaryManager(ASTContext& ctx) : Ctx(ctx) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000169 ~CFRefSummaryManager();
170
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000171 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000172};
173
174} // end anonymous namespace
175
176//===----------------------------------------------------------------------===//
177// Implementation of checker data structures.
178//===----------------------------------------------------------------------===//
179
180CFRefSummaryManager::~CFRefSummaryManager() {
181
182 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
183 // mitigating the need to do explicit cleanup of the
184 // Argument-Effect summaries.
185
186 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
187 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000188}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000189
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000190ArgEffects* CFRefSummaryManager::getArgEffects() {
191
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000192 if (ScratchArgs.empty())
193 return NULL;
194
195 // Compute a profile for a non-empty ScratchArgs.
196
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000197 llvm::FoldingSetNodeID profile;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000198
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000199 profile.Add(ScratchArgs);
200 void* InsertPos;
201
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000202 // Look up the uniqued copy, or create a new one.
203
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000204 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
205 AESet.FindNodeOrInsertPos(profile, InsertPos);
206
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000207 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000208 ScratchArgs.clear();
209 return &E->getValue();
210 }
211
212 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
213 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
214
215 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
216 AESet.InsertNode(E, InsertPos);
217
218 ScratchArgs.clear();
219 return &E->getValue();
220}
221
222CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
223 RetEffect RE) {
224
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000225 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000226 llvm::FoldingSetNodeID profile;
227 CFRefSummary::Profile(profile, AE, RE);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000228
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000229 // Look up the uniqued summary, or create one if it doesn't exist.
230 void* InsertPos;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000231 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
232
233 if (Summ)
234 return Summ;
235
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000236 // Create the summary and return it.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000237 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
238 new (Summ) CFRefSummary(AE, RE);
239 SummarySet.InsertNode(Summ, InsertPos);
240
241 return Summ;
242}
243
244
245CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
246 ASTContext& Ctx) {
247
248 SourceLocation Loc = FD->getLocation();
249
250 if (!Loc.isFileID())
251 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000252
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000253
254 // Look up a summary in our cache of FunctionDecls -> Summaries.
255 SummaryMapTy::iterator I = SummaryMap.find(FD);
256
257 if (I != SummaryMap.end())
258 return I->second;
259
260 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000261 const char* FName = FD->getIdentifier()->getName();
262
263 if (FName[0] == 'C' && FName[1] == 'F') {
264 CFRefSummary* S = getCFSummary(FD, FName);
265 SummaryMap[FD] = S;
266 return S;
267 }
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000268
269 // Function has no ref-count effects. Return the NULL summary.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000270 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000271}
272
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000273CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
274 const char* FName) {
275
276 // For now, only generate summaries for functions that have a prototype.
277
278 FunctionTypeProto* FT =
279 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
280
281 if (!FT)
282 return NULL;
283
284 FName += 2;
285
286 if (strcmp(FName, "Retain") == 0)
287 return getCannedCFSummary(FT, true);
288
289 if (strcmp(FName, "Release") == 0)
290 return getCannedCFSummary(FT, false);
291
292 assert (ScratchArgs.empty());
293 bool usesCreateRule = false;
294
295 if (strstr(FName, "Create"))
296 usesCreateRule = true;
297
298 if (!usesCreateRule && strstr(FName, "Copy"))
299 usesCreateRule = true;
300
301 if (usesCreateRule)
302 return getCFSummaryCreateRule(FT);
303
304 if (strstr(FName, "Get"))
305 return getCFSummaryGetRule(FT);
306
307 return NULL;
308}
309
310CFRefSummary* CFRefSummaryManager::getCannedCFSummary(FunctionTypeProto* FT,
311 bool isRetain) {
312
313 if (FT->getNumArgs() != 1)
314 return NULL;
315
316 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
317
318 if (!ArgT)
319 return NULL;
320
321 // For CFRetain/CFRelease, the first (and only) argument is of type
322 // "CFTypeRef".
323
324 const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
325 assert (TDName);
326
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000327 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000328 return NULL;
329
330 if (!ArgT->isPointerType())
331 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000332
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000333 QualType RetTy = FT->getResultType();
334
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000335 if (isRetain) {
336 // CFRetain: the return type should also be "CFTypeRef".
337 if (RetTy.getTypePtr() != ArgT)
338 return NULL;
Ted Kremenek940b1d82008-04-10 23:44:06 +0000339
340 // The function's interface checks out. Generate a canned summary.
341 assert (ScratchArgs.empty());
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000342 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek940b1d82008-04-10 23:44:06 +0000343 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000344 }
345 else {
346 // CFRelease: the return type should be void.
347
348 if (RetTy != Ctx.VoidTy)
349 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000350
Ted Kremenek940b1d82008-04-10 23:44:06 +0000351 assert (ScratchArgs.empty());
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000352 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek940b1d82008-04-10 23:44:06 +0000353 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
354 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000355}
356
357static bool isCFRefType(QualType T) {
358
359 if (!T->isPointerType())
360 return false;
361
362 // Check the typedef for the name "CF" and the substring "Ref".
363
364 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
365
366 if (!TD)
367 return false;
368
369 const char* TDName = TD->getDecl()->getIdentifier()->getName();
370 assert (TDName);
371
372 if (TDName[0] != 'C' || TDName[1] != 'F')
373 return false;
374
375 if (strstr(TDName, "Ref") == 0)
376 return false;
377
378 return true;
379}
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000380
381CFRefSummary*
382CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
383
384 if (!isCFRefType(FT->getResultType()))
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000385 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000386
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000387 // FIXME: Add special-cases for functions that retain/release. For now
388 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000389
390 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000391 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
392}
393
394CFRefSummary*
395CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
396
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000397 QualType RetTy = FT->getResultType();
398
399 // FIXME: For now we assume that all pointer types returned are referenced
400 // counted. Since this is the "Get" rule, we assume non-ownership, which
401 // works fine for things that are not reference counted. We do this because
402 // some generic data structures return "void*". We need something better
403 // in the future.
404
405 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
406 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000407
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000408 // FIXME: Add special-cases for functions that retain/release. For now
409 // just handle the default case.
410
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000411 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000412 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
413}
414
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000415//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000416// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000417//===----------------------------------------------------------------------===//
418
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000419namespace {
420
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000421class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000422public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000423
Ted Kremenek4fd88972008-04-17 18:12:53 +0000424 enum Kind {
425 Owned = 0, // Owning reference.
426 NotOwned, // Reference is not owned by still valid (not freed).
427 Released, // Object has been released.
428 ReturnedOwned, // Returned object passes ownership to caller.
429 ReturnedNotOwned, // Return object does not pass ownership to caller.
430 ErrorUseAfterRelease, // Object used after released.
431 ErrorReleaseNotOwned, // Release of an object that was not owned.
432 ErrorLeak // A memory leak due to excessive reference counts.
433 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000434
Ted Kremenek4fd88972008-04-17 18:12:53 +0000435private:
436
437 Kind kind;
438 unsigned Cnt;
439
440 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
441
442 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000443
444public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000445
Ted Kremenek4fd88972008-04-17 18:12:53 +0000446 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000447
Ted Kremenek4fd88972008-04-17 18:12:53 +0000448 unsigned getCount() const { return Cnt; }
449
450 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000451
Ted Kremenek73c750b2008-03-11 18:14:09 +0000452 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
453
Ted Kremenekdb863712008-04-16 22:32:20 +0000454 static bool isLeak(Kind k) { return k == ErrorLeak; }
455
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000456 bool isOwned() const {
457 return getKind() == Owned;
458 }
459
Ted Kremenekdb863712008-04-16 22:32:20 +0000460 bool isNotOwned() const {
461 return getKind() == NotOwned;
462 }
463
Ted Kremenek4fd88972008-04-17 18:12:53 +0000464 bool isReturnedOwned() const {
465 return getKind() == ReturnedOwned;
466 }
467
468 bool isReturnedNotOwned() const {
469 return getKind() == ReturnedNotOwned;
470 }
471
472 bool isNonLeakError() const {
473 Kind k = getKind();
474 return isError(k) && !isLeak(k);
475 }
476
477 // State creation: normal state.
478
Ted Kremenek61b9f872008-04-10 23:09:18 +0000479 static RefVal makeOwned(unsigned Count = 0) {
480 return RefVal(Owned, Count);
481 }
482
483 static RefVal makeNotOwned(unsigned Count = 0) {
484 return RefVal(NotOwned, Count);
485 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000486
487 static RefVal makeReturnedOwned(unsigned Count) {
488 return RefVal(ReturnedOwned, Count);
489 }
490
491 static RefVal makeReturnedNotOwned() {
492 return RefVal(ReturnedNotOwned);
493 }
494
495 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000496
Ted Kremenekdb863712008-04-16 22:32:20 +0000497 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000498 static RefVal makeReleased() { return RefVal(Released); }
499 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
500 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000501
502 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000503
Ted Kremenek4fd88972008-04-17 18:12:53 +0000504 bool operator==(const RefVal& X) const {
505 return kind == X.kind && Cnt == X.Cnt;
506 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000507
Ted Kremenek4fd88972008-04-17 18:12:53 +0000508 void Profile(llvm::FoldingSetNodeID& ID) const {
509 ID.AddInteger((unsigned) kind);
510 ID.AddInteger(Cnt);
511 }
512
Ted Kremenekf3948042008-03-11 19:44:10 +0000513 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000514};
Ted Kremenekf3948042008-03-11 19:44:10 +0000515
516void RefVal::print(std::ostream& Out) const {
517 switch (getKind()) {
518 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000519 case Owned: {
520 Out << "Owned";
521 unsigned cnt = getCount();
522 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000523 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000524 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000525
Ted Kremenek61b9f872008-04-10 23:09:18 +0000526 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000527 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000528 unsigned cnt = getCount();
529 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000530 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000531 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000532
Ted Kremenek4fd88972008-04-17 18:12:53 +0000533 case ReturnedOwned: {
534 Out << "ReturnedOwned";
535 unsigned cnt = getCount();
536 if (cnt) Out << " (+ " << cnt << ")";
537 break;
538 }
539
540 case ReturnedNotOwned: {
541 Out << "ReturnedNotOwned";
542 unsigned cnt = getCount();
543 if (cnt) Out << " (+ " << cnt << ")";
544 break;
545 }
546
Ted Kremenekf3948042008-03-11 19:44:10 +0000547 case Released:
548 Out << "Released";
549 break;
550
Ted Kremenekdb863712008-04-16 22:32:20 +0000551 case ErrorLeak:
552 Out << "Leaked";
553 break;
554
Ted Kremenekf3948042008-03-11 19:44:10 +0000555 case ErrorUseAfterRelease:
556 Out << "Use-After-Release [ERROR]";
557 break;
558
559 case ErrorReleaseNotOwned:
560 Out << "Release of Not-Owned [ERROR]";
561 break;
562 }
563}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000564
Ted Kremenek13922612008-04-16 20:40:59 +0000565//===----------------------------------------------------------------------===//
566// Transfer functions.
567//===----------------------------------------------------------------------===//
568
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000569class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000570public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000571 // Type definitions.
572
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000573 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000574 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000575
Ted Kremenek8dd56462008-04-18 03:39:05 +0000576 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
577 ReleasesNotOwnedTy;
578
579 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
580
581 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000582 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000583
Ted Kremenekf3948042008-03-11 19:44:10 +0000584 class BindingsPrinter : public ValueState::CheckerStatePrinter {
585 public:
586 virtual void PrintCheckerState(std::ostream& Out, void* State,
587 const char* nl, const char* sep);
588 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000589
590private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000591 // Instance variables.
592
Ted Kremeneke5c30122008-04-29 05:13:59 +0000593 CFRefSummaryManager Summaries;
594 const bool GCEnabled;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000595 RefBFactoryTy RefBFactory;
596
Ted Kremenek73c750b2008-03-11 18:14:09 +0000597 UseAfterReleasesTy UseAfterReleases;
598 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000599 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000600
Ted Kremenekf3948042008-03-11 19:44:10 +0000601 BindingsPrinter Printer;
602
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000603 Selector RetainSelector;
604 Selector ReleaseSelector;
605
Ted Kremenek8dd56462008-04-18 03:39:05 +0000606public:
607
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000608 static RefBindings GetRefBindings(ValueState& StImpl) {
609 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
610 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000611
Ted Kremenek8dd56462008-04-18 03:39:05 +0000612private:
613
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000614 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
615 StImpl.CheckerState = B.getRoot();
616 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000617
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000618 RefBindings Remove(RefBindings B, SymbolID sym) {
619 return RefBFactory.Remove(B, sym);
620 }
621
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000622 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000623 RefVal::Kind& hasErr);
624
Ted Kremenekdb863712008-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 Kremenek8dd56462008-04-18 03:39:05 +0000630 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-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 Kremenek6b3a0f72008-03-11 06:39:11 +0000637
638public:
Ted Kremenek13922612008-04-16 20:40:59 +0000639
Ted Kremeneke5c30122008-04-29 05:13:59 +0000640 CFRefCount(ASTContext& Ctx, bool gcenabled)
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000641 : Summaries(Ctx),
Ted Kremeneke5c30122008-04-29 05:13:59 +0000642 GCEnabled(gcenabled),
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000643 RetainSelector(GetUnarySelector("retain", Ctx)),
644 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
645
Ted Kremenek8dd56462008-04-18 03:39:05 +0000646 virtual ~CFRefCount() {
647 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
648 delete I->second;
649 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000650
651 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000652
653 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
654 return &Printer;
655 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000656
657 // Calls.
658
659 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000660 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000661 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000662 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000663 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000664
Ted Kremenek85348202008-04-15 23:44:31 +0000665 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
666 GRExprEngine& Engine,
667 GRStmtNodeBuilder<ValueState>& Builder,
668 ObjCMessageExpr* ME,
669 ExplodedNode<ValueState>* Pred);
670
671 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
672 GRExprEngine& Engine,
673 GRStmtNodeBuilder<ValueState>& Builder,
674 ObjCMessageExpr* ME,
675 ExplodedNode<ValueState>* Pred);
676
Ted Kremenek13922612008-04-16 20:40:59 +0000677 // Stores.
678
679 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
680 GRExprEngine& Engine,
681 GRStmtNodeBuilder<ValueState>& Builder,
682 Expr* E, ExplodedNode<ValueState>* Pred,
683 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000684 // End-of-path.
685
686 virtual void EvalEndPath(GRExprEngine& Engine,
687 GREndPathNodeBuilder<ValueState>& Builder);
688
Ted Kremenek652adc62008-04-24 23:57:27 +0000689 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
690 GRExprEngine& Engine,
691 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +0000692 ExplodedNode<ValueState>* Pred,
693 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +0000694 ValueState* St,
695 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +0000696 // Return statements.
697
698 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
699 GRExprEngine& Engine,
700 GRStmtNodeBuilder<ValueState>& Builder,
701 ReturnStmt* S,
702 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +0000703
704 // Assumptions.
705
706 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
707 RVal Cond, bool Assumption, bool& isFeasible);
708
Ted Kremenekfa34b332008-04-09 01:10:13 +0000709 // Error iterators.
710
711 typedef UseAfterReleasesTy::iterator use_after_iterator;
712 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000713 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000714
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000715 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
716 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000717
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000718 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
719 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000720
721 leaks_iterator leaks_begin() { return Leaks.begin(); }
722 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000723};
724
725} // end anonymous namespace
726
Ted Kremenek8dd56462008-04-18 03:39:05 +0000727
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000728
729
Ted Kremenekf3948042008-03-11 19:44:10 +0000730void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
731 void* State, const char* nl,
732 const char* sep) {
733 RefBindings B((RefBindings::TreeTy*) State);
734
735 if (State)
736 Out << sep << nl;
737
738 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
739 Out << (*I).first << " : ";
740 (*I).second.print(Out);
741 Out << nl;
742 }
743}
744
Ted Kremenekf9561e52008-04-11 20:23:24 +0000745static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
746 return Summ ? Summ->getArg(idx) : DoNothing;
747}
748
749static inline RetEffect GetRetE(CFRefSummary* Summ) {
750 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
751}
752
Ted Kremenekdb863712008-04-16 22:32:20 +0000753void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
754 GRStmtNodeBuilder<ValueState>& Builder,
755 Expr* NodeExpr, Expr* ErrorExpr,
756 ExplodedNode<ValueState>* Pred,
757 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000758 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000759 Builder.BuildSinks = true;
760 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
761
762 if (!N) return;
763
764 switch (hasErr) {
765 default: assert(false);
766 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000767 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000768 break;
769
770 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000771 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000772 break;
773 }
774}
775
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000776void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000777 GRExprEngine& Eng,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000778 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000779 CallExpr* CE, RVal L,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000780 ExplodedNode<ValueState>* Pred) {
781
Ted Kremenek199e1a02008-03-12 21:06:49 +0000782 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000783
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000784 CFRefSummary* Summ = NULL;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000785
786 // Get the summary.
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000787
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000788 if (isa<lval::FuncVal>(L)) {
789 lval::FuncVal FV = cast<lval::FuncVal>(L);
790 FunctionDecl* FD = FV.getDecl();
791 Summ = Summaries.getSummary(FD, Eng.getContext());
792 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000793
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000794 // Get the state.
795
796 ValueState* St = Builder.GetState(Pred);
797
798 // Evaluate the effects of the call.
799
800 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000801 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekf9561e52008-04-11 20:23:24 +0000802
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000803 // This function has a summary. Evaluate the effect of the arguments.
804
805 unsigned idx = 0;
806
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000807 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000808 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000809
810 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
811 I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000812
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000813 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000814
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000815 if (isa<lval::SymbolVal>(V)) {
816 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +0000817 RefBindings B = GetRefBindings(StVals);
818
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000819 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000820 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000821 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000822
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000823 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000824 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000825 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000826 break;
827 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000828 }
Ted Kremenekb8873552008-04-11 20:51:02 +0000829 }
830 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
831
832 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
833 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000834 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +0000835 }
Ted Kremeneka5488462008-04-22 21:39:21 +0000836 else if (isa<nonlval::LValAsInteger>(V))
837 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000838 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000839
840 St = StateMgr.getPersistentState(StVals);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000841
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000842 if (hasErr) {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000843 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
844 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000845 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000846 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000847
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000848 // Finally, consult the summary for the return value.
849
Ted Kremenekf9561e52008-04-11 20:23:24 +0000850 RetEffect RE = GetRetE(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000851
852 switch (RE.getKind()) {
853 default:
854 assert (false && "Unhandled RetEffect."); break;
855
Ted Kremenek940b1d82008-04-10 23:44:06 +0000856 case RetEffect::NoRet:
Ted Kremenekf9561e52008-04-11 20:23:24 +0000857
858 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +0000859 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
860 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000861
862 if (CE->getType() != Eng.getContext().VoidTy) {
863 unsigned Count = Builder.getCurrentBlockCount();
864 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
865
866 RVal X = CE->getType()->isPointerType()
867 ? cast<RVal>(lval::SymbolVal(Sym))
868 : cast<RVal>(nonlval::SymbolVal(Sym));
869
870 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
871 }
872
Ted Kremenek940b1d82008-04-10 23:44:06 +0000873 break;
874
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000875 case RetEffect::Alias: {
876 unsigned idx = RE.getValue();
877 assert (idx < CE->getNumArgs());
878 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenek199e1a02008-03-12 21:06:49 +0000879 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000880 break;
881 }
882
883 case RetEffect::OwnedSymbol: {
884 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000885 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000886
887 ValueState StImpl = *St;
888 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000889 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000890
891 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
892 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000893 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000894
895 break;
896 }
897
898 case RetEffect::NotOwnedSymbol: {
899 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000900 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000901
902 ValueState StImpl = *St;
903 RefBindings B = GetRefBindings(StImpl);
904 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
905
906 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
907 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000908 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000909
910 break;
911 }
912 }
913
Ted Kremenek0e561a32008-03-21 21:30:14 +0000914 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000915}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000916
Ted Kremenek85348202008-04-15 23:44:31 +0000917
918void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
919 GRExprEngine& Eng,
920 GRStmtNodeBuilder<ValueState>& Builder,
921 ObjCMessageExpr* ME,
922 ExplodedNode<ValueState>* Pred) {
923
924 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
925 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
926}
927
928bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
929 GRExprEngine& Eng,
930 GRStmtNodeBuilder<ValueState>& Builder,
931 ObjCMessageExpr* ME,
932 ExplodedNode<ValueState>* Pred) {
933
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000934 // Handle "toll-free bridging" of calls to "Release" and "Retain".
935
936 // FIXME: track the underlying object type associated so that we can
937 // flag illegal uses of toll-free bridging (or at least handle it
938 // at casts).
Ted Kremenek85348202008-04-15 23:44:31 +0000939
940 Selector S = ME->getSelector();
941
942 if (!S.isUnarySelector())
943 return true;
944
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000945 Expr* Receiver = ME->getReceiver();
946
947 if (!Receiver)
948 return true;
949
950 // Check if we are calling "Retain" or "Release".
951
952 bool isRetain = false;
953
954 if (S == RetainSelector)
955 isRetain = true;
956 else if (S != ReleaseSelector)
957 return true;
958
959 // We have "Retain" or "Release". Get the reference binding.
960
961 ValueStateManager& StateMgr = Eng.getStateManager();
962 ValueState* St = Builder.GetState(Pred);
963 RVal V = StateMgr.GetRVal(St, Receiver);
964
965 if (!isa<lval::SymbolVal>(V))
966 return true;
967
968 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
969 RefBindings B = GetRefBindings(*St);
970
971 RefBindings::TreeTy* T = B.SlimFind(Sym);
972
973 if (!T)
974 return true;
975
976 RefVal::Kind hasErr = (RefVal::Kind) 0;
977 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
978
979 // Create a new state with the updated bindings.
980
981 ValueState StVals = *St;
982 SetRefBindings(StVals, B);
983 St = StateMgr.getPersistentState(StVals);
984
985 // Create an error node if it exists.
986
987 if (hasErr)
Ted Kremenek8dd56462008-04-18 03:39:05 +0000988 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000989 else
990 Builder.MakeNode(Dst, ME, Pred, St);
991
992 return false;
Ted Kremenek85348202008-04-15 23:44:31 +0000993}
994
Ted Kremenek13922612008-04-16 20:40:59 +0000995// Stores.
996
997void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
998 GRExprEngine& Eng,
999 GRStmtNodeBuilder<ValueState>& Builder,
1000 Expr* E, ExplodedNode<ValueState>* Pred,
1001 ValueState* St, RVal TargetLV, RVal Val) {
1002
1003 // Check if we have a binding for "Val" and if we are storing it to something
1004 // we don't understand or otherwise the value "escapes" the function.
1005
1006 if (!isa<lval::SymbolVal>(Val))
1007 return;
1008
1009 // Are we storing to something that causes the value to "escape"?
1010
1011 bool escapes = false;
1012
1013 if (!isa<lval::DeclVal>(TargetLV))
1014 escapes = true;
1015 else
1016 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1017
1018 if (!escapes)
1019 return;
1020
1021 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1022 RefBindings B = GetRefBindings(*St);
1023 RefBindings::TreeTy* T = B.SlimFind(Sym);
1024
1025 if (!T)
1026 return;
1027
Ted Kremenekdb863712008-04-16 22:32:20 +00001028 // Nuke the binding.
1029 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001030
1031 // Hand of the remaining logic to the parent implementation.
1032 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1033}
1034
Ted Kremenekdb863712008-04-16 22:32:20 +00001035
1036ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1037 SymbolID sid) {
1038 ValueState StImpl = *St;
1039 RefBindings B = GetRefBindings(StImpl);
1040 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1041 return VMgr.getPersistentState(StImpl);
1042}
1043
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001044// End-of-path.
1045
Ted Kremenekdb863712008-04-16 22:32:20 +00001046ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1047 ValueState* St, SymbolID sid,
1048 RefVal V, bool& hasLeak) {
1049
Ted Kremenek4fd88972008-04-17 18:12:53 +00001050 hasLeak = V.isOwned() ||
1051 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001052
1053 if (!hasLeak)
1054 return NukeBinding(VMgr, St, sid);
1055
1056 RefBindings B = GetRefBindings(*St);
1057 ValueState StImpl = *St;
1058 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1059 return VMgr.getPersistentState(StImpl);
1060}
1061
1062void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001063 GREndPathNodeBuilder<ValueState>& Builder) {
1064
Ted Kremenekdb863712008-04-16 22:32:20 +00001065 ValueState* St = Builder.getState();
1066 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001067
Ted Kremenekdb863712008-04-16 22:32:20 +00001068 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001069
Ted Kremenekdb863712008-04-16 22:32:20 +00001070 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1071 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001072
Ted Kremenekdb863712008-04-16 22:32:20 +00001073 St = HandleSymbolDeath(Eng.getStateManager(), St,
1074 (*I).first, (*I).second, hasLeak);
1075
1076 if (hasLeak) Leaked.push_back((*I).first);
1077 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001078
1079 if (Leaked.empty())
1080 return;
1081
Ted Kremenek8dd56462008-04-18 03:39:05 +00001082 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001083
Ted Kremenek652adc62008-04-24 23:57:27 +00001084 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001085 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001086
Ted Kremenek8dd56462008-04-18 03:39:05 +00001087 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1088 assert (!LeaksAtNode);
1089 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001090
1091 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1092 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001093 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001094}
1095
Ted Kremenek652adc62008-04-24 23:57:27 +00001096// Dead symbols.
1097
1098void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1099 GRExprEngine& Eng,
1100 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001101 ExplodedNode<ValueState>* Pred,
1102 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001103 ValueState* St,
1104 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001105
Ted Kremenek652adc62008-04-24 23:57:27 +00001106 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1107
1108 RefBindings B = GetRefBindings(*St);
1109 llvm::SmallVector<SymbolID, 10> Leaked;
1110
1111 for (ValueStateManager::DeadSymbolsTy::const_iterator
1112 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1113
1114 RefBindings::TreeTy* T = B.SlimFind(*I);
1115
1116 if (!T)
1117 continue;
1118
1119 bool hasLeak = false;
1120
1121 St = HandleSymbolDeath(Eng.getStateManager(), St,
1122 *I, T->getValue().second, hasLeak);
1123
1124 if (hasLeak) Leaked.push_back(*I);
1125 }
1126
1127 if (Leaked.empty())
1128 return;
1129
1130 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1131
1132 if (!N)
1133 return;
1134
1135 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1136 assert (!LeaksAtNode);
1137 LeaksAtNode = new std::vector<SymbolID>();
1138
1139 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1140 E = Leaked.end(); I != E; ++I)
1141 (*LeaksAtNode).push_back(*I);
1142}
1143
Ted Kremenek4fd88972008-04-17 18:12:53 +00001144 // Return statements.
1145
1146void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1147 GRExprEngine& Eng,
1148 GRStmtNodeBuilder<ValueState>& Builder,
1149 ReturnStmt* S,
1150 ExplodedNode<ValueState>* Pred) {
1151
1152 Expr* RetE = S->getRetValue();
1153 if (!RetE) return;
1154
1155 ValueStateManager& StateMgr = Eng.getStateManager();
1156 ValueState* St = Builder.GetState(Pred);
1157 RVal V = StateMgr.GetRVal(St, RetE);
1158
1159 if (!isa<lval::SymbolVal>(V))
1160 return;
1161
1162 // Get the reference count binding (if any).
1163 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1164 RefBindings B = GetRefBindings(*St);
1165 RefBindings::TreeTy* T = B.SlimFind(Sym);
1166
1167 if (!T)
1168 return;
1169
1170 // Change the reference count.
1171
1172 RefVal X = T->getValue().second;
1173
1174 switch (X.getKind()) {
1175
1176 case RefVal::Owned: {
1177 unsigned cnt = X.getCount();
1178 X = RefVal::makeReturnedOwned(cnt);
1179 break;
1180 }
1181
1182 case RefVal::NotOwned: {
1183 unsigned cnt = X.getCount();
1184 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1185 : RefVal::makeReturnedNotOwned();
1186 break;
1187 }
1188
1189 default:
1190 // None of the error states should be possible at this point.
1191 // A symbol could not have been leaked (yet) if we are returning it
1192 // (and thus it is still live), and the other errors are hard errors.
1193 assert(false);
1194 return;
1195 }
1196
1197 // Update the binding.
1198
1199 ValueState StImpl = *St;
1200 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1201 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1202}
1203
Ted Kremenekcb612922008-04-18 19:23:43 +00001204// Assumptions.
1205
1206ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1207 RVal Cond, bool Assumption,
1208 bool& isFeasible) {
1209
1210 // FIXME: We may add to the interface of EvalAssume the list of symbols
1211 // whose assumptions have changed. For now we just iterate through the
1212 // bindings and check if any of the tracked symbols are NULL. This isn't
1213 // too bad since the number of symbols we will track in practice are
1214 // probably small and EvalAssume is only called at branches and a few
1215 // other places.
1216
1217 RefBindings B = GetRefBindings(*St);
1218
1219 if (B.isEmpty())
1220 return St;
1221
1222 bool changed = false;
1223
1224 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1225
1226 // Check if the symbol is null (or equal to any constant).
1227 // If this is the case, stop tracking the symbol.
1228
1229 if (St->getSymVal(I.getKey())) {
1230 changed = true;
1231 B = RefBFactory.Remove(B, I.getKey());
1232 }
1233 }
1234
1235 if (!changed)
1236 return St;
1237
1238 ValueState StImpl = *St;
1239 StImpl.CheckerState = B.getRoot();
1240 return Eng.getStateManager().getPersistentState(StImpl);
1241}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001242
1243CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001244 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001245 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001246
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001247 // FIXME: This dispatch can potentially be sped up by unifiying it into
1248 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001249
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001250 switch (E) {
1251 default:
1252 assert (false && "Unhandled CFRef transition.");
1253
1254 case DoNothing:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001255 if (V.getKind() == RefVal::Released) {
1256 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001257 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001258 break;
1259 }
1260
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001261 return B;
1262
1263 case IncRef:
1264 switch (V.getKind()) {
1265 default:
1266 assert(false);
1267
1268 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001269 V = RefVal::makeOwned(V.getCount()+1);
1270 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001271
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001272 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001273 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001274 break;
1275
1276 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001277 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001278 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001279 break;
1280 }
1281
Ted Kremenek940b1d82008-04-10 23:44:06 +00001282 break;
1283
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001284 case DecRef:
1285 switch (V.getKind()) {
1286 default:
1287 assert (false);
1288
1289 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001290 unsigned Count = V.getCount();
1291 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001292 break;
1293 }
1294
Ted Kremenek61b9f872008-04-10 23:09:18 +00001295 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001296 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001297
Ted Kremenek4fd88972008-04-17 18:12:53 +00001298 if (Count > 0)
1299 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001300 else {
1301 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001302 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001303 }
1304
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001305 break;
1306 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001307
1308 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001309 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001310 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001311 break;
1312 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001313
1314 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001315 }
1316
1317 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001318}
1319
Ted Kremenekfa34b332008-04-09 01:10:13 +00001320
1321//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001322// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001323//===----------------------------------------------------------------------===//
1324
Ted Kremenek8dd56462008-04-18 03:39:05 +00001325namespace {
1326
1327 //===-------------===//
1328 // Bug Descriptions. //
1329 //===-------------===//
1330
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001331 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001332 protected:
1333 CFRefCount& TF;
1334
1335 public:
1336 CFRefBug(CFRefCount& tf) : TF(tf) {}
1337 };
1338
1339 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1340 public:
1341 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1342
1343 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001344 return "Core Foundation: Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001345 }
1346 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001347 return "Reference-counted object is used"
1348 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001349 }
1350
1351 virtual void EmitWarnings(BugReporter& BR);
1352
1353 };
1354
1355 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1356 public:
1357 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1358
1359 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001360 return "Core Foundation: Release of non-owned object";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001361 }
1362 virtual const char* getDescription() const {
1363 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001364 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001365 "The object is not owned at this point by the caller.";
1366 }
1367
1368 virtual void EmitWarnings(BugReporter& BR);
1369 };
1370
1371 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1372 public:
1373 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1374
1375 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001376 return "Core Foundation: Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001377 }
1378
1379 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001380 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001381 }
1382
1383 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekcb612922008-04-18 19:23:43 +00001384 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001385 };
1386
1387 //===---------===//
1388 // Bug Reports. //
1389 //===---------===//
1390
1391 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1392 SymbolID Sym;
1393 public:
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001394 CFRefReport(BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001395 : RangedBugReport(D, n), Sym(sym) {}
1396
1397 virtual ~CFRefReport() {}
1398
1399
1400 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1401 ExplodedNode<ValueState>* PrevN,
1402 ExplodedGraph<ValueState>& G,
1403 BugReporter& BR);
1404 };
1405
1406
1407} // end anonymous namespace
1408
1409void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1410 GRSimpleVals::RegisterChecks(Eng);
1411 Eng.Register(new UseAfterRelease(*this));
1412 Eng.Register(new BadRelease(*this));
1413 Eng.Register(new Leak(*this));
1414}
1415
1416PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1417 ExplodedNode<ValueState>* PrevN,
1418 ExplodedGraph<ValueState>& G,
1419 BugReporter& BR) {
1420
1421 // Check if the type state has changed.
1422
1423 ValueState* PrevSt = PrevN->getState();
1424 ValueState* CurrSt = N->getState();
1425
1426 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1427 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1428
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001429 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1430 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001431
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001432 if (!CurrT)
1433 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001434
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001435 const char* Msg = NULL;
1436 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001437
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001438 if (!PrevT) {
1439
1440 // Check for the point where we start tracking the value.
1441
1442 if (CurrV.isOwned())
1443 Msg = "Function call returns 'Owned' Core Foundation object.";
1444 else {
1445 assert (CurrV.isNotOwned());
1446 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1447 }
1448
1449 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1450 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1451 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1452
1453 if (Expr* Exp = dyn_cast<Expr>(S))
1454 P->addRange(Exp->getSourceRange());
1455
1456 return P;
1457 }
1458
1459 // Determine if the typestate has changed.
1460
1461 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1462
1463 if (PrevV == CurrV)
1464 return NULL;
1465
1466 // The typestate has changed.
1467
1468 std::ostringstream os;
1469
1470 switch (CurrV.getKind()) {
1471 case RefVal::Owned:
1472 case RefVal::NotOwned:
1473 assert (PrevV.getKind() == CurrV.getKind());
1474
1475 if (PrevV.getCount() > CurrV.getCount())
1476 os << "Reference count decremented.";
1477 else
1478 os << "Reference count incremented.";
1479
Ted Kremenek79c140b2008-04-18 05:32:44 +00001480 if (CurrV.getCount()) {
1481 os << " Object has +" << CurrV.getCount();
1482
1483 if (CurrV.getCount() > 1)
1484 os << " reference counts.";
1485 else
1486 os << " reference count.";
1487 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001488
1489 Msg = os.str().c_str();
1490
1491 break;
1492
1493 case RefVal::Released:
1494 Msg = "Object released.";
1495 break;
1496
1497 case RefVal::ReturnedOwned:
1498 Msg = "Object returned to caller. "
1499 "Caller gets ownership of object.";
1500 break;
1501
1502 case RefVal::ReturnedNotOwned:
1503 Msg = "Object returned to caller. "
1504 "Caller does not get ownership of object.";
1505 break;
1506
1507 default:
1508 return NULL;
1509 }
1510
1511 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1512 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1513 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1514
1515 // Add the range by scanning the children of the statement for any bindings
1516 // to Sym.
1517
1518 ValueStateManager& VSM = BR.getEngine().getStateManager();
1519
1520 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1521 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1522 RVal X = VSM.GetRVal(CurrSt, Exp);
1523
1524 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1525 if (SV->getSymbol() == Sym) {
1526 P->addRange(Exp->getSourceRange()); break;
1527 }
1528 }
1529
1530 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001531}
1532
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001533void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001534
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001535 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1536 E = TF.use_after_end(); I != E; ++I) {
1537
Ted Kremenek8dd56462008-04-18 03:39:05 +00001538 CFRefReport report(*this, I->first, I->second.second);
1539 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00001540 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001541 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001542}
1543
1544void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001545
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001546 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1547 E = TF.bad_release_end(); I != E; ++I) {
1548
Ted Kremenek8dd56462008-04-18 03:39:05 +00001549 CFRefReport report(*this, I->first, I->second.second);
1550 report.addRange(I->second.first->getSourceRange());
1551 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001552 }
1553}
Ted Kremenekfa34b332008-04-09 01:10:13 +00001554
Ted Kremenek989d5192008-04-17 23:43:50 +00001555void Leak::EmitWarnings(BugReporter& BR) {
1556
1557 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1558 E = TF.leaks_end(); I != E; ++I) {
1559
Ted Kremenek8dd56462008-04-18 03:39:05 +00001560 std::vector<SymbolID>& SymV = *(I->second);
1561 unsigned n = SymV.size();
1562
1563 for (unsigned i = 0; i < n; ++i) {
1564 CFRefReport report(*this, I->first, SymV[i]);
1565 BR.EmitWarning(report);
1566 }
Ted Kremenek989d5192008-04-17 23:43:50 +00001567 }
1568}
1569
Ted Kremenekcb612922008-04-18 19:23:43 +00001570void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1571 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1572 I!=E; ++I)
1573 Nodes.push_back(I->first);
1574}
1575
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001576//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00001577// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001578//===----------------------------------------------------------------------===//
1579
Ted Kremeneke5c30122008-04-29 05:13:59 +00001580GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled) {
1581 return new CFRefCount(Ctx, GCEnabled);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00001582}