blob: ea036f047b3afe115aa8724ba8e595504fccb71a [file] [log] [blame]
Chris Lattnerbe1a7a02008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek827f93b2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif2224fcb2008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek827f93b2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremeneka7338b42008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenekfe30beb2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000017#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenekdd0126b2008-03-31 18:26:32 +000018#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000019#include "clang/Analysis/LocalCheckers.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000020#include "clang/Analysis/PathDiagnostic.h"
21#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremeneka7338b42008-03-11 06:39:11 +000022#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/FoldingSet.h"
24#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000025#include "llvm/Support/Compiler.h"
Ted Kremenek3b11f7a2008-03-11 19:44:10 +000026#include <ostream>
Ted Kremeneka8503952008-04-18 04:55:01 +000027#include <sstream>
Ted Kremenek827f93b2008-03-06 00:08:09 +000028
29using namespace clang;
30
Ted Kremenek7d421f32008-04-09 23:49:11 +000031//===----------------------------------------------------------------------===//
Ted Kremenekd9ccf682008-04-17 18:12:53 +000032// Utility functions.
33//===----------------------------------------------------------------------===//
34
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +000035static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenekd9ccf682008-04-17 18:12:53 +000036 IdentifierInfo* II = &Ctx.Idents.get(name);
37 return Ctx.Selectors.getSelector(0, &II);
38}
39
40//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +000041// Symbolic Evaluation of Reference Counting Logic
42//===----------------------------------------------------------------------===//
43
Ted Kremeneka7338b42008-03-11 06:39:11 +000044namespace {
45 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenekae855d42008-04-24 17:22:33 +000046 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremeneka7338b42008-03-11 06:39:11 +000047}
Ted Kremenek827f93b2008-03-06 00:08:09 +000048
Ted Kremeneka7338b42008-03-11 06:39:11 +000049namespace llvm {
50 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +000051 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenekae855d42008-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 Kremeneka4c74292008-04-10 22:58:08 +000056 }
Ted Kremeneka7338b42008-03-11 06:39:11 +000057 };
58} // end llvm namespace
59
60namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +000061
Ted Kremeneka7338b42008-03-11 06:39:11 +000062class RetEffect {
63public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000064 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
65 NotOwnedSymbol = 0x3 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000066
67private:
68 unsigned Data;
Ted Kremeneka4c74292008-04-10 22:58:08 +000069 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000070
Ted Kremeneka7338b42008-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 Kremeneka4c74292008-04-10 22:58:08 +000077 return Data >> 2;
Ted Kremeneka7338b42008-03-11 06:39:11 +000078 }
Ted Kremenekffefc352008-04-11 22:25:11 +000079
Ted Kremeneka7338b42008-03-11 06:39:11 +000080 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000081
Ted Kremeneka7338b42008-03-11 06:39:11 +000082 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000083
Ted Kremeneka7338b42008-03-11 06:39:11 +000084 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
85
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000086 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
87
Ted Kremeneka7338b42008-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 Kremenek0d721572008-03-11 17:48:22 +0000103 ArgEffect getArg(unsigned idx) const {
Ted Kremenekae855d42008-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 Kremenek0d721572008-03-11 17:48:22 +0000123 }
124
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000125 RetEffect getRet() const {
126 return Ret;
127 }
128
Ted Kremeneka7338b42008-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 Kremenek9b0c09c2008-04-29 05:33:51 +0000150 ASTContext& Ctx;
151 const bool GCEnabled;
152
Ted Kremeneka4c74292008-04-10 22:58:08 +0000153 SummarySetTy SummarySet;
154 SummaryMapTy SummaryMap;
155 AESetTy AESet;
156 llvm::BumpPtrAllocator BPAlloc;
Ted Kremenekae855d42008-04-24 17:22:33 +0000157 ArgEffects ScratchArgs;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000158
159 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000160
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000161 enum CFUnaryFunc { cfretain, cfrelease, cfmakecollectable };
162 CFRefSummary* getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func);
163
Ted Kremenekce3ed1e2008-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 Kremenekae855d42008-04-24 17:22:33 +0000170
Ted Kremeneka7338b42008-03-11 06:39:11 +0000171public:
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000172 CFRefSummaryManager(ASTContext& ctx, bool gcenabled)
173 : Ctx(ctx), GCEnabled(gcenabled) {}
174
Ted Kremeneka7338b42008-03-11 06:39:11 +0000175 ~CFRefSummaryManager();
176
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000177 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremeneka7338b42008-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 Kremenek827f93b2008-03-06 00:08:09 +0000194}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000195
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000196ArgEffects* CFRefSummaryManager::getArgEffects() {
197
Ted Kremenekae855d42008-04-24 17:22:33 +0000198 if (ScratchArgs.empty())
199 return NULL;
200
201 // Compute a profile for a non-empty ScratchArgs.
202
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000203 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000204
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000205 profile.Add(ScratchArgs);
206 void* InsertPos;
207
Ted Kremenekae855d42008-04-24 17:22:33 +0000208 // Look up the uniqued copy, or create a new one.
209
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000210 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
211 AESet.FindNodeOrInsertPos(profile, InsertPos);
212
Ted Kremenekae855d42008-04-24 17:22:33 +0000213 if (E) {
Ted Kremenekce3ed1e2008-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 Kremenekae855d42008-04-24 17:22:33 +0000231 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000232 llvm::FoldingSetNodeID profile;
233 CFRefSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000234
Ted Kremenekae855d42008-04-24 17:22:33 +0000235 // Look up the uniqued summary, or create one if it doesn't exist.
236 void* InsertPos;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000237 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
238
239 if (Summ)
240 return Summ;
241
Ted Kremenekae855d42008-04-24 17:22:33 +0000242 // Create the summary and return it.
Ted Kremenekce3ed1e2008-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 Kremenek827f93b2008-03-06 00:08:09 +0000258
Ted Kremenekae855d42008-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 Kremenekce3ed1e2008-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 Kremenekae855d42008-04-24 17:22:33 +0000274
275 // Function has no ref-count effects. Return the NULL summary.
Ted Kremeneka7338b42008-03-11 06:39:11 +0000276 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000277}
278
Ted Kremenekce3ed1e2008-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 Kremenek9b0c09c2008-04-29 05:33:51 +0000293 return getUnaryCFSummary(FT, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000294
295 if (strcmp(FName, "Release") == 0)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000296 return getUnaryCFSummary(FT, cfrelease);
Ted Kremenek33661802008-05-01 21:31:50 +0000297
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000298 if (strcmp(FName, "MakeCollectable") == 0)
299 return getUnaryCFSummary(FT, cfmakecollectable);
Ted Kremenekce3ed1e2008-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 Kremenek9b0c09c2008-04-29 05:33:51 +0000319CFRefSummary*
320CFRefSummaryManager::getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func) {
Ted Kremenekce3ed1e2008-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 Kremeneka4c74292008-04-10 22:58:08 +0000336 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000337 return NULL;
338
Ted Kremenek7cefcac2008-04-30 20:17:27 +0000339 if (!ArgT->isPointerType())
340 return NULL;
Ted Kremeneka4c74292008-04-10 22:58:08 +0000341
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000342 QualType RetTy = FT->getResultType();
343
Ted Kremenek9b0c09c2008-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 Kremenekab2fa2a2008-04-10 23:44:06 +0000388 }
Ted Kremenekce3ed1e2008-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 Kremenekce3ed1e2008-03-12 01:21:45 +0000414
415CFRefSummary*
416CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
417
418 if (!isCFRefType(FT->getResultType()))
Ted Kremenekd4244d42008-04-11 20:11:19 +0000419 return NULL;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000420
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000421 // FIXME: Add special-cases for functions that retain/release. For now
422 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000423
424 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000425 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
426}
427
428CFRefSummary*
429CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
430
Ted Kremenekd4244d42008-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 Kremenekce3ed1e2008-03-12 01:21:45 +0000441
Ted Kremenekce3ed1e2008-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 Kremenekae855d42008-04-24 17:22:33 +0000445 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000446 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
447}
448
Ted Kremeneka7338b42008-03-11 06:39:11 +0000449//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000450// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000451//===----------------------------------------------------------------------===//
452
Ted Kremeneka7338b42008-03-11 06:39:11 +0000453namespace {
454
Ted Kremenek7d421f32008-04-09 23:49:11 +0000455class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000456public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000457
Ted Kremenekd9ccf682008-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 Kremenek0d721572008-03-11 17:48:22 +0000468
Ted Kremenekd9ccf682008-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 Kremenek0d721572008-03-11 17:48:22 +0000477
478public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000479
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000480 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000481
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000482 unsigned getCount() const { return Cnt; }
483
484 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000485
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000486 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
487
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000488 static bool isLeak(Kind k) { return k == ErrorLeak; }
489
Ted Kremenekffefc352008-04-11 22:25:11 +0000490 bool isOwned() const {
491 return getKind() == Owned;
492 }
493
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000494 bool isNotOwned() const {
495 return getKind() == NotOwned;
496 }
497
Ted Kremenekd9ccf682008-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 Kremenekc4f81022008-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 Kremenekd9ccf682008-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 Kremenekc4f81022008-04-10 23:09:18 +0000530
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000531 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek0d721572008-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 Kremenekd9ccf682008-04-17 18:12:53 +0000535
536 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000537
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000538 bool operator==(const RefVal& X) const {
539 return kind == X.kind && Cnt == X.Cnt;
540 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000541
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000542 void Profile(llvm::FoldingSetNodeID& ID) const {
543 ID.AddInteger((unsigned) kind);
544 ID.AddInteger(Cnt);
545 }
546
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000547 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000548};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000549
550void RefVal::print(std::ostream& Out) const {
551 switch (getKind()) {
552 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000553 case Owned: {
554 Out << "Owned";
555 unsigned cnt = getCount();
556 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000557 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000558 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000559
Ted Kremenekc4f81022008-04-10 23:09:18 +0000560 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000561 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000562 unsigned cnt = getCount();
563 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000564 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000565 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000566
Ted Kremenekd9ccf682008-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 Kremenek3b11f7a2008-03-11 19:44:10 +0000581 case Released:
582 Out << "Released";
583 break;
584
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000585 case ErrorLeak:
586 Out << "Leaked";
587 break;
588
Ted Kremenek3b11f7a2008-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 Kremenek0d721572008-03-11 17:48:22 +0000598
Ted Kremenek7aef4842008-04-16 20:40:59 +0000599//===----------------------------------------------------------------------===//
600// Transfer functions.
601//===----------------------------------------------------------------------===//
602
Ted Kremenek7d421f32008-04-09 23:49:11 +0000603class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000604public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000605 // Type definitions.
606
Ted Kremenek0d721572008-03-11 17:48:22 +0000607 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000608 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000609
Ted Kremenek2be7ddb2008-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 Kremenek3f3c9c82008-04-16 22:32:20 +0000616 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000617
Ted Kremenek3b11f7a2008-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 Kremenek2be7ddb2008-04-18 03:39:05 +0000623
624private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000625 // Instance variables.
626
Ted Kremenek102d42e2008-04-29 05:13:59 +0000627 CFRefSummaryManager Summaries;
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000628 const bool GCEnabled;
629 const LangOptions& LOpts;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000630 RefBFactoryTy RefBFactory;
631
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000632 UseAfterReleasesTy UseAfterReleases;
633 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000634 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000635
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000636 BindingsPrinter Printer;
637
Ted Kremenek1feab292008-04-16 04:28:53 +0000638 Selector RetainSelector;
639 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000640 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000641
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000642public:
643
Ted Kremeneka7338b42008-03-11 06:39:11 +0000644 static RefBindings GetRefBindings(ValueState& StImpl) {
645 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
646 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000647
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000648private:
649
Ted Kremeneka7338b42008-03-11 06:39:11 +0000650 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
651 StImpl.CheckerState = B.getRoot();
652 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000653
Ted Kremeneka7338b42008-03-11 06:39:11 +0000654 RefBindings Remove(RefBindings B, SymbolID sym) {
655 return RefBFactory.Remove(B, sym);
656 }
657
Ted Kremenek0d721572008-03-11 17:48:22 +0000658 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000659 RefVal::Kind& hasErr);
660
Ted Kremenek3f3c9c82008-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 Kremenek2be7ddb2008-04-18 03:39:05 +0000666 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-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 Kremeneka7338b42008-03-11 06:39:11 +0000673
674public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000675
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000676 CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000677 : Summaries(Ctx, gcenabled),
Ted Kremenek102d42e2008-04-29 05:13:59 +0000678 GCEnabled(gcenabled),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000679 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000680 RetainSelector(GetNullarySelector("retain", Ctx)),
681 ReleaseSelector(GetNullarySelector("release", Ctx)),
682 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000683
Ted Kremenek2be7ddb2008-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 Kremenek7d421f32008-04-09 23:49:11 +0000688
689 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000690
691 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
692 return &Printer;
693 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000694
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000695 bool isGCEnabled() const { return GCEnabled; }
696 const LangOptions& getLangOptions() const { return LOpts; }
697
Ted Kremeneka7338b42008-03-11 06:39:11 +0000698 // Calls.
699
700 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000701 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000702 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000703 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000704 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000705
Ted Kremenek4b4738b2008-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 Kremenek7aef4842008-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 Kremenekffefc352008-04-11 22:25:11 +0000725 // End-of-path.
726
727 virtual void EvalEndPath(GRExprEngine& Engine,
728 GREndPathNodeBuilder<ValueState>& Builder);
729
Ted Kremenek541db372008-04-24 23:57:27 +0000730 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
731 GRExprEngine& Engine,
732 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000733 ExplodedNode<ValueState>* Pred,
734 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000735 ValueState* St,
736 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-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 Kremenekeef8f1e2008-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 Kremenek10fe66d2008-04-09 01:10:13 +0000750 // Error iterators.
751
752 typedef UseAfterReleasesTy::iterator use_after_iterator;
753 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000754 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000755
Ted Kremenek7d421f32008-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 Kremenek10fe66d2008-04-09 01:10:13 +0000758
Ted Kremenek7d421f32008-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 Kremenek7f3f41a2008-04-17 23:43:50 +0000761
762 leaks_iterator leaks_begin() { return Leaks.begin(); }
763 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000764};
765
766} // end anonymous namespace
767
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000768
Ted Kremenek7d421f32008-04-09 23:49:11 +0000769
770
Ted Kremenek3b11f7a2008-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 Kremenek455dd862008-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 Kremenek3f3c9c82008-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 Kremenek2be7ddb2008-04-18 03:39:05 +0000799 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-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 Kremenek2be7ddb2008-04-18 03:39:05 +0000808 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000809 break;
810
811 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000812 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000813 break;
814 }
815}
816
Ted Kremenek827f93b2008-03-06 00:08:09 +0000817void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000818 GRExprEngine& Eng,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000819 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000820 CallExpr* CE, RVal L,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000821 ExplodedNode<ValueState>* Pred) {
822
Ted Kremenekce0767f2008-03-12 21:06:49 +0000823 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000824
Ted Kremenek73ba0472008-04-14 17:45:13 +0000825 CFRefSummary* Summ = NULL;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000826
827 // Get the summary.
Ted Kremenek827f93b2008-03-06 00:08:09 +0000828
Ted Kremenek73ba0472008-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 Kremenek827f93b2008-03-06 00:08:09 +0000834
Ted Kremeneka7338b42008-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 Kremenek1feab292008-04-16 04:28:53 +0000842 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek455dd862008-04-11 20:23:24 +0000843
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000844 // This function has a summary. Evaluate the effect of the arguments.
845
846 unsigned idx = 0;
847
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000848 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000849 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-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 Kremeneka7338b42008-03-11 06:39:11 +0000853
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000854 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000855
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000856 if (isa<lval::SymbolVal>(V)) {
857 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000858 RefBindings B = GetRefBindings(StVals);
859
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000860 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000861 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000862 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000863
Ted Kremenek1feab292008-04-16 04:28:53 +0000864 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000865 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000866 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000867 break;
868 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000869 }
Ted Kremeneke4924202008-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 Kremenek455dd862008-04-11 20:23:24 +0000875 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000876 }
Ted Kremenekbe621292008-04-22 21:39:21 +0000877 else if (isa<nonlval::LValAsInteger>(V))
878 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000879 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000880
881 St = StateMgr.getPersistentState(StVals);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000882
Ted Kremenek1feab292008-04-16 04:28:53 +0000883 if (hasErr) {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000884 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
885 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000886 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000887 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000888
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000889 // Finally, consult the summary for the return value.
890
Ted Kremenek455dd862008-04-11 20:23:24 +0000891 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000892
893 switch (RE.getKind()) {
894 default:
895 assert (false && "Unhandled RetEffect."); break;
896
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000897 case RetEffect::NoRet:
Ted Kremenek455dd862008-04-11 20:23:24 +0000898
899 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000900 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
901 // should compose behavior, not copy it.
Ted Kremenek455dd862008-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 Kremenekab2fa2a2008-04-10 23:44:06 +0000914 break;
915
Ted Kremenekce3ed1e2008-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 Kremenekce0767f2008-03-12 21:06:49 +0000920 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000921 break;
922 }
923
924 case RetEffect::OwnedSymbol: {
925 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000926 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000927
928 ValueState StImpl = *St;
929 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000930 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000931
932 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
933 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000934 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000935
936 break;
937 }
938
939 case RetEffect::NotOwnedSymbol: {
940 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000941 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-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 Kremenekce0767f2008-03-12 21:06:49 +0000949 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000950
951 break;
952 }
953 }
954
Ted Kremenekf10f2882008-03-21 21:30:14 +0000955 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek827f93b2008-03-06 00:08:09 +0000956}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000957
Ted Kremenek4b4738b2008-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
Ted Kremenek33661802008-05-01 21:31:50 +0000965 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
966 return;
967
968 // The basic transfer function logic for message expressions does nothing.
969 // We just invalidate all arguments passed in by references.
970
971 ValueStateManager& StateMgr = Eng.getStateManager();
972 ValueState* St = Builder.GetState(Pred);
973 RefBindings B = GetRefBindings(*St);
974
975 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
976 I != E; ++I) {
977
978 RVal V = StateMgr.GetRVal(St, *I);
979
980 if (isa<LVal>(V)) {
981
982 LVal lv = cast<LVal>(V);
983
984 // Did the lval bind to a symbol?
985 RVal X = StateMgr.GetRVal(St, lv);
986
987 if (isa<lval::SymbolVal>(X)) {
988 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
989 B = Remove(B, Sym);
990
991 // Create a new state with the updated bindings.
992 ValueState StVals = *St;
993 SetRefBindings(StVals, B);
994 St = StateMgr.getPersistentState(StVals);
995 }
996
997 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
998 }
999 }
1000
1001 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001002}
1003
1004bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1005 GRExprEngine& Eng,
1006 GRStmtNodeBuilder<ValueState>& Builder,
1007 ObjCMessageExpr* ME,
1008 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001009
1010 if (GCEnabled)
1011 return true;
1012
Ted Kremenek1feab292008-04-16 04:28:53 +00001013 // Handle "toll-free bridging" of calls to "Release" and "Retain".
1014
1015 // FIXME: track the underlying object type associated so that we can
1016 // flag illegal uses of toll-free bridging (or at least handle it
1017 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001018
1019 Selector S = ME->getSelector();
1020
1021 if (!S.isUnarySelector())
1022 return true;
1023
Ted Kremenek1feab292008-04-16 04:28:53 +00001024 Expr* Receiver = ME->getReceiver();
1025
1026 if (!Receiver)
1027 return true;
1028
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001029 // Check if we are calling "autorelease".
1030
1031 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001032
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001033 if (S == AutoreleaseSelector)
1034 mode = IsAutorelease;
1035 else if (S == RetainSelector)
1036 mode = IsRetain;
1037 else if (S == ReleaseSelector)
1038 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001039
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001040 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001041 return true;
1042
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001043 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001044 ValueStateManager& StateMgr = Eng.getStateManager();
1045 ValueState* St = Builder.GetState(Pred);
1046 RVal V = StateMgr.GetRVal(St, Receiver);
1047
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001048 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001049 if (!isa<lval::SymbolVal>(V))
1050 return true;
1051
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001052 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001053 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1054 RefBindings B = GetRefBindings(*St);
1055
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001056 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001057 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001058
Ted Kremenek1feab292008-04-16 04:28:53 +00001059 if (!T)
1060 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001061
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001062 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001063
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001064 // Update the bindings.
1065 switch (mode) {
1066 case IsNone:
1067 assert(false);
1068
1069 case IsRelease:
1070 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1071 break;
1072
1073 case IsRetain:
1074 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1075 break;
1076
1077 case IsAutorelease:
1078 // For now we just stop tracking a value if we see
1079 // it sent "autorelease." In the future we can potentially
1080 // track the associated pool.
1081 B = Remove(B, Sym);
1082 break;
1083 }
1084
1085 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001086 ValueState StVals = *St;
1087 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001088 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001089
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001090 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001091 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001092 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001093 else
1094 Builder.MakeNode(Dst, ME, Pred, St);
1095
1096 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001097}
1098
Ted Kremenek7aef4842008-04-16 20:40:59 +00001099// Stores.
1100
1101void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1102 GRExprEngine& Eng,
1103 GRStmtNodeBuilder<ValueState>& Builder,
1104 Expr* E, ExplodedNode<ValueState>* Pred,
1105 ValueState* St, RVal TargetLV, RVal Val) {
1106
1107 // Check if we have a binding for "Val" and if we are storing it to something
1108 // we don't understand or otherwise the value "escapes" the function.
1109
1110 if (!isa<lval::SymbolVal>(Val))
1111 return;
1112
1113 // Are we storing to something that causes the value to "escape"?
1114
1115 bool escapes = false;
1116
1117 if (!isa<lval::DeclVal>(TargetLV))
1118 escapes = true;
1119 else
1120 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1121
1122 if (!escapes)
1123 return;
1124
1125 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1126 RefBindings B = GetRefBindings(*St);
1127 RefBindings::TreeTy* T = B.SlimFind(Sym);
1128
1129 if (!T)
1130 return;
1131
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001132 // Nuke the binding.
1133 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001134
1135 // Hand of the remaining logic to the parent implementation.
1136 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1137}
1138
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001139
1140ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1141 SymbolID sid) {
1142 ValueState StImpl = *St;
1143 RefBindings B = GetRefBindings(StImpl);
1144 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1145 return VMgr.getPersistentState(StImpl);
1146}
1147
Ted Kremenekffefc352008-04-11 22:25:11 +00001148// End-of-path.
1149
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001150ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1151 ValueState* St, SymbolID sid,
1152 RefVal V, bool& hasLeak) {
1153
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001154 hasLeak = V.isOwned() ||
1155 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001156
1157 if (!hasLeak)
1158 return NukeBinding(VMgr, St, sid);
1159
1160 RefBindings B = GetRefBindings(*St);
1161 ValueState StImpl = *St;
1162 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1163 return VMgr.getPersistentState(StImpl);
1164}
1165
1166void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001167 GREndPathNodeBuilder<ValueState>& Builder) {
1168
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001169 ValueState* St = Builder.getState();
1170 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001171
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001172 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001173
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001174 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1175 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001176
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001177 St = HandleSymbolDeath(Eng.getStateManager(), St,
1178 (*I).first, (*I).second, hasLeak);
1179
1180 if (hasLeak) Leaked.push_back((*I).first);
1181 }
Ted Kremenek541db372008-04-24 23:57:27 +00001182
1183 if (Leaked.empty())
1184 return;
1185
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001186 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001187
Ted Kremenek541db372008-04-24 23:57:27 +00001188 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001189 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001190
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001191 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1192 assert (!LeaksAtNode);
1193 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001194
1195 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1196 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001197 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001198}
1199
Ted Kremenek541db372008-04-24 23:57:27 +00001200// Dead symbols.
1201
1202void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1203 GRExprEngine& Eng,
1204 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001205 ExplodedNode<ValueState>* Pred,
1206 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001207 ValueState* St,
1208 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001209
Ted Kremenek541db372008-04-24 23:57:27 +00001210 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1211
1212 RefBindings B = GetRefBindings(*St);
1213 llvm::SmallVector<SymbolID, 10> Leaked;
1214
1215 for (ValueStateManager::DeadSymbolsTy::const_iterator
1216 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1217
1218 RefBindings::TreeTy* T = B.SlimFind(*I);
1219
1220 if (!T)
1221 continue;
1222
1223 bool hasLeak = false;
1224
1225 St = HandleSymbolDeath(Eng.getStateManager(), St,
1226 *I, T->getValue().second, hasLeak);
1227
1228 if (hasLeak) Leaked.push_back(*I);
1229 }
1230
1231 if (Leaked.empty())
1232 return;
1233
1234 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1235
1236 if (!N)
1237 return;
1238
1239 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1240 assert (!LeaksAtNode);
1241 LeaksAtNode = new std::vector<SymbolID>();
1242
1243 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1244 E = Leaked.end(); I != E; ++I)
1245 (*LeaksAtNode).push_back(*I);
1246}
1247
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001248 // Return statements.
1249
1250void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1251 GRExprEngine& Eng,
1252 GRStmtNodeBuilder<ValueState>& Builder,
1253 ReturnStmt* S,
1254 ExplodedNode<ValueState>* Pred) {
1255
1256 Expr* RetE = S->getRetValue();
1257 if (!RetE) return;
1258
1259 ValueStateManager& StateMgr = Eng.getStateManager();
1260 ValueState* St = Builder.GetState(Pred);
1261 RVal V = StateMgr.GetRVal(St, RetE);
1262
1263 if (!isa<lval::SymbolVal>(V))
1264 return;
1265
1266 // Get the reference count binding (if any).
1267 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1268 RefBindings B = GetRefBindings(*St);
1269 RefBindings::TreeTy* T = B.SlimFind(Sym);
1270
1271 if (!T)
1272 return;
1273
1274 // Change the reference count.
1275
1276 RefVal X = T->getValue().second;
1277
1278 switch (X.getKind()) {
1279
1280 case RefVal::Owned: {
1281 unsigned cnt = X.getCount();
1282 X = RefVal::makeReturnedOwned(cnt);
1283 break;
1284 }
1285
1286 case RefVal::NotOwned: {
1287 unsigned cnt = X.getCount();
1288 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1289 : RefVal::makeReturnedNotOwned();
1290 break;
1291 }
1292
1293 default:
1294 // None of the error states should be possible at this point.
1295 // A symbol could not have been leaked (yet) if we are returning it
1296 // (and thus it is still live), and the other errors are hard errors.
1297 assert(false);
1298 return;
1299 }
1300
1301 // Update the binding.
1302
1303 ValueState StImpl = *St;
1304 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1305 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1306}
1307
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001308// Assumptions.
1309
1310ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1311 RVal Cond, bool Assumption,
1312 bool& isFeasible) {
1313
1314 // FIXME: We may add to the interface of EvalAssume the list of symbols
1315 // whose assumptions have changed. For now we just iterate through the
1316 // bindings and check if any of the tracked symbols are NULL. This isn't
1317 // too bad since the number of symbols we will track in practice are
1318 // probably small and EvalAssume is only called at branches and a few
1319 // other places.
1320
1321 RefBindings B = GetRefBindings(*St);
1322
1323 if (B.isEmpty())
1324 return St;
1325
1326 bool changed = false;
1327
1328 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1329
1330 // Check if the symbol is null (or equal to any constant).
1331 // If this is the case, stop tracking the symbol.
1332
1333 if (St->getSymVal(I.getKey())) {
1334 changed = true;
1335 B = RefBFactory.Remove(B, I.getKey());
1336 }
1337 }
1338
1339 if (!changed)
1340 return St;
1341
1342 ValueState StImpl = *St;
1343 StImpl.CheckerState = B.getRoot();
1344 return Eng.getStateManager().getPersistentState(StImpl);
1345}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001346
1347CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001348 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001349 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001350
Ted Kremenek0d721572008-03-11 17:48:22 +00001351 // FIXME: This dispatch can potentially be sped up by unifiying it into
1352 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001353
Ted Kremenek0d721572008-03-11 17:48:22 +00001354 switch (E) {
1355 default:
1356 assert (false && "Unhandled CFRef transition.");
1357
1358 case DoNothing:
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001359 if (!GCEnabled && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001360 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001361 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001362 break;
1363 }
1364
Ted Kremenek0d721572008-03-11 17:48:22 +00001365 return B;
1366
1367 case IncRef:
1368 switch (V.getKind()) {
1369 default:
1370 assert(false);
1371
1372 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001373 V = RefVal::makeOwned(V.getCount()+1);
1374 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001375
Ted Kremenek0d721572008-03-11 17:48:22 +00001376 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001377 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001378 break;
1379
1380 case RefVal::Released:
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001381 if (GCEnabled)
1382 V = RefVal::makeOwned();
1383 else {
1384 V = RefVal::makeUseAfterRelease();
1385 hasErr = V.getKind();
1386 }
1387
Ted Kremenek0d721572008-03-11 17:48:22 +00001388 break;
1389 }
1390
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001391 break;
1392
Ted Kremenek0d721572008-03-11 17:48:22 +00001393 case DecRef:
1394 switch (V.getKind()) {
1395 default:
1396 assert (false);
1397
1398 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001399 unsigned Count = V.getCount();
1400 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001401 break;
1402 }
1403
Ted Kremenekc4f81022008-04-10 23:09:18 +00001404 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001405 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001406
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001407 if (Count > 0)
1408 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001409 else {
1410 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001411 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001412 }
1413
Ted Kremenek0d721572008-03-11 17:48:22 +00001414 break;
1415 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001416
1417 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001418 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001419 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001420 break;
1421 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001422
1423 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001424 }
1425
1426 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001427}
1428
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001429
1430//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001431// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001432//===----------------------------------------------------------------------===//
1433
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001434namespace {
1435
1436 //===-------------===//
1437 // Bug Descriptions. //
1438 //===-------------===//
1439
Ted Kremeneke3769852008-04-18 20:54:29 +00001440 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001441 protected:
1442 CFRefCount& TF;
1443
1444 public:
1445 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001446
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001447 CFRefCount& getTF() { return TF; }
1448
1449 virtual bool ReportRanges() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001450 };
1451
1452 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1453 public:
1454 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1455
1456 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001457 return "Core Foundation: Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001458 }
1459 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001460 return "Reference-counted object is used"
1461 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001462 }
1463
1464 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001465 };
1466
1467 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1468 public:
1469 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1470
1471 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001472 return "Core Foundation: Release of non-owned object";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001473 }
1474 virtual const char* getDescription() const {
1475 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001476 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001477 "The object is not owned at this point by the caller.";
1478 }
1479
1480 virtual void EmitWarnings(BugReporter& BR);
1481 };
1482
1483 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1484 public:
1485 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1486
1487 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001488 return "Core Foundation: Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001489 }
1490
1491 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001492 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001493 }
1494
1495 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001496 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
1497 virtual bool ReportRanges() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001498 };
1499
1500 //===---------===//
1501 // Bug Reports. //
1502 //===---------===//
1503
1504 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1505 SymbolID Sym;
1506 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001507 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001508 : RangedBugReport(D, n), Sym(sym) {}
1509
1510 virtual ~CFRefReport() {}
1511
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001512 CFRefBug& getBugType() {
1513 return (CFRefBug&) RangedBugReport::getBugType();
1514 }
1515 const CFRefBug& getBugType() const {
1516 return (const CFRefBug&) RangedBugReport::getBugType();
1517 }
1518
1519 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1520 const SourceRange*& end) {
1521
1522 if (getBugType().ReportRanges())
1523 RangedBugReport::getRanges(BR, beg, end);
1524 else {
1525 beg = 0;
1526 end = 0;
1527 }
1528 }
1529
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001530 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001531
1532 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1533 ExplodedNode<ValueState>* PrevN,
1534 ExplodedGraph<ValueState>& G,
1535 BugReporter& BR);
1536 };
1537
1538
1539} // end anonymous namespace
1540
1541void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1542 GRSimpleVals::RegisterChecks(Eng);
1543 Eng.Register(new UseAfterRelease(*this));
1544 Eng.Register(new BadRelease(*this));
1545 Eng.Register(new Leak(*this));
1546}
1547
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001548
1549static const char* Msgs[] = {
1550 "Code is compiled in garbage collection only mode" // GC only
1551 " (the bug occurs with garbage collection enabled).",
1552
1553 "Code is compiled without garbage collection.", // No GC.
1554
1555 "Code is compiled for use with and without garbage collection (GC)."
1556 " The bug occurs with GC enabled.", // Hybrid, with GC.
1557
1558 "Code is compiled for use with and without garbage collection (GC)."
1559 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1560};
1561
1562std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1563 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1564
1565 switch (TF.getLangOptions().getGCMode()) {
1566 default:
1567 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001568
1569 case LangOptions::GCOnly:
1570 assert (TF.isGCEnabled());
1571 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001572
1573 case LangOptions::NonGC:
1574 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001575 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1576
1577 case LangOptions::HybridGC:
1578 if (TF.isGCEnabled())
1579 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1580 else
1581 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1582 }
1583}
1584
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001585PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1586 ExplodedNode<ValueState>* PrevN,
1587 ExplodedGraph<ValueState>& G,
1588 BugReporter& BR) {
1589
1590 // Check if the type state has changed.
1591
1592 ValueState* PrevSt = PrevN->getState();
1593 ValueState* CurrSt = N->getState();
1594
1595 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1596 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1597
Ted Kremeneka8503952008-04-18 04:55:01 +00001598 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1599 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001600
Ted Kremeneka8503952008-04-18 04:55:01 +00001601 if (!CurrT)
1602 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001603
Ted Kremeneka8503952008-04-18 04:55:01 +00001604 const char* Msg = NULL;
1605 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001606
Ted Kremeneka8503952008-04-18 04:55:01 +00001607 if (!PrevT) {
1608
1609 // Check for the point where we start tracking the value.
1610
1611 if (CurrV.isOwned())
1612 Msg = "Function call returns 'Owned' Core Foundation object.";
1613 else {
1614 assert (CurrV.isNotOwned());
1615 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1616 }
1617
1618 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1619 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1620 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1621
1622 if (Expr* Exp = dyn_cast<Expr>(S))
1623 P->addRange(Exp->getSourceRange());
1624
1625 return P;
1626 }
1627
1628 // Determine if the typestate has changed.
1629
1630 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1631
1632 if (PrevV == CurrV)
1633 return NULL;
1634
1635 // The typestate has changed.
1636
1637 std::ostringstream os;
1638
1639 switch (CurrV.getKind()) {
1640 case RefVal::Owned:
1641 case RefVal::NotOwned:
1642 assert (PrevV.getKind() == CurrV.getKind());
1643
1644 if (PrevV.getCount() > CurrV.getCount())
1645 os << "Reference count decremented.";
1646 else
1647 os << "Reference count incremented.";
1648
Ted Kremenek752b5842008-04-18 05:32:44 +00001649 if (CurrV.getCount()) {
1650 os << " Object has +" << CurrV.getCount();
1651
1652 if (CurrV.getCount() > 1)
1653 os << " reference counts.";
1654 else
1655 os << " reference count.";
1656 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001657
1658 Msg = os.str().c_str();
1659
1660 break;
1661
1662 case RefVal::Released:
1663 Msg = "Object released.";
1664 break;
1665
1666 case RefVal::ReturnedOwned:
1667 Msg = "Object returned to caller. "
1668 "Caller gets ownership of object.";
1669 break;
1670
1671 case RefVal::ReturnedNotOwned:
1672 Msg = "Object returned to caller. "
1673 "Caller does not get ownership of object.";
1674 break;
1675
1676 default:
1677 return NULL;
1678 }
1679
1680 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1681 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1682 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1683
1684 // Add the range by scanning the children of the statement for any bindings
1685 // to Sym.
1686
1687 ValueStateManager& VSM = BR.getEngine().getStateManager();
1688
1689 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1690 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1691 RVal X = VSM.GetRVal(CurrSt, Exp);
1692
1693 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1694 if (SV->getSymbol() == Sym) {
1695 P->addRange(Exp->getSourceRange()); break;
1696 }
1697 }
1698
1699 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001700}
1701
Ted Kremenek7d421f32008-04-09 23:49:11 +00001702void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001703
Ted Kremenek7d421f32008-04-09 23:49:11 +00001704 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1705 E = TF.use_after_end(); I != E; ++I) {
1706
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001707 CFRefReport report(*this, I->first, I->second.second);
1708 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00001709 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001710 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001711}
1712
1713void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001714
Ted Kremenek7d421f32008-04-09 23:49:11 +00001715 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1716 E = TF.bad_release_end(); I != E; ++I) {
1717
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001718 CFRefReport report(*this, I->first, I->second.second);
1719 report.addRange(I->second.first->getSourceRange());
1720 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00001721 }
1722}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001723
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001724void Leak::EmitWarnings(BugReporter& BR) {
1725
1726 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1727 E = TF.leaks_end(); I != E; ++I) {
1728
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001729 std::vector<SymbolID>& SymV = *(I->second);
1730 unsigned n = SymV.size();
1731
1732 for (unsigned i = 0; i < n; ++i) {
1733 CFRefReport report(*this, I->first, SymV[i]);
1734 BR.EmitWarning(report);
1735 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001736 }
1737}
1738
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001739void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1740 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1741 I!=E; ++I)
1742 Nodes.push_back(I->first);
1743}
1744
Ted Kremeneka7338b42008-03-11 06:39:11 +00001745//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001746// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001747//===----------------------------------------------------------------------===//
1748
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001749GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
1750 const LangOptions& lopts) {
1751 return new CFRefCount(Ctx, GCEnabled, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00001752}