blob: b1936fd631f0abb5e7b896d5a5e0cc193c91b000 [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 Kremenek072192b2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000017#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000018#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000019#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000020#include "clang/Analysis/PathDiagnostic.h"
21#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000022#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/FoldingSet.h"
24#include "llvm/ADT/ImmutableMap.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000025#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000026#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000027#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000028
29using namespace clang;
30
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000031//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-04-17 18:12:53 +000032// Utility functions.
33//===----------------------------------------------------------------------===//
34
35static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
36 IdentifierInfo* II = &Ctx.Idents.get(name);
37 return Ctx.Selectors.getSelector(0, &II);
38}
39
40//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000041// Symbolic Evaluation of Reference Counting Logic
42//===----------------------------------------------------------------------===//
43
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000044namespace {
45 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenek891d5cc2008-04-24 17:22:33 +000046 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000047}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000048
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000049namespace llvm {
50 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000051 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +000052 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
53 ID.AddInteger(I->first);
54 ID.AddInteger((unsigned) I->second);
55 }
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000056 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000057 };
58} // end llvm namespace
59
60namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +000061
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000062class RetEffect {
63public:
Ted Kremenek940b1d82008-04-10 23:44:06 +000064 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
65 NotOwnedSymbol = 0x3 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000066
67private:
68 unsigned Data;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000069 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000070
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000071public:
72
73 Kind getKind() const { return (Kind) (Data & 0x3); }
74
75 unsigned getValue() const {
76 assert(getKind() == Alias);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000077 return Data >> 2;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000078 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +000079
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000080 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000081
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000082 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000083
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000084 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
85
Ted Kremenek940b1d82008-04-10 23:44:06 +000086 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
87
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000088 operator Kind() const { return getKind(); }
89
90 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
91};
92
93
94class CFRefSummary : public llvm::FoldingSetNode {
95 ArgEffects* Args;
96 RetEffect Ret;
97public:
98
99 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
100
101 unsigned getNumArgs() const { return Args->size(); }
102
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000103 ArgEffect getArg(unsigned idx) const {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000104 if (!Args)
105 return DoNothing;
106
107 // If Args is present, it is likely to contain only 1 element.
108 // Just do a linear search. Do it from the back because functions with
109 // large numbers of arguments will be tail heavy with respect to which
110 // argument they actually modify with respect to the reference count.
111
112 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
113 I!=E; ++I) {
114
115 if (idx > I->first)
116 return DoNothing;
117
118 if (idx == I->first)
119 return I->second;
120 }
121
122 return DoNothing;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000123 }
124
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000125 RetEffect getRet() const {
126 return Ret;
127 }
128
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000129 typedef ArgEffects::const_iterator arg_iterator;
130
131 arg_iterator begin_args() const { return Args->begin(); }
132 arg_iterator end_args() const { return Args->end(); }
133
134 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
135 ID.AddPointer(A);
136 ID.Add(R);
137 }
138
139 void Profile(llvm::FoldingSetNodeID& ID) const {
140 Profile(ID, Args, Ret);
141 }
142};
143
144
145class CFRefSummaryManager {
146 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
147 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
148 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
149
Ted Kremenek377e2302008-04-29 05:33:51 +0000150 ASTContext& Ctx;
151 const bool GCEnabled;
152
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000153 SummarySetTy SummarySet;
154 SummaryMapTy SummaryMap;
155 AESetTy AESet;
156 llvm::BumpPtrAllocator BPAlloc;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000157 ArgEffects ScratchArgs;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000158
159 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000160
Ted Kremenek377e2302008-04-29 05:33:51 +0000161 enum CFUnaryFunc { cfretain, cfrelease, cfmakecollectable };
162 CFRefSummary* getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func);
163
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000164 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
165
166 CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
167 CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);
168
169 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000170
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000171public:
Ted Kremenek377e2302008-04-29 05:33:51 +0000172 CFRefSummaryManager(ASTContext& ctx, bool gcenabled)
173 : Ctx(ctx), GCEnabled(gcenabled) {}
174
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000175 ~CFRefSummaryManager();
176
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000177 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000178};
179
180} // end anonymous namespace
181
182//===----------------------------------------------------------------------===//
183// Implementation of checker data structures.
184//===----------------------------------------------------------------------===//
185
186CFRefSummaryManager::~CFRefSummaryManager() {
187
188 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
189 // mitigating the need to do explicit cleanup of the
190 // Argument-Effect summaries.
191
192 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
193 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000194}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000195
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000196ArgEffects* CFRefSummaryManager::getArgEffects() {
197
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000198 if (ScratchArgs.empty())
199 return NULL;
200
201 // Compute a profile for a non-empty ScratchArgs.
202
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000203 llvm::FoldingSetNodeID profile;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000204
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000205 profile.Add(ScratchArgs);
206 void* InsertPos;
207
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000208 // Look up the uniqued copy, or create a new one.
209
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000210 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
211 AESet.FindNodeOrInsertPos(profile, InsertPos);
212
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000213 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000214 ScratchArgs.clear();
215 return &E->getValue();
216 }
217
218 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
219 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
220
221 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
222 AESet.InsertNode(E, InsertPos);
223
224 ScratchArgs.clear();
225 return &E->getValue();
226}
227
228CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
229 RetEffect RE) {
230
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000231 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000232 llvm::FoldingSetNodeID profile;
233 CFRefSummary::Profile(profile, AE, RE);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000234
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000235 // Look up the uniqued summary, or create one if it doesn't exist.
236 void* InsertPos;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000237 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
238
239 if (Summ)
240 return Summ;
241
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000242 // Create the summary and return it.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000243 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
244 new (Summ) CFRefSummary(AE, RE);
245 SummarySet.InsertNode(Summ, InsertPos);
246
247 return Summ;
248}
249
250
251CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
252 ASTContext& Ctx) {
253
254 SourceLocation Loc = FD->getLocation();
255
256 if (!Loc.isFileID())
257 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000258
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000259
260 // Look up a summary in our cache of FunctionDecls -> Summaries.
261 SummaryMapTy::iterator I = SummaryMap.find(FD);
262
263 if (I != SummaryMap.end())
264 return I->second;
265
266 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000267 const char* FName = FD->getIdentifier()->getName();
268
269 if (FName[0] == 'C' && FName[1] == 'F') {
270 CFRefSummary* S = getCFSummary(FD, FName);
271 SummaryMap[FD] = S;
272 return S;
273 }
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000274
275 // Function has no ref-count effects. Return the NULL summary.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000276 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000277}
278
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000279CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
280 const char* FName) {
281
282 // For now, only generate summaries for functions that have a prototype.
283
284 FunctionTypeProto* FT =
285 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
286
287 if (!FT)
288 return NULL;
289
290 FName += 2;
291
292 if (strcmp(FName, "Retain") == 0)
Ted Kremenek377e2302008-04-29 05:33:51 +0000293 return getUnaryCFSummary(FT, cfretain);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000294
295 if (strcmp(FName, "Release") == 0)
Ted Kremenek377e2302008-04-29 05:33:51 +0000296 return getUnaryCFSummary(FT, cfrelease);
297
298 if (strcmp(FName, "MakeCollectable") == 0)
299 return getUnaryCFSummary(FT, cfmakecollectable);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000300
301 assert (ScratchArgs.empty());
302 bool usesCreateRule = false;
303
304 if (strstr(FName, "Create"))
305 usesCreateRule = true;
306
307 if (!usesCreateRule && strstr(FName, "Copy"))
308 usesCreateRule = true;
309
310 if (usesCreateRule)
311 return getCFSummaryCreateRule(FT);
312
313 if (strstr(FName, "Get"))
314 return getCFSummaryGetRule(FT);
315
316 return NULL;
317}
318
Ted Kremenek377e2302008-04-29 05:33:51 +0000319CFRefSummary*
320CFRefSummaryManager::getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000321
322 if (FT->getNumArgs() != 1)
323 return NULL;
324
325 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
326
327 if (!ArgT)
328 return NULL;
329
330 // For CFRetain/CFRelease, the first (and only) argument is of type
331 // "CFTypeRef".
332
333 const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
334 assert (TDName);
335
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000336 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000337 return NULL;
338
Ted Kremenekc0c3f5d2008-04-30 20:17:27 +0000339 if (!ArgT->isPointerType())
340 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000341
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000342 QualType RetTy = FT->getResultType();
343
Ted Kremenek377e2302008-04-29 05:33:51 +0000344 switch (func) {
345 case cfretain: {
346
347 // CFRetain: the return type should also be "CFTypeRef".
348 if (RetTy.getTypePtr() != ArgT)
349 return NULL;
350
351 // The function's interface checks out. Generate a canned summary.
352 assert (ScratchArgs.empty());
353 ScratchArgs.push_back(std::make_pair(0, IncRef));
354 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
355 }
356
357 case cfrelease: {
358
359 // CFRelease: the return type should be void.
360
361 if (RetTy != Ctx.VoidTy)
362 return NULL;
363
364 assert (ScratchArgs.empty());
365 ScratchArgs.push_back(std::make_pair(0, DecRef));
366 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
367 }
368
369 case cfmakecollectable: {
370
371 // CFRetain: the return type should also be "CFTypeRef".
372 if (RetTy.getTypePtr() != ArgT)
373 return NULL;
374
375 // The function's interface checks out. Generate a canned summary.
376 assert (ScratchArgs.empty());
377
378 if (GCEnabled)
379 ScratchArgs.push_back(std::make_pair(0, DecRef));
380
381 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
382
383
384 }
385
386 default:
387 assert (false && "Not a support unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000388 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000389}
390
391static bool isCFRefType(QualType T) {
392
393 if (!T->isPointerType())
394 return false;
395
396 // Check the typedef for the name "CF" and the substring "Ref".
397
398 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
399
400 if (!TD)
401 return false;
402
403 const char* TDName = TD->getDecl()->getIdentifier()->getName();
404 assert (TDName);
405
406 if (TDName[0] != 'C' || TDName[1] != 'F')
407 return false;
408
409 if (strstr(TDName, "Ref") == 0)
410 return false;
411
412 return true;
413}
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000414
415CFRefSummary*
416CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
417
418 if (!isCFRefType(FT->getResultType()))
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000419 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000420
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000421 // FIXME: Add special-cases for functions that retain/release. For now
422 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000423
424 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000425 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
426}
427
428CFRefSummary*
429CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
430
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000431 QualType RetTy = FT->getResultType();
432
433 // FIXME: For now we assume that all pointer types returned are referenced
434 // counted. Since this is the "Get" rule, we assume non-ownership, which
435 // works fine for things that are not reference counted. We do this because
436 // some generic data structures return "void*". We need something better
437 // in the future.
438
439 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
440 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000441
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000442 // FIXME: Add special-cases for functions that retain/release. For now
443 // just handle the default case.
444
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000445 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000446 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
447}
448
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000449//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000450// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000451//===----------------------------------------------------------------------===//
452
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000453namespace {
454
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000455class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000456public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000457
Ted Kremenek4fd88972008-04-17 18:12:53 +0000458 enum Kind {
459 Owned = 0, // Owning reference.
460 NotOwned, // Reference is not owned by still valid (not freed).
461 Released, // Object has been released.
462 ReturnedOwned, // Returned object passes ownership to caller.
463 ReturnedNotOwned, // Return object does not pass ownership to caller.
464 ErrorUseAfterRelease, // Object used after released.
465 ErrorReleaseNotOwned, // Release of an object that was not owned.
466 ErrorLeak // A memory leak due to excessive reference counts.
467 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000468
Ted Kremenek4fd88972008-04-17 18:12:53 +0000469private:
470
471 Kind kind;
472 unsigned Cnt;
473
474 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
475
476 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000477
478public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000479
Ted Kremenek4fd88972008-04-17 18:12:53 +0000480 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000481
Ted Kremenek4fd88972008-04-17 18:12:53 +0000482 unsigned getCount() const { return Cnt; }
483
484 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000485
Ted Kremenek73c750b2008-03-11 18:14:09 +0000486 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
487
Ted Kremenekdb863712008-04-16 22:32:20 +0000488 static bool isLeak(Kind k) { return k == ErrorLeak; }
489
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000490 bool isOwned() const {
491 return getKind() == Owned;
492 }
493
Ted Kremenekdb863712008-04-16 22:32:20 +0000494 bool isNotOwned() const {
495 return getKind() == NotOwned;
496 }
497
Ted Kremenek4fd88972008-04-17 18:12:53 +0000498 bool isReturnedOwned() const {
499 return getKind() == ReturnedOwned;
500 }
501
502 bool isReturnedNotOwned() const {
503 return getKind() == ReturnedNotOwned;
504 }
505
506 bool isNonLeakError() const {
507 Kind k = getKind();
508 return isError(k) && !isLeak(k);
509 }
510
511 // State creation: normal state.
512
Ted Kremenek61b9f872008-04-10 23:09:18 +0000513 static RefVal makeOwned(unsigned Count = 0) {
514 return RefVal(Owned, Count);
515 }
516
517 static RefVal makeNotOwned(unsigned Count = 0) {
518 return RefVal(NotOwned, Count);
519 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000520
521 static RefVal makeReturnedOwned(unsigned Count) {
522 return RefVal(ReturnedOwned, Count);
523 }
524
525 static RefVal makeReturnedNotOwned() {
526 return RefVal(ReturnedNotOwned);
527 }
528
529 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000530
Ted Kremenekdb863712008-04-16 22:32:20 +0000531 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000532 static RefVal makeReleased() { return RefVal(Released); }
533 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
534 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000535
536 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000537
Ted Kremenek4fd88972008-04-17 18:12:53 +0000538 bool operator==(const RefVal& X) const {
539 return kind == X.kind && Cnt == X.Cnt;
540 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000541
Ted Kremenek4fd88972008-04-17 18:12:53 +0000542 void Profile(llvm::FoldingSetNodeID& ID) const {
543 ID.AddInteger((unsigned) kind);
544 ID.AddInteger(Cnt);
545 }
546
Ted Kremenekf3948042008-03-11 19:44:10 +0000547 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000548};
Ted Kremenekf3948042008-03-11 19:44:10 +0000549
550void RefVal::print(std::ostream& Out) const {
551 switch (getKind()) {
552 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000553 case Owned: {
554 Out << "Owned";
555 unsigned cnt = getCount();
556 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000557 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000558 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000559
Ted Kremenek61b9f872008-04-10 23:09:18 +0000560 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000561 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000562 unsigned cnt = getCount();
563 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000564 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000565 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000566
Ted Kremenek4fd88972008-04-17 18:12:53 +0000567 case ReturnedOwned: {
568 Out << "ReturnedOwned";
569 unsigned cnt = getCount();
570 if (cnt) Out << " (+ " << cnt << ")";
571 break;
572 }
573
574 case ReturnedNotOwned: {
575 Out << "ReturnedNotOwned";
576 unsigned cnt = getCount();
577 if (cnt) Out << " (+ " << cnt << ")";
578 break;
579 }
580
Ted Kremenekf3948042008-03-11 19:44:10 +0000581 case Released:
582 Out << "Released";
583 break;
584
Ted Kremenekdb863712008-04-16 22:32:20 +0000585 case ErrorLeak:
586 Out << "Leaked";
587 break;
588
Ted Kremenekf3948042008-03-11 19:44:10 +0000589 case ErrorUseAfterRelease:
590 Out << "Use-After-Release [ERROR]";
591 break;
592
593 case ErrorReleaseNotOwned:
594 Out << "Release of Not-Owned [ERROR]";
595 break;
596 }
597}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000598
Ted Kremenek13922612008-04-16 20:40:59 +0000599//===----------------------------------------------------------------------===//
600// Transfer functions.
601//===----------------------------------------------------------------------===//
602
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000603class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000604public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000605 // Type definitions.
606
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000607 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000608 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000609
Ted Kremenek8dd56462008-04-18 03:39:05 +0000610 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
611 ReleasesNotOwnedTy;
612
613 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
614
615 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000616 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000617
Ted Kremenekf3948042008-03-11 19:44:10 +0000618 class BindingsPrinter : public ValueState::CheckerStatePrinter {
619 public:
620 virtual void PrintCheckerState(std::ostream& Out, void* State,
621 const char* nl, const char* sep);
622 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000623
624private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000625 // Instance variables.
626
Ted Kremeneke5c30122008-04-29 05:13:59 +0000627 CFRefSummaryManager Summaries;
Ted Kremenek072192b2008-04-30 23:47:44 +0000628 const bool GCEnabled;
629 const LangOptions& LOpts;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000630 RefBFactoryTy RefBFactory;
631
Ted Kremenek73c750b2008-03-11 18:14:09 +0000632 UseAfterReleasesTy UseAfterReleases;
633 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000634 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000635
Ted Kremenekf3948042008-03-11 19:44:10 +0000636 BindingsPrinter Printer;
637
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000638 Selector RetainSelector;
639 Selector ReleaseSelector;
Ted Kremenek5934cee2008-05-01 02:18:37 +0000640 Selector AutoreleaseSelector;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000641
Ted Kremenek8dd56462008-04-18 03:39:05 +0000642public:
643
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000644 static RefBindings GetRefBindings(ValueState& StImpl) {
645 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
646 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000647
Ted Kremenek8dd56462008-04-18 03:39:05 +0000648private:
649
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000650 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
651 StImpl.CheckerState = B.getRoot();
652 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000653
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000654 RefBindings Remove(RefBindings B, SymbolID sym) {
655 return RefBFactory.Remove(B, sym);
656 }
657
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000658 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000659 RefVal::Kind& hasErr);
660
Ted Kremenekdb863712008-04-16 22:32:20 +0000661 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
662 GRStmtNodeBuilder<ValueState>& Builder,
663 Expr* NodeExpr, Expr* ErrorExpr,
664 ExplodedNode<ValueState>* Pred,
665 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000666 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000667
668 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
669 SymbolID sid, RefVal V, bool& hasLeak);
670
671 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
672 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000673
674public:
Ted Kremenek13922612008-04-16 20:40:59 +0000675
Ted Kremenek072192b2008-04-30 23:47:44 +0000676 CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
Ted Kremenek377e2302008-04-29 05:33:51 +0000677 : Summaries(Ctx, gcenabled),
Ted Kremeneke5c30122008-04-29 05:13:59 +0000678 GCEnabled(gcenabled),
Ted Kremenek072192b2008-04-30 23:47:44 +0000679 LOpts(lopts),
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000680 RetainSelector(GetUnarySelector("retain", Ctx)),
Ted Kremenek5934cee2008-05-01 02:18:37 +0000681 ReleaseSelector(GetUnarySelector("release", Ctx)),
682 AutoreleaseSelector(GetUnarySelector("autorelease", Ctx)) {}
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000683
Ted Kremenek8dd56462008-04-18 03:39:05 +0000684 virtual ~CFRefCount() {
685 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
686 delete I->second;
687 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000688
689 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000690
691 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
692 return &Printer;
693 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000694
Ted Kremenek072192b2008-04-30 23:47:44 +0000695 bool isGCEnabled() const { return GCEnabled; }
696 const LangOptions& getLangOptions() const { return LOpts; }
697
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000698 // Calls.
699
700 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000701 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000702 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000703 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000704 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000705
Ted Kremenek85348202008-04-15 23:44:31 +0000706 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
707 GRExprEngine& Engine,
708 GRStmtNodeBuilder<ValueState>& Builder,
709 ObjCMessageExpr* ME,
710 ExplodedNode<ValueState>* Pred);
711
712 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
713 GRExprEngine& Engine,
714 GRStmtNodeBuilder<ValueState>& Builder,
715 ObjCMessageExpr* ME,
716 ExplodedNode<ValueState>* Pred);
717
Ted Kremenek13922612008-04-16 20:40:59 +0000718 // Stores.
719
720 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
721 GRExprEngine& Engine,
722 GRStmtNodeBuilder<ValueState>& Builder,
723 Expr* E, ExplodedNode<ValueState>* Pred,
724 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000725 // End-of-path.
726
727 virtual void EvalEndPath(GRExprEngine& Engine,
728 GREndPathNodeBuilder<ValueState>& Builder);
729
Ted Kremenek652adc62008-04-24 23:57:27 +0000730 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
731 GRExprEngine& Engine,
732 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +0000733 ExplodedNode<ValueState>* Pred,
734 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +0000735 ValueState* St,
736 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +0000737 // Return statements.
738
739 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
740 GRExprEngine& Engine,
741 GRStmtNodeBuilder<ValueState>& Builder,
742 ReturnStmt* S,
743 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +0000744
745 // Assumptions.
746
747 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
748 RVal Cond, bool Assumption, bool& isFeasible);
749
Ted Kremenekfa34b332008-04-09 01:10:13 +0000750 // Error iterators.
751
752 typedef UseAfterReleasesTy::iterator use_after_iterator;
753 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000754 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000755
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000756 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
757 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000758
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000759 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
760 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000761
762 leaks_iterator leaks_begin() { return Leaks.begin(); }
763 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000764};
765
766} // end anonymous namespace
767
Ted Kremenek8dd56462008-04-18 03:39:05 +0000768
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000769
770
Ted Kremenekf3948042008-03-11 19:44:10 +0000771void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
772 void* State, const char* nl,
773 const char* sep) {
774 RefBindings B((RefBindings::TreeTy*) State);
775
776 if (State)
777 Out << sep << nl;
778
779 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
780 Out << (*I).first << " : ";
781 (*I).second.print(Out);
782 Out << nl;
783 }
784}
785
Ted Kremenekf9561e52008-04-11 20:23:24 +0000786static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
787 return Summ ? Summ->getArg(idx) : DoNothing;
788}
789
790static inline RetEffect GetRetE(CFRefSummary* Summ) {
791 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
792}
793
Ted Kremenekdb863712008-04-16 22:32:20 +0000794void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
795 GRStmtNodeBuilder<ValueState>& Builder,
796 Expr* NodeExpr, Expr* ErrorExpr,
797 ExplodedNode<ValueState>* Pred,
798 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000799 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000800 Builder.BuildSinks = true;
801 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
802
803 if (!N) return;
804
805 switch (hasErr) {
806 default: assert(false);
807 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000808 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000809 break;
810
811 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000812 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000813 break;
814 }
815}
816
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000817void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000818 GRExprEngine& Eng,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000819 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000820 CallExpr* CE, RVal L,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000821 ExplodedNode<ValueState>* Pred) {
822
Ted Kremenek199e1a02008-03-12 21:06:49 +0000823 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000824
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000825 CFRefSummary* Summ = NULL;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000826
827 // Get the summary.
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000828
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000829 if (isa<lval::FuncVal>(L)) {
830 lval::FuncVal FV = cast<lval::FuncVal>(L);
831 FunctionDecl* FD = FV.getDecl();
832 Summ = Summaries.getSummary(FD, Eng.getContext());
833 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000834
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000835 // Get the state.
836
837 ValueState* St = Builder.GetState(Pred);
838
839 // Evaluate the effects of the call.
840
841 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000842 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekf9561e52008-04-11 20:23:24 +0000843
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000844 // This function has a summary. Evaluate the effect of the arguments.
845
846 unsigned idx = 0;
847
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000848 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000849 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000850
851 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
852 I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000853
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000854 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000855
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000856 if (isa<lval::SymbolVal>(V)) {
857 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +0000858 RefBindings B = GetRefBindings(StVals);
859
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000860 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000861 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000862 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000863
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000864 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000865 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000866 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000867 break;
868 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000869 }
Ted Kremenekb8873552008-04-11 20:51:02 +0000870 }
871 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
872
873 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
874 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000875 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +0000876 }
Ted Kremeneka5488462008-04-22 21:39:21 +0000877 else if (isa<nonlval::LValAsInteger>(V))
878 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000879 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000880
881 St = StateMgr.getPersistentState(StVals);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000882
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000883 if (hasErr) {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000884 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
885 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000886 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000887 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000888
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000889 // Finally, consult the summary for the return value.
890
Ted Kremenekf9561e52008-04-11 20:23:24 +0000891 RetEffect RE = GetRetE(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000892
893 switch (RE.getKind()) {
894 default:
895 assert (false && "Unhandled RetEffect."); break;
896
Ted Kremenek940b1d82008-04-10 23:44:06 +0000897 case RetEffect::NoRet:
Ted Kremenekf9561e52008-04-11 20:23:24 +0000898
899 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +0000900 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
901 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000902
903 if (CE->getType() != Eng.getContext().VoidTy) {
904 unsigned Count = Builder.getCurrentBlockCount();
905 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
906
907 RVal X = CE->getType()->isPointerType()
908 ? cast<RVal>(lval::SymbolVal(Sym))
909 : cast<RVal>(nonlval::SymbolVal(Sym));
910
911 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
912 }
913
Ted Kremenek940b1d82008-04-10 23:44:06 +0000914 break;
915
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000916 case RetEffect::Alias: {
917 unsigned idx = RE.getValue();
918 assert (idx < CE->getNumArgs());
919 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenek199e1a02008-03-12 21:06:49 +0000920 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000921 break;
922 }
923
924 case RetEffect::OwnedSymbol: {
925 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000926 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000927
928 ValueState StImpl = *St;
929 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000930 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000931
932 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
933 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000934 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000935
936 break;
937 }
938
939 case RetEffect::NotOwnedSymbol: {
940 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000941 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000942
943 ValueState StImpl = *St;
944 RefBindings B = GetRefBindings(StImpl);
945 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
946
947 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
948 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000949 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000950
951 break;
952 }
953 }
954
Ted Kremenek0e561a32008-03-21 21:30:14 +0000955 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000956}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000957
Ted Kremenek85348202008-04-15 23:44:31 +0000958
959void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
960 GRExprEngine& Eng,
961 GRStmtNodeBuilder<ValueState>& Builder,
962 ObjCMessageExpr* ME,
963 ExplodedNode<ValueState>* Pred) {
964
965 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
966 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
967}
968
969bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
970 GRExprEngine& Eng,
971 GRStmtNodeBuilder<ValueState>& Builder,
972 ObjCMessageExpr* ME,
973 ExplodedNode<ValueState>* Pred) {
Ted Kremenek377e2302008-04-29 05:33:51 +0000974
975 if (GCEnabled)
976 return true;
977
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000978 // Handle "toll-free bridging" of calls to "Release" and "Retain".
979
980 // FIXME: track the underlying object type associated so that we can
981 // flag illegal uses of toll-free bridging (or at least handle it
982 // at casts).
Ted Kremenek85348202008-04-15 23:44:31 +0000983
984 Selector S = ME->getSelector();
985
986 if (!S.isUnarySelector())
987 return true;
988
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000989 Expr* Receiver = ME->getReceiver();
990
991 if (!Receiver)
992 return true;
993
Ted Kremenek5934cee2008-05-01 02:18:37 +0000994 // Check if we are calling "autorelease".
995
996 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000997
Ted Kremenek5934cee2008-05-01 02:18:37 +0000998 if (S == AutoreleaseSelector)
999 mode = IsAutorelease;
1000 else if (S == RetainSelector)
1001 mode = IsRetain;
1002 else if (S == ReleaseSelector)
1003 mode = IsRelease;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001004
Ted Kremenek5934cee2008-05-01 02:18:37 +00001005 if (mode == IsNone)
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001006 return true;
1007
Ted Kremenek5934cee2008-05-01 02:18:37 +00001008 // We have "retain", "release", or "autorelease".
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001009 ValueStateManager& StateMgr = Eng.getStateManager();
1010 ValueState* St = Builder.GetState(Pred);
1011 RVal V = StateMgr.GetRVal(St, Receiver);
1012
Ted Kremenek5934cee2008-05-01 02:18:37 +00001013 // Was the argument something we are not tracking?
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001014 if (!isa<lval::SymbolVal>(V))
1015 return true;
1016
Ted Kremenek5934cee2008-05-01 02:18:37 +00001017 // Get the bindings.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001018 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1019 RefBindings B = GetRefBindings(*St);
1020
Ted Kremenek5934cee2008-05-01 02:18:37 +00001021 // Find the tracked value.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001022 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek5934cee2008-05-01 02:18:37 +00001023
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001024 if (!T)
1025 return true;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001026
Ted Kremenek5934cee2008-05-01 02:18:37 +00001027 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001028
Ted Kremenek5934cee2008-05-01 02:18:37 +00001029 // Update the bindings.
1030 switch (mode) {
1031 case IsNone:
1032 assert(false);
1033
1034 case IsRelease:
1035 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1036 break;
1037
1038 case IsRetain:
1039 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1040 break;
1041
1042 case IsAutorelease:
1043 // For now we just stop tracking a value if we see
1044 // it sent "autorelease." In the future we can potentially
1045 // track the associated pool.
1046 B = Remove(B, Sym);
1047 break;
1048 }
1049
1050 // Create a new state with the updated bindings.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001051 ValueState StVals = *St;
1052 SetRefBindings(StVals, B);
1053 St = StateMgr.getPersistentState(StVals);
1054
Ted Kremenek5934cee2008-05-01 02:18:37 +00001055 // Create an error node if it exists.
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001056 if (hasErr)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001057 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001058 else
1059 Builder.MakeNode(Dst, ME, Pred, St);
1060
1061 return false;
Ted Kremenek85348202008-04-15 23:44:31 +00001062}
1063
Ted Kremenek13922612008-04-16 20:40:59 +00001064// Stores.
1065
1066void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1067 GRExprEngine& Eng,
1068 GRStmtNodeBuilder<ValueState>& Builder,
1069 Expr* E, ExplodedNode<ValueState>* Pred,
1070 ValueState* St, RVal TargetLV, RVal Val) {
1071
1072 // Check if we have a binding for "Val" and if we are storing it to something
1073 // we don't understand or otherwise the value "escapes" the function.
1074
1075 if (!isa<lval::SymbolVal>(Val))
1076 return;
1077
1078 // Are we storing to something that causes the value to "escape"?
1079
1080 bool escapes = false;
1081
1082 if (!isa<lval::DeclVal>(TargetLV))
1083 escapes = true;
1084 else
1085 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1086
1087 if (!escapes)
1088 return;
1089
1090 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1091 RefBindings B = GetRefBindings(*St);
1092 RefBindings::TreeTy* T = B.SlimFind(Sym);
1093
1094 if (!T)
1095 return;
1096
Ted Kremenekdb863712008-04-16 22:32:20 +00001097 // Nuke the binding.
1098 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001099
1100 // Hand of the remaining logic to the parent implementation.
1101 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1102}
1103
Ted Kremenekdb863712008-04-16 22:32:20 +00001104
1105ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1106 SymbolID sid) {
1107 ValueState StImpl = *St;
1108 RefBindings B = GetRefBindings(StImpl);
1109 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1110 return VMgr.getPersistentState(StImpl);
1111}
1112
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001113// End-of-path.
1114
Ted Kremenekdb863712008-04-16 22:32:20 +00001115ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1116 ValueState* St, SymbolID sid,
1117 RefVal V, bool& hasLeak) {
1118
Ted Kremenek4fd88972008-04-17 18:12:53 +00001119 hasLeak = V.isOwned() ||
1120 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001121
1122 if (!hasLeak)
1123 return NukeBinding(VMgr, St, sid);
1124
1125 RefBindings B = GetRefBindings(*St);
1126 ValueState StImpl = *St;
1127 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1128 return VMgr.getPersistentState(StImpl);
1129}
1130
1131void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001132 GREndPathNodeBuilder<ValueState>& Builder) {
1133
Ted Kremenekdb863712008-04-16 22:32:20 +00001134 ValueState* St = Builder.getState();
1135 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001136
Ted Kremenekdb863712008-04-16 22:32:20 +00001137 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001138
Ted Kremenekdb863712008-04-16 22:32:20 +00001139 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1140 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001141
Ted Kremenekdb863712008-04-16 22:32:20 +00001142 St = HandleSymbolDeath(Eng.getStateManager(), St,
1143 (*I).first, (*I).second, hasLeak);
1144
1145 if (hasLeak) Leaked.push_back((*I).first);
1146 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001147
1148 if (Leaked.empty())
1149 return;
1150
Ted Kremenek8dd56462008-04-18 03:39:05 +00001151 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001152
Ted Kremenek652adc62008-04-24 23:57:27 +00001153 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001154 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001155
Ted Kremenek8dd56462008-04-18 03:39:05 +00001156 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1157 assert (!LeaksAtNode);
1158 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001159
1160 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1161 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001162 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001163}
1164
Ted Kremenek652adc62008-04-24 23:57:27 +00001165// Dead symbols.
1166
1167void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1168 GRExprEngine& Eng,
1169 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001170 ExplodedNode<ValueState>* Pred,
1171 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001172 ValueState* St,
1173 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001174
Ted Kremenek652adc62008-04-24 23:57:27 +00001175 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1176
1177 RefBindings B = GetRefBindings(*St);
1178 llvm::SmallVector<SymbolID, 10> Leaked;
1179
1180 for (ValueStateManager::DeadSymbolsTy::const_iterator
1181 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1182
1183 RefBindings::TreeTy* T = B.SlimFind(*I);
1184
1185 if (!T)
1186 continue;
1187
1188 bool hasLeak = false;
1189
1190 St = HandleSymbolDeath(Eng.getStateManager(), St,
1191 *I, T->getValue().second, hasLeak);
1192
1193 if (hasLeak) Leaked.push_back(*I);
1194 }
1195
1196 if (Leaked.empty())
1197 return;
1198
1199 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1200
1201 if (!N)
1202 return;
1203
1204 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1205 assert (!LeaksAtNode);
1206 LeaksAtNode = new std::vector<SymbolID>();
1207
1208 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1209 E = Leaked.end(); I != E; ++I)
1210 (*LeaksAtNode).push_back(*I);
1211}
1212
Ted Kremenek4fd88972008-04-17 18:12:53 +00001213 // Return statements.
1214
1215void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1216 GRExprEngine& Eng,
1217 GRStmtNodeBuilder<ValueState>& Builder,
1218 ReturnStmt* S,
1219 ExplodedNode<ValueState>* Pred) {
1220
1221 Expr* RetE = S->getRetValue();
1222 if (!RetE) return;
1223
1224 ValueStateManager& StateMgr = Eng.getStateManager();
1225 ValueState* St = Builder.GetState(Pred);
1226 RVal V = StateMgr.GetRVal(St, RetE);
1227
1228 if (!isa<lval::SymbolVal>(V))
1229 return;
1230
1231 // Get the reference count binding (if any).
1232 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1233 RefBindings B = GetRefBindings(*St);
1234 RefBindings::TreeTy* T = B.SlimFind(Sym);
1235
1236 if (!T)
1237 return;
1238
1239 // Change the reference count.
1240
1241 RefVal X = T->getValue().second;
1242
1243 switch (X.getKind()) {
1244
1245 case RefVal::Owned: {
1246 unsigned cnt = X.getCount();
1247 X = RefVal::makeReturnedOwned(cnt);
1248 break;
1249 }
1250
1251 case RefVal::NotOwned: {
1252 unsigned cnt = X.getCount();
1253 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1254 : RefVal::makeReturnedNotOwned();
1255 break;
1256 }
1257
1258 default:
1259 // None of the error states should be possible at this point.
1260 // A symbol could not have been leaked (yet) if we are returning it
1261 // (and thus it is still live), and the other errors are hard errors.
1262 assert(false);
1263 return;
1264 }
1265
1266 // Update the binding.
1267
1268 ValueState StImpl = *St;
1269 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1270 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1271}
1272
Ted Kremenekcb612922008-04-18 19:23:43 +00001273// Assumptions.
1274
1275ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1276 RVal Cond, bool Assumption,
1277 bool& isFeasible) {
1278
1279 // FIXME: We may add to the interface of EvalAssume the list of symbols
1280 // whose assumptions have changed. For now we just iterate through the
1281 // bindings and check if any of the tracked symbols are NULL. This isn't
1282 // too bad since the number of symbols we will track in practice are
1283 // probably small and EvalAssume is only called at branches and a few
1284 // other places.
1285
1286 RefBindings B = GetRefBindings(*St);
1287
1288 if (B.isEmpty())
1289 return St;
1290
1291 bool changed = false;
1292
1293 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1294
1295 // Check if the symbol is null (or equal to any constant).
1296 // If this is the case, stop tracking the symbol.
1297
1298 if (St->getSymVal(I.getKey())) {
1299 changed = true;
1300 B = RefBFactory.Remove(B, I.getKey());
1301 }
1302 }
1303
1304 if (!changed)
1305 return St;
1306
1307 ValueState StImpl = *St;
1308 StImpl.CheckerState = B.getRoot();
1309 return Eng.getStateManager().getPersistentState(StImpl);
1310}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001311
1312CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001313 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001314 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001315
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001316 // FIXME: This dispatch can potentially be sped up by unifiying it into
1317 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001318
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001319 switch (E) {
1320 default:
1321 assert (false && "Unhandled CFRef transition.");
1322
1323 case DoNothing:
Ted Kremenek65c91652008-04-29 05:44:10 +00001324 if (!GCEnabled && V.getKind() == RefVal::Released) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001325 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001326 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001327 break;
1328 }
1329
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001330 return B;
1331
1332 case IncRef:
1333 switch (V.getKind()) {
1334 default:
1335 assert(false);
1336
1337 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001338 V = RefVal::makeOwned(V.getCount()+1);
1339 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001340
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001341 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001342 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001343 break;
1344
1345 case RefVal::Released:
Ted Kremenek65c91652008-04-29 05:44:10 +00001346 if (GCEnabled)
1347 V = RefVal::makeOwned();
1348 else {
1349 V = RefVal::makeUseAfterRelease();
1350 hasErr = V.getKind();
1351 }
1352
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001353 break;
1354 }
1355
Ted Kremenek940b1d82008-04-10 23:44:06 +00001356 break;
1357
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001358 case DecRef:
1359 switch (V.getKind()) {
1360 default:
1361 assert (false);
1362
1363 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001364 unsigned Count = V.getCount();
1365 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001366 break;
1367 }
1368
Ted Kremenek61b9f872008-04-10 23:09:18 +00001369 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001370 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001371
Ted Kremenek4fd88972008-04-17 18:12:53 +00001372 if (Count > 0)
1373 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001374 else {
1375 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001376 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001377 }
1378
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001379 break;
1380 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001381
1382 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001383 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001384 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001385 break;
1386 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001387
1388 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001389 }
1390
1391 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001392}
1393
Ted Kremenekfa34b332008-04-09 01:10:13 +00001394
1395//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001396// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001397//===----------------------------------------------------------------------===//
1398
Ted Kremenek8dd56462008-04-18 03:39:05 +00001399namespace {
1400
1401 //===-------------===//
1402 // Bug Descriptions. //
1403 //===-------------===//
1404
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001405 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001406 protected:
1407 CFRefCount& TF;
1408
1409 public:
1410 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenek072192b2008-04-30 23:47:44 +00001411
1412 CFRefCount& getTF() { return TF; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001413 };
1414
1415 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1416 public:
1417 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1418
1419 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001420 return "Core Foundation: Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001421 }
1422 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001423 return "Reference-counted object is used"
1424 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001425 }
1426
1427 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001428 };
1429
1430 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1431 public:
1432 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1433
1434 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001435 return "Core Foundation: Release of non-owned object";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001436 }
1437 virtual const char* getDescription() const {
1438 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001439 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001440 "The object is not owned at this point by the caller.";
1441 }
1442
1443 virtual void EmitWarnings(BugReporter& BR);
1444 };
1445
1446 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1447 public:
1448 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1449
1450 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001451 return "Core Foundation: Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001452 }
1453
1454 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001455 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001456 }
1457
1458 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekcb612922008-04-18 19:23:43 +00001459 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001460 };
1461
1462 //===---------===//
1463 // Bug Reports. //
1464 //===---------===//
1465
1466 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1467 SymbolID Sym;
1468 public:
Ted Kremenek072192b2008-04-30 23:47:44 +00001469 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001470 : RangedBugReport(D, n), Sym(sym) {}
1471
1472 virtual ~CFRefReport() {}
1473
Ted Kremenek072192b2008-04-30 23:47:44 +00001474 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek8dd56462008-04-18 03:39:05 +00001475
1476 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1477 ExplodedNode<ValueState>* PrevN,
1478 ExplodedGraph<ValueState>& G,
1479 BugReporter& BR);
1480 };
1481
1482
1483} // end anonymous namespace
1484
1485void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1486 GRSimpleVals::RegisterChecks(Eng);
1487 Eng.Register(new UseAfterRelease(*this));
1488 Eng.Register(new BadRelease(*this));
1489 Eng.Register(new Leak(*this));
1490}
1491
Ted Kremenek072192b2008-04-30 23:47:44 +00001492
1493static const char* Msgs[] = {
1494 "Code is compiled in garbage collection only mode" // GC only
1495 " (the bug occurs with garbage collection enabled).",
1496
1497 "Code is compiled without garbage collection.", // No GC.
1498
1499 "Code is compiled for use with and without garbage collection (GC)."
1500 " The bug occurs with GC enabled.", // Hybrid, with GC.
1501
1502 "Code is compiled for use with and without garbage collection (GC)."
1503 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1504};
1505
1506std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1507 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1508
1509 switch (TF.getLangOptions().getGCMode()) {
1510 default:
1511 assert(false);
1512
1513 case LangOptions::NonGC:
1514 assert (!TF.isGCEnabled());
1515 return std::make_pair(&Msgs[0], &Msgs[0]+1);
1516
1517 case LangOptions::GCOnly:
1518 assert (TF.isGCEnabled());
1519 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1520
1521 case LangOptions::HybridGC:
1522 if (TF.isGCEnabled())
1523 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1524 else
1525 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1526 }
1527}
1528
Ted Kremenek8dd56462008-04-18 03:39:05 +00001529PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1530 ExplodedNode<ValueState>* PrevN,
1531 ExplodedGraph<ValueState>& G,
1532 BugReporter& BR) {
1533
1534 // Check if the type state has changed.
1535
1536 ValueState* PrevSt = PrevN->getState();
1537 ValueState* CurrSt = N->getState();
1538
1539 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1540 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1541
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001542 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1543 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001544
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001545 if (!CurrT)
1546 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001547
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001548 const char* Msg = NULL;
1549 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001550
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001551 if (!PrevT) {
1552
1553 // Check for the point where we start tracking the value.
1554
1555 if (CurrV.isOwned())
1556 Msg = "Function call returns 'Owned' Core Foundation object.";
1557 else {
1558 assert (CurrV.isNotOwned());
1559 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1560 }
1561
1562 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1563 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1564 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1565
1566 if (Expr* Exp = dyn_cast<Expr>(S))
1567 P->addRange(Exp->getSourceRange());
1568
1569 return P;
1570 }
1571
1572 // Determine if the typestate has changed.
1573
1574 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1575
1576 if (PrevV == CurrV)
1577 return NULL;
1578
1579 // The typestate has changed.
1580
1581 std::ostringstream os;
1582
1583 switch (CurrV.getKind()) {
1584 case RefVal::Owned:
1585 case RefVal::NotOwned:
1586 assert (PrevV.getKind() == CurrV.getKind());
1587
1588 if (PrevV.getCount() > CurrV.getCount())
1589 os << "Reference count decremented.";
1590 else
1591 os << "Reference count incremented.";
1592
Ted Kremenek79c140b2008-04-18 05:32:44 +00001593 if (CurrV.getCount()) {
1594 os << " Object has +" << CurrV.getCount();
1595
1596 if (CurrV.getCount() > 1)
1597 os << " reference counts.";
1598 else
1599 os << " reference count.";
1600 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001601
1602 Msg = os.str().c_str();
1603
1604 break;
1605
1606 case RefVal::Released:
1607 Msg = "Object released.";
1608 break;
1609
1610 case RefVal::ReturnedOwned:
1611 Msg = "Object returned to caller. "
1612 "Caller gets ownership of object.";
1613 break;
1614
1615 case RefVal::ReturnedNotOwned:
1616 Msg = "Object returned to caller. "
1617 "Caller does not get ownership of object.";
1618 break;
1619
1620 default:
1621 return NULL;
1622 }
1623
1624 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1625 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1626 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1627
1628 // Add the range by scanning the children of the statement for any bindings
1629 // to Sym.
1630
1631 ValueStateManager& VSM = BR.getEngine().getStateManager();
1632
1633 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1634 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1635 RVal X = VSM.GetRVal(CurrSt, Exp);
1636
1637 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1638 if (SV->getSymbol() == Sym) {
1639 P->addRange(Exp->getSourceRange()); break;
1640 }
1641 }
1642
1643 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001644}
1645
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001646void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001647
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001648 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1649 E = TF.use_after_end(); I != E; ++I) {
1650
Ted Kremenek8dd56462008-04-18 03:39:05 +00001651 CFRefReport report(*this, I->first, I->second.second);
1652 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00001653 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001654 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001655}
1656
1657void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001658
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001659 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1660 E = TF.bad_release_end(); I != E; ++I) {
1661
Ted Kremenek8dd56462008-04-18 03:39:05 +00001662 CFRefReport report(*this, I->first, I->second.second);
1663 report.addRange(I->second.first->getSourceRange());
1664 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001665 }
1666}
Ted Kremenekfa34b332008-04-09 01:10:13 +00001667
Ted Kremenek989d5192008-04-17 23:43:50 +00001668void Leak::EmitWarnings(BugReporter& BR) {
1669
1670 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1671 E = TF.leaks_end(); I != E; ++I) {
1672
Ted Kremenek8dd56462008-04-18 03:39:05 +00001673 std::vector<SymbolID>& SymV = *(I->second);
1674 unsigned n = SymV.size();
1675
1676 for (unsigned i = 0; i < n; ++i) {
1677 CFRefReport report(*this, I->first, SymV[i]);
1678 BR.EmitWarning(report);
1679 }
Ted Kremenek989d5192008-04-17 23:43:50 +00001680 }
1681}
1682
Ted Kremenekcb612922008-04-18 19:23:43 +00001683void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1684 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1685 I!=E; ++I)
1686 Nodes.push_back(I->first);
1687}
1688
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001689//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00001690// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001691//===----------------------------------------------------------------------===//
1692
Ted Kremenek072192b2008-04-30 23:47:44 +00001693GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
1694 const LangOptions& lopts) {
1695 return new CFRefCount(Ctx, GCEnabled, lopts);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00001696}