blob: 9ed4f1db2934115c156ae325db922e9d48d11680 [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000016#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000017#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000019#include "clang/Analysis/PathDiagnostic.h"
20#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000021#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/ImmutableMap.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000024#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000025#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000026#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000027
28using namespace clang;
29
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000030//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-04-17 18:12:53 +000031// Utility functions.
32//===----------------------------------------------------------------------===//
33
34static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
35 IdentifierInfo* II = &Ctx.Idents.get(name);
36 return Ctx.Selectors.getSelector(0, &II);
37}
38
39//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000040// Symbolic Evaluation of Reference Counting Logic
41//===----------------------------------------------------------------------===//
42
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000043namespace {
44 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenek891d5cc2008-04-24 17:22:33 +000045 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000046}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000047
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000048namespace llvm {
49 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000050 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +000051 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
52 ID.AddInteger(I->first);
53 ID.AddInteger((unsigned) I->second);
54 }
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000055 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000056 };
57} // end llvm namespace
58
59namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +000060
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000061class RetEffect {
62public:
Ted Kremenek940b1d82008-04-10 23:44:06 +000063 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
64 NotOwnedSymbol = 0x3 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000065
66private:
67 unsigned Data;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000068 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000069
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000070public:
71
72 Kind getKind() const { return (Kind) (Data & 0x3); }
73
74 unsigned getValue() const {
75 assert(getKind() == Alias);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000076 return Data >> 2;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000077 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +000078
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000079 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000080
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000081 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000082
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000083 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
84
Ted Kremenek940b1d82008-04-10 23:44:06 +000085 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
86
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000087 operator Kind() const { return getKind(); }
88
89 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
90};
91
92
93class CFRefSummary : public llvm::FoldingSetNode {
94 ArgEffects* Args;
95 RetEffect Ret;
96public:
97
98 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
99
100 unsigned getNumArgs() const { return Args->size(); }
101
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000102 ArgEffect getArg(unsigned idx) const {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000103 if (!Args)
104 return DoNothing;
105
106 // If Args is present, it is likely to contain only 1 element.
107 // Just do a linear search. Do it from the back because functions with
108 // large numbers of arguments will be tail heavy with respect to which
109 // argument they actually modify with respect to the reference count.
110
111 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
112 I!=E; ++I) {
113
114 if (idx > I->first)
115 return DoNothing;
116
117 if (idx == I->first)
118 return I->second;
119 }
120
121 return DoNothing;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000122 }
123
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000124 RetEffect getRet() const {
125 return Ret;
126 }
127
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000128 typedef ArgEffects::const_iterator arg_iterator;
129
130 arg_iterator begin_args() const { return Args->begin(); }
131 arg_iterator end_args() const { return Args->end(); }
132
133 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
134 ID.AddPointer(A);
135 ID.Add(R);
136 }
137
138 void Profile(llvm::FoldingSetNodeID& ID) const {
139 Profile(ID, Args, Ret);
140 }
141};
142
143
144class CFRefSummaryManager {
145 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
146 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
147 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
148
Ted Kremenek377e2302008-04-29 05:33:51 +0000149 ASTContext& Ctx;
150 const bool GCEnabled;
151
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000152 SummarySetTy SummarySet;
153 SummaryMapTy SummaryMap;
154 AESetTy AESet;
155 llvm::BumpPtrAllocator BPAlloc;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000156 ArgEffects ScratchArgs;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000157
158 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000159
Ted Kremenek377e2302008-04-29 05:33:51 +0000160 enum CFUnaryFunc { cfretain, cfrelease, cfmakecollectable };
161 CFRefSummary* getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func);
162
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000163 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
164
165 CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
166 CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);
167
168 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000169
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000170public:
Ted Kremenek377e2302008-04-29 05:33:51 +0000171 CFRefSummaryManager(ASTContext& ctx, bool gcenabled)
172 : Ctx(ctx), GCEnabled(gcenabled) {}
173
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000174 ~CFRefSummaryManager();
175
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000176 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000177};
178
179} // end anonymous namespace
180
181//===----------------------------------------------------------------------===//
182// Implementation of checker data structures.
183//===----------------------------------------------------------------------===//
184
185CFRefSummaryManager::~CFRefSummaryManager() {
186
187 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
188 // mitigating the need to do explicit cleanup of the
189 // Argument-Effect summaries.
190
191 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
192 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000193}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000194
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000195ArgEffects* CFRefSummaryManager::getArgEffects() {
196
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000197 if (ScratchArgs.empty())
198 return NULL;
199
200 // Compute a profile for a non-empty ScratchArgs.
201
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000202 llvm::FoldingSetNodeID profile;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000203
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000204 profile.Add(ScratchArgs);
205 void* InsertPos;
206
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000207 // Look up the uniqued copy, or create a new one.
208
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000209 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
210 AESet.FindNodeOrInsertPos(profile, InsertPos);
211
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000212 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000213 ScratchArgs.clear();
214 return &E->getValue();
215 }
216
217 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
218 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
219
220 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
221 AESet.InsertNode(E, InsertPos);
222
223 ScratchArgs.clear();
224 return &E->getValue();
225}
226
227CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
228 RetEffect RE) {
229
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000230 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000231 llvm::FoldingSetNodeID profile;
232 CFRefSummary::Profile(profile, AE, RE);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000233
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000234 // Look up the uniqued summary, or create one if it doesn't exist.
235 void* InsertPos;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000236 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
237
238 if (Summ)
239 return Summ;
240
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000241 // Create the summary and return it.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000242 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
243 new (Summ) CFRefSummary(AE, RE);
244 SummarySet.InsertNode(Summ, InsertPos);
245
246 return Summ;
247}
248
249
250CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
251 ASTContext& Ctx) {
252
253 SourceLocation Loc = FD->getLocation();
254
255 if (!Loc.isFileID())
256 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000257
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000258
259 // Look up a summary in our cache of FunctionDecls -> Summaries.
260 SummaryMapTy::iterator I = SummaryMap.find(FD);
261
262 if (I != SummaryMap.end())
263 return I->second;
264
265 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000266 const char* FName = FD->getIdentifier()->getName();
267
268 if (FName[0] == 'C' && FName[1] == 'F') {
269 CFRefSummary* S = getCFSummary(FD, FName);
270 SummaryMap[FD] = S;
271 return S;
272 }
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000273
274 // Function has no ref-count effects. Return the NULL summary.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000275 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000276}
277
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000278CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
279 const char* FName) {
280
281 // For now, only generate summaries for functions that have a prototype.
282
283 FunctionTypeProto* FT =
284 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
285
286 if (!FT)
287 return NULL;
288
289 FName += 2;
290
291 if (strcmp(FName, "Retain") == 0)
Ted Kremenek377e2302008-04-29 05:33:51 +0000292 return getUnaryCFSummary(FT, cfretain);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000293
294 if (strcmp(FName, "Release") == 0)
Ted Kremenek377e2302008-04-29 05:33:51 +0000295 return getUnaryCFSummary(FT, cfrelease);
296
297 if (strcmp(FName, "MakeCollectable") == 0)
298 return getUnaryCFSummary(FT, cfmakecollectable);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000299
300 assert (ScratchArgs.empty());
301 bool usesCreateRule = false;
302
303 if (strstr(FName, "Create"))
304 usesCreateRule = true;
305
306 if (!usesCreateRule && strstr(FName, "Copy"))
307 usesCreateRule = true;
308
309 if (usesCreateRule)
310 return getCFSummaryCreateRule(FT);
311
312 if (strstr(FName, "Get"))
313 return getCFSummaryGetRule(FT);
314
315 return NULL;
316}
317
Ted Kremenek377e2302008-04-29 05:33:51 +0000318CFRefSummary*
319CFRefSummaryManager::getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000320
321 if (FT->getNumArgs() != 1)
322 return NULL;
323
324 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
325
326 if (!ArgT)
327 return NULL;
328
329 // For CFRetain/CFRelease, the first (and only) argument is of type
330 // "CFTypeRef".
331
332 const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
333 assert (TDName);
334
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000335 if (strcmp("CFTypeRef", TDName) != 0)
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000336 return NULL;
337
Ted Kremenekc0c3f5d2008-04-30 20:17:27 +0000338 if (!ArgT->isPointerType())
339 return NULL;
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000340
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000341 QualType RetTy = FT->getResultType();
342
Ted Kremenek377e2302008-04-29 05:33:51 +0000343 switch (func) {
344 case cfretain: {
345
346 // CFRetain: the return type should also be "CFTypeRef".
347 if (RetTy.getTypePtr() != ArgT)
348 return NULL;
349
350 // The function's interface checks out. Generate a canned summary.
351 assert (ScratchArgs.empty());
352 ScratchArgs.push_back(std::make_pair(0, IncRef));
353 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
354 }
355
356 case cfrelease: {
357
358 // CFRelease: the return type should be void.
359
360 if (RetTy != Ctx.VoidTy)
361 return NULL;
362
363 assert (ScratchArgs.empty());
364 ScratchArgs.push_back(std::make_pair(0, DecRef));
365 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
366 }
367
368 case cfmakecollectable: {
369
370 // CFRetain: the return type should also be "CFTypeRef".
371 if (RetTy.getTypePtr() != ArgT)
372 return NULL;
373
374 // The function's interface checks out. Generate a canned summary.
375 assert (ScratchArgs.empty());
376
377 if (GCEnabled)
378 ScratchArgs.push_back(std::make_pair(0, DecRef));
379
380 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
381
382
383 }
384
385 default:
386 assert (false && "Not a support unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000387 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000388}
389
390static bool isCFRefType(QualType T) {
391
392 if (!T->isPointerType())
393 return false;
394
395 // Check the typedef for the name "CF" and the substring "Ref".
396
397 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
398
399 if (!TD)
400 return false;
401
402 const char* TDName = TD->getDecl()->getIdentifier()->getName();
403 assert (TDName);
404
405 if (TDName[0] != 'C' || TDName[1] != 'F')
406 return false;
407
408 if (strstr(TDName, "Ref") == 0)
409 return false;
410
411 return true;
412}
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000413
414CFRefSummary*
415CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
416
417 if (!isCFRefType(FT->getResultType()))
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000418 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000419
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000420 // FIXME: Add special-cases for functions that retain/release. For now
421 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000422
423 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000424 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
425}
426
427CFRefSummary*
428CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
429
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000430 QualType RetTy = FT->getResultType();
431
432 // FIXME: For now we assume that all pointer types returned are referenced
433 // counted. Since this is the "Get" rule, we assume non-ownership, which
434 // works fine for things that are not reference counted. We do this because
435 // some generic data structures return "void*". We need something better
436 // in the future.
437
438 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
439 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000440
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000441 // FIXME: Add special-cases for functions that retain/release. For now
442 // just handle the default case.
443
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000444 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000445 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
446}
447
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000448//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000449// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000450//===----------------------------------------------------------------------===//
451
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000452namespace {
453
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000454class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000455public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000456
Ted Kremenek4fd88972008-04-17 18:12:53 +0000457 enum Kind {
458 Owned = 0, // Owning reference.
459 NotOwned, // Reference is not owned by still valid (not freed).
460 Released, // Object has been released.
461 ReturnedOwned, // Returned object passes ownership to caller.
462 ReturnedNotOwned, // Return object does not pass ownership to caller.
463 ErrorUseAfterRelease, // Object used after released.
464 ErrorReleaseNotOwned, // Release of an object that was not owned.
465 ErrorLeak // A memory leak due to excessive reference counts.
466 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000467
Ted Kremenek4fd88972008-04-17 18:12:53 +0000468private:
469
470 Kind kind;
471 unsigned Cnt;
472
473 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
474
475 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000476
477public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000478
Ted Kremenek4fd88972008-04-17 18:12:53 +0000479 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000480
Ted Kremenek4fd88972008-04-17 18:12:53 +0000481 unsigned getCount() const { return Cnt; }
482
483 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000484
Ted Kremenek73c750b2008-03-11 18:14:09 +0000485 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
486
Ted Kremenekdb863712008-04-16 22:32:20 +0000487 static bool isLeak(Kind k) { return k == ErrorLeak; }
488
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000489 bool isOwned() const {
490 return getKind() == Owned;
491 }
492
Ted Kremenekdb863712008-04-16 22:32:20 +0000493 bool isNotOwned() const {
494 return getKind() == NotOwned;
495 }
496
Ted Kremenek4fd88972008-04-17 18:12:53 +0000497 bool isReturnedOwned() const {
498 return getKind() == ReturnedOwned;
499 }
500
501 bool isReturnedNotOwned() const {
502 return getKind() == ReturnedNotOwned;
503 }
504
505 bool isNonLeakError() const {
506 Kind k = getKind();
507 return isError(k) && !isLeak(k);
508 }
509
510 // State creation: normal state.
511
Ted Kremenek61b9f872008-04-10 23:09:18 +0000512 static RefVal makeOwned(unsigned Count = 0) {
513 return RefVal(Owned, Count);
514 }
515
516 static RefVal makeNotOwned(unsigned Count = 0) {
517 return RefVal(NotOwned, Count);
518 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000519
520 static RefVal makeReturnedOwned(unsigned Count) {
521 return RefVal(ReturnedOwned, Count);
522 }
523
524 static RefVal makeReturnedNotOwned() {
525 return RefVal(ReturnedNotOwned);
526 }
527
528 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000529
Ted Kremenekdb863712008-04-16 22:32:20 +0000530 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000531 static RefVal makeReleased() { return RefVal(Released); }
532 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
533 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000534
535 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000536
Ted Kremenek4fd88972008-04-17 18:12:53 +0000537 bool operator==(const RefVal& X) const {
538 return kind == X.kind && Cnt == X.Cnt;
539 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000540
Ted Kremenek4fd88972008-04-17 18:12:53 +0000541 void Profile(llvm::FoldingSetNodeID& ID) const {
542 ID.AddInteger((unsigned) kind);
543 ID.AddInteger(Cnt);
544 }
545
Ted Kremenekf3948042008-03-11 19:44:10 +0000546 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000547};
Ted Kremenekf3948042008-03-11 19:44:10 +0000548
549void RefVal::print(std::ostream& Out) const {
550 switch (getKind()) {
551 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000552 case Owned: {
553 Out << "Owned";
554 unsigned cnt = getCount();
555 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000556 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000557 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000558
Ted Kremenek61b9f872008-04-10 23:09:18 +0000559 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000560 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000561 unsigned cnt = getCount();
562 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000563 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000564 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000565
Ted Kremenek4fd88972008-04-17 18:12:53 +0000566 case ReturnedOwned: {
567 Out << "ReturnedOwned";
568 unsigned cnt = getCount();
569 if (cnt) Out << " (+ " << cnt << ")";
570 break;
571 }
572
573 case ReturnedNotOwned: {
574 Out << "ReturnedNotOwned";
575 unsigned cnt = getCount();
576 if (cnt) Out << " (+ " << cnt << ")";
577 break;
578 }
579
Ted Kremenekf3948042008-03-11 19:44:10 +0000580 case Released:
581 Out << "Released";
582 break;
583
Ted Kremenekdb863712008-04-16 22:32:20 +0000584 case ErrorLeak:
585 Out << "Leaked";
586 break;
587
Ted Kremenekf3948042008-03-11 19:44:10 +0000588 case ErrorUseAfterRelease:
589 Out << "Use-After-Release [ERROR]";
590 break;
591
592 case ErrorReleaseNotOwned:
593 Out << "Release of Not-Owned [ERROR]";
594 break;
595 }
596}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000597
Ted Kremenek13922612008-04-16 20:40:59 +0000598//===----------------------------------------------------------------------===//
599// Transfer functions.
600//===----------------------------------------------------------------------===//
601
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000602class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000603public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000604 // Type definitions.
605
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000606 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000607 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000608
Ted Kremenek8dd56462008-04-18 03:39:05 +0000609 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
610 ReleasesNotOwnedTy;
611
612 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
613
614 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000615 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000616
Ted Kremenekf3948042008-03-11 19:44:10 +0000617 class BindingsPrinter : public ValueState::CheckerStatePrinter {
618 public:
619 virtual void PrintCheckerState(std::ostream& Out, void* State,
620 const char* nl, const char* sep);
621 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000622
623private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000624 // Instance variables.
625
Ted Kremeneke5c30122008-04-29 05:13:59 +0000626 CFRefSummaryManager Summaries;
627 const bool GCEnabled;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000628 RefBFactoryTy RefBFactory;
629
Ted Kremenek73c750b2008-03-11 18:14:09 +0000630 UseAfterReleasesTy UseAfterReleases;
631 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000632 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000633
Ted Kremenekf3948042008-03-11 19:44:10 +0000634 BindingsPrinter Printer;
635
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000636 Selector RetainSelector;
637 Selector ReleaseSelector;
638
Ted Kremenek8dd56462008-04-18 03:39:05 +0000639public:
640
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000641 static RefBindings GetRefBindings(ValueState& StImpl) {
642 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
643 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000644
Ted Kremenek8dd56462008-04-18 03:39:05 +0000645private:
646
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000647 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
648 StImpl.CheckerState = B.getRoot();
649 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000650
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000651 RefBindings Remove(RefBindings B, SymbolID sym) {
652 return RefBFactory.Remove(B, sym);
653 }
654
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000655 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000656 RefVal::Kind& hasErr);
657
Ted Kremenekdb863712008-04-16 22:32:20 +0000658 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
659 GRStmtNodeBuilder<ValueState>& Builder,
660 Expr* NodeExpr, Expr* ErrorExpr,
661 ExplodedNode<ValueState>* Pred,
662 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000663 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000664
665 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
666 SymbolID sid, RefVal V, bool& hasLeak);
667
668 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
669 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000670
671public:
Ted Kremenek13922612008-04-16 20:40:59 +0000672
Ted Kremeneke5c30122008-04-29 05:13:59 +0000673 CFRefCount(ASTContext& Ctx, bool gcenabled)
Ted Kremenek377e2302008-04-29 05:33:51 +0000674 : Summaries(Ctx, gcenabled),
Ted Kremeneke5c30122008-04-29 05:13:59 +0000675 GCEnabled(gcenabled),
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000676 RetainSelector(GetUnarySelector("retain", Ctx)),
677 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
678
Ted Kremenek8dd56462008-04-18 03:39:05 +0000679 virtual ~CFRefCount() {
680 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
681 delete I->second;
682 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000683
684 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000685
686 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
687 return &Printer;
688 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000689
690 // Calls.
691
692 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000693 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000694 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000695 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000696 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000697
Ted Kremenek85348202008-04-15 23:44:31 +0000698 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
699 GRExprEngine& Engine,
700 GRStmtNodeBuilder<ValueState>& Builder,
701 ObjCMessageExpr* ME,
702 ExplodedNode<ValueState>* Pred);
703
704 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
705 GRExprEngine& Engine,
706 GRStmtNodeBuilder<ValueState>& Builder,
707 ObjCMessageExpr* ME,
708 ExplodedNode<ValueState>* Pred);
709
Ted Kremenek13922612008-04-16 20:40:59 +0000710 // Stores.
711
712 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
713 GRExprEngine& Engine,
714 GRStmtNodeBuilder<ValueState>& Builder,
715 Expr* E, ExplodedNode<ValueState>* Pred,
716 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000717 // End-of-path.
718
719 virtual void EvalEndPath(GRExprEngine& Engine,
720 GREndPathNodeBuilder<ValueState>& Builder);
721
Ted Kremenek652adc62008-04-24 23:57:27 +0000722 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
723 GRExprEngine& Engine,
724 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +0000725 ExplodedNode<ValueState>* Pred,
726 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +0000727 ValueState* St,
728 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +0000729 // Return statements.
730
731 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
732 GRExprEngine& Engine,
733 GRStmtNodeBuilder<ValueState>& Builder,
734 ReturnStmt* S,
735 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +0000736
737 // Assumptions.
738
739 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
740 RVal Cond, bool Assumption, bool& isFeasible);
741
Ted Kremenekfa34b332008-04-09 01:10:13 +0000742 // Error iterators.
743
744 typedef UseAfterReleasesTy::iterator use_after_iterator;
745 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000746 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000747
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000748 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
749 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000750
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000751 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
752 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000753
754 leaks_iterator leaks_begin() { return Leaks.begin(); }
755 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000756};
757
758} // end anonymous namespace
759
Ted Kremenek8dd56462008-04-18 03:39:05 +0000760
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000761
762
Ted Kremenekf3948042008-03-11 19:44:10 +0000763void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
764 void* State, const char* nl,
765 const char* sep) {
766 RefBindings B((RefBindings::TreeTy*) State);
767
768 if (State)
769 Out << sep << nl;
770
771 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
772 Out << (*I).first << " : ";
773 (*I).second.print(Out);
774 Out << nl;
775 }
776}
777
Ted Kremenekf9561e52008-04-11 20:23:24 +0000778static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
779 return Summ ? Summ->getArg(idx) : DoNothing;
780}
781
782static inline RetEffect GetRetE(CFRefSummary* Summ) {
783 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
784}
785
Ted Kremenekdb863712008-04-16 22:32:20 +0000786void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
787 GRStmtNodeBuilder<ValueState>& Builder,
788 Expr* NodeExpr, Expr* ErrorExpr,
789 ExplodedNode<ValueState>* Pred,
790 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000791 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000792 Builder.BuildSinks = true;
793 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
794
795 if (!N) return;
796
797 switch (hasErr) {
798 default: assert(false);
799 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000800 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000801 break;
802
803 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000804 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000805 break;
806 }
807}
808
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000809void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000810 GRExprEngine& Eng,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000811 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000812 CallExpr* CE, RVal L,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000813 ExplodedNode<ValueState>* Pred) {
814
Ted Kremenek199e1a02008-03-12 21:06:49 +0000815 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000816
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000817 CFRefSummary* Summ = NULL;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000818
819 // Get the summary.
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000820
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000821 if (isa<lval::FuncVal>(L)) {
822 lval::FuncVal FV = cast<lval::FuncVal>(L);
823 FunctionDecl* FD = FV.getDecl();
824 Summ = Summaries.getSummary(FD, Eng.getContext());
825 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000826
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000827 // Get the state.
828
829 ValueState* St = Builder.GetState(Pred);
830
831 // Evaluate the effects of the call.
832
833 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000834 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekf9561e52008-04-11 20:23:24 +0000835
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000836 // This function has a summary. Evaluate the effect of the arguments.
837
838 unsigned idx = 0;
839
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000840 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000841 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000842
843 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
844 I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000845
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000846 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000847
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000848 if (isa<lval::SymbolVal>(V)) {
849 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +0000850 RefBindings B = GetRefBindings(StVals);
851
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000852 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000853 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000854 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000855
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000856 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000857 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000858 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000859 break;
860 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000861 }
Ted Kremenekb8873552008-04-11 20:51:02 +0000862 }
863 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
864
865 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
866 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000867 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +0000868 }
Ted Kremeneka5488462008-04-22 21:39:21 +0000869 else if (isa<nonlval::LValAsInteger>(V))
870 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000871 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000872
873 St = StateMgr.getPersistentState(StVals);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000874
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000875 if (hasErr) {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000876 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
877 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000878 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000879 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000880
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000881 // Finally, consult the summary for the return value.
882
Ted Kremenekf9561e52008-04-11 20:23:24 +0000883 RetEffect RE = GetRetE(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000884
885 switch (RE.getKind()) {
886 default:
887 assert (false && "Unhandled RetEffect."); break;
888
Ted Kremenek940b1d82008-04-10 23:44:06 +0000889 case RetEffect::NoRet:
Ted Kremenekf9561e52008-04-11 20:23:24 +0000890
891 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +0000892 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
893 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000894
895 if (CE->getType() != Eng.getContext().VoidTy) {
896 unsigned Count = Builder.getCurrentBlockCount();
897 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
898
899 RVal X = CE->getType()->isPointerType()
900 ? cast<RVal>(lval::SymbolVal(Sym))
901 : cast<RVal>(nonlval::SymbolVal(Sym));
902
903 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
904 }
905
Ted Kremenek940b1d82008-04-10 23:44:06 +0000906 break;
907
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000908 case RetEffect::Alias: {
909 unsigned idx = RE.getValue();
910 assert (idx < CE->getNumArgs());
911 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenek199e1a02008-03-12 21:06:49 +0000912 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000913 break;
914 }
915
916 case RetEffect::OwnedSymbol: {
917 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000918 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000919
920 ValueState StImpl = *St;
921 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000922 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000923
924 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
925 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000926 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000927
928 break;
929 }
930
931 case RetEffect::NotOwnedSymbol: {
932 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000933 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000934
935 ValueState StImpl = *St;
936 RefBindings B = GetRefBindings(StImpl);
937 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
938
939 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
940 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000941 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000942
943 break;
944 }
945 }
946
Ted Kremenek0e561a32008-03-21 21:30:14 +0000947 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000948}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000949
Ted Kremenek85348202008-04-15 23:44:31 +0000950
951void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
952 GRExprEngine& Eng,
953 GRStmtNodeBuilder<ValueState>& Builder,
954 ObjCMessageExpr* ME,
955 ExplodedNode<ValueState>* Pred) {
956
957 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
958 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
959}
960
961bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
962 GRExprEngine& Eng,
963 GRStmtNodeBuilder<ValueState>& Builder,
964 ObjCMessageExpr* ME,
965 ExplodedNode<ValueState>* Pred) {
Ted Kremenek377e2302008-04-29 05:33:51 +0000966
967 if (GCEnabled)
968 return true;
969
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000970 // Handle "toll-free bridging" of calls to "Release" and "Retain".
971
972 // FIXME: track the underlying object type associated so that we can
973 // flag illegal uses of toll-free bridging (or at least handle it
974 // at casts).
Ted Kremenek85348202008-04-15 23:44:31 +0000975
976 Selector S = ME->getSelector();
977
978 if (!S.isUnarySelector())
979 return true;
980
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000981 Expr* Receiver = ME->getReceiver();
982
983 if (!Receiver)
984 return true;
985
986 // Check if we are calling "Retain" or "Release".
987
988 bool isRetain = false;
989
990 if (S == RetainSelector)
991 isRetain = true;
992 else if (S != ReleaseSelector)
993 return true;
994
995 // We have "Retain" or "Release". Get the reference binding.
996
997 ValueStateManager& StateMgr = Eng.getStateManager();
998 ValueState* St = Builder.GetState(Pred);
999 RVal V = StateMgr.GetRVal(St, Receiver);
1000
1001 if (!isa<lval::SymbolVal>(V))
1002 return true;
1003
1004 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1005 RefBindings B = GetRefBindings(*St);
1006
1007 RefBindings::TreeTy* T = B.SlimFind(Sym);
1008
1009 if (!T)
1010 return true;
1011
1012 RefVal::Kind hasErr = (RefVal::Kind) 0;
1013 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
1014
1015 // Create a new state with the updated bindings.
1016
1017 ValueState StVals = *St;
1018 SetRefBindings(StVals, B);
1019 St = StateMgr.getPersistentState(StVals);
1020
1021 // Create an error node if it exists.
1022
1023 if (hasErr)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001024 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001025 else
1026 Builder.MakeNode(Dst, ME, Pred, St);
1027
1028 return false;
Ted Kremenek85348202008-04-15 23:44:31 +00001029}
1030
Ted Kremenek13922612008-04-16 20:40:59 +00001031// Stores.
1032
1033void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1034 GRExprEngine& Eng,
1035 GRStmtNodeBuilder<ValueState>& Builder,
1036 Expr* E, ExplodedNode<ValueState>* Pred,
1037 ValueState* St, RVal TargetLV, RVal Val) {
1038
1039 // Check if we have a binding for "Val" and if we are storing it to something
1040 // we don't understand or otherwise the value "escapes" the function.
1041
1042 if (!isa<lval::SymbolVal>(Val))
1043 return;
1044
1045 // Are we storing to something that causes the value to "escape"?
1046
1047 bool escapes = false;
1048
1049 if (!isa<lval::DeclVal>(TargetLV))
1050 escapes = true;
1051 else
1052 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1053
1054 if (!escapes)
1055 return;
1056
1057 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1058 RefBindings B = GetRefBindings(*St);
1059 RefBindings::TreeTy* T = B.SlimFind(Sym);
1060
1061 if (!T)
1062 return;
1063
Ted Kremenekdb863712008-04-16 22:32:20 +00001064 // Nuke the binding.
1065 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001066
1067 // Hand of the remaining logic to the parent implementation.
1068 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1069}
1070
Ted Kremenekdb863712008-04-16 22:32:20 +00001071
1072ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1073 SymbolID sid) {
1074 ValueState StImpl = *St;
1075 RefBindings B = GetRefBindings(StImpl);
1076 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1077 return VMgr.getPersistentState(StImpl);
1078}
1079
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001080// End-of-path.
1081
Ted Kremenekdb863712008-04-16 22:32:20 +00001082ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1083 ValueState* St, SymbolID sid,
1084 RefVal V, bool& hasLeak) {
1085
Ted Kremenek4fd88972008-04-17 18:12:53 +00001086 hasLeak = V.isOwned() ||
1087 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001088
1089 if (!hasLeak)
1090 return NukeBinding(VMgr, St, sid);
1091
1092 RefBindings B = GetRefBindings(*St);
1093 ValueState StImpl = *St;
1094 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1095 return VMgr.getPersistentState(StImpl);
1096}
1097
1098void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001099 GREndPathNodeBuilder<ValueState>& Builder) {
1100
Ted Kremenekdb863712008-04-16 22:32:20 +00001101 ValueState* St = Builder.getState();
1102 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001103
Ted Kremenekdb863712008-04-16 22:32:20 +00001104 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001105
Ted Kremenekdb863712008-04-16 22:32:20 +00001106 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1107 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001108
Ted Kremenekdb863712008-04-16 22:32:20 +00001109 St = HandleSymbolDeath(Eng.getStateManager(), St,
1110 (*I).first, (*I).second, hasLeak);
1111
1112 if (hasLeak) Leaked.push_back((*I).first);
1113 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001114
1115 if (Leaked.empty())
1116 return;
1117
Ted Kremenek8dd56462008-04-18 03:39:05 +00001118 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001119
Ted Kremenek652adc62008-04-24 23:57:27 +00001120 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001121 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001122
Ted Kremenek8dd56462008-04-18 03:39:05 +00001123 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1124 assert (!LeaksAtNode);
1125 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001126
1127 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1128 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001129 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001130}
1131
Ted Kremenek652adc62008-04-24 23:57:27 +00001132// Dead symbols.
1133
1134void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1135 GRExprEngine& Eng,
1136 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001137 ExplodedNode<ValueState>* Pred,
1138 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001139 ValueState* St,
1140 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001141
Ted Kremenek652adc62008-04-24 23:57:27 +00001142 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1143
1144 RefBindings B = GetRefBindings(*St);
1145 llvm::SmallVector<SymbolID, 10> Leaked;
1146
1147 for (ValueStateManager::DeadSymbolsTy::const_iterator
1148 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1149
1150 RefBindings::TreeTy* T = B.SlimFind(*I);
1151
1152 if (!T)
1153 continue;
1154
1155 bool hasLeak = false;
1156
1157 St = HandleSymbolDeath(Eng.getStateManager(), St,
1158 *I, T->getValue().second, hasLeak);
1159
1160 if (hasLeak) Leaked.push_back(*I);
1161 }
1162
1163 if (Leaked.empty())
1164 return;
1165
1166 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1167
1168 if (!N)
1169 return;
1170
1171 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1172 assert (!LeaksAtNode);
1173 LeaksAtNode = new std::vector<SymbolID>();
1174
1175 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1176 E = Leaked.end(); I != E; ++I)
1177 (*LeaksAtNode).push_back(*I);
1178}
1179
Ted Kremenek4fd88972008-04-17 18:12:53 +00001180 // Return statements.
1181
1182void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1183 GRExprEngine& Eng,
1184 GRStmtNodeBuilder<ValueState>& Builder,
1185 ReturnStmt* S,
1186 ExplodedNode<ValueState>* Pred) {
1187
1188 Expr* RetE = S->getRetValue();
1189 if (!RetE) return;
1190
1191 ValueStateManager& StateMgr = Eng.getStateManager();
1192 ValueState* St = Builder.GetState(Pred);
1193 RVal V = StateMgr.GetRVal(St, RetE);
1194
1195 if (!isa<lval::SymbolVal>(V))
1196 return;
1197
1198 // Get the reference count binding (if any).
1199 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1200 RefBindings B = GetRefBindings(*St);
1201 RefBindings::TreeTy* T = B.SlimFind(Sym);
1202
1203 if (!T)
1204 return;
1205
1206 // Change the reference count.
1207
1208 RefVal X = T->getValue().second;
1209
1210 switch (X.getKind()) {
1211
1212 case RefVal::Owned: {
1213 unsigned cnt = X.getCount();
1214 X = RefVal::makeReturnedOwned(cnt);
1215 break;
1216 }
1217
1218 case RefVal::NotOwned: {
1219 unsigned cnt = X.getCount();
1220 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1221 : RefVal::makeReturnedNotOwned();
1222 break;
1223 }
1224
1225 default:
1226 // None of the error states should be possible at this point.
1227 // A symbol could not have been leaked (yet) if we are returning it
1228 // (and thus it is still live), and the other errors are hard errors.
1229 assert(false);
1230 return;
1231 }
1232
1233 // Update the binding.
1234
1235 ValueState StImpl = *St;
1236 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1237 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1238}
1239
Ted Kremenekcb612922008-04-18 19:23:43 +00001240// Assumptions.
1241
1242ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1243 RVal Cond, bool Assumption,
1244 bool& isFeasible) {
1245
1246 // FIXME: We may add to the interface of EvalAssume the list of symbols
1247 // whose assumptions have changed. For now we just iterate through the
1248 // bindings and check if any of the tracked symbols are NULL. This isn't
1249 // too bad since the number of symbols we will track in practice are
1250 // probably small and EvalAssume is only called at branches and a few
1251 // other places.
1252
1253 RefBindings B = GetRefBindings(*St);
1254
1255 if (B.isEmpty())
1256 return St;
1257
1258 bool changed = false;
1259
1260 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1261
1262 // Check if the symbol is null (or equal to any constant).
1263 // If this is the case, stop tracking the symbol.
1264
1265 if (St->getSymVal(I.getKey())) {
1266 changed = true;
1267 B = RefBFactory.Remove(B, I.getKey());
1268 }
1269 }
1270
1271 if (!changed)
1272 return St;
1273
1274 ValueState StImpl = *St;
1275 StImpl.CheckerState = B.getRoot();
1276 return Eng.getStateManager().getPersistentState(StImpl);
1277}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001278
1279CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001280 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001281 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001282
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001283 // FIXME: This dispatch can potentially be sped up by unifiying it into
1284 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001285
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001286 switch (E) {
1287 default:
1288 assert (false && "Unhandled CFRef transition.");
1289
1290 case DoNothing:
Ted Kremenek65c91652008-04-29 05:44:10 +00001291 if (!GCEnabled && V.getKind() == RefVal::Released) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001292 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001293 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001294 break;
1295 }
1296
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001297 return B;
1298
1299 case IncRef:
1300 switch (V.getKind()) {
1301 default:
1302 assert(false);
1303
1304 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001305 V = RefVal::makeOwned(V.getCount()+1);
1306 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001307
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001308 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001309 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001310 break;
1311
1312 case RefVal::Released:
Ted Kremenek65c91652008-04-29 05:44:10 +00001313 if (GCEnabled)
1314 V = RefVal::makeOwned();
1315 else {
1316 V = RefVal::makeUseAfterRelease();
1317 hasErr = V.getKind();
1318 }
1319
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001320 break;
1321 }
1322
Ted Kremenek940b1d82008-04-10 23:44:06 +00001323 break;
1324
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001325 case DecRef:
1326 switch (V.getKind()) {
1327 default:
1328 assert (false);
1329
1330 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001331 unsigned Count = V.getCount();
1332 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001333 break;
1334 }
1335
Ted Kremenek61b9f872008-04-10 23:09:18 +00001336 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001337 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001338
Ted Kremenek4fd88972008-04-17 18:12:53 +00001339 if (Count > 0)
1340 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001341 else {
1342 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001343 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001344 }
1345
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001346 break;
1347 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001348
1349 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001350 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001351 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001352 break;
1353 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001354
1355 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001356 }
1357
1358 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001359}
1360
Ted Kremenekfa34b332008-04-09 01:10:13 +00001361
1362//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001363// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001364//===----------------------------------------------------------------------===//
1365
Ted Kremenek8dd56462008-04-18 03:39:05 +00001366namespace {
1367
1368 //===-------------===//
1369 // Bug Descriptions. //
1370 //===-------------===//
1371
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001372 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001373 protected:
1374 CFRefCount& TF;
1375
1376 public:
1377 CFRefBug(CFRefCount& tf) : TF(tf) {}
1378 };
1379
1380 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1381 public:
1382 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1383
1384 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001385 return "Core Foundation: Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001386 }
1387 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001388 return "Reference-counted object is used"
1389 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001390 }
1391
1392 virtual void EmitWarnings(BugReporter& BR);
1393
1394 };
1395
1396 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1397 public:
1398 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1399
1400 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001401 return "Core Foundation: Release of non-owned object";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001402 }
1403 virtual const char* getDescription() const {
1404 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001405 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001406 "The object is not owned at this point by the caller.";
1407 }
1408
1409 virtual void EmitWarnings(BugReporter& BR);
1410 };
1411
1412 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1413 public:
1414 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1415
1416 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001417 return "Core Foundation: Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001418 }
1419
1420 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001421 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001422 }
1423
1424 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekcb612922008-04-18 19:23:43 +00001425 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001426 };
1427
1428 //===---------===//
1429 // Bug Reports. //
1430 //===---------===//
1431
1432 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1433 SymbolID Sym;
1434 public:
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001435 CFRefReport(BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001436 : RangedBugReport(D, n), Sym(sym) {}
1437
1438 virtual ~CFRefReport() {}
1439
1440
1441 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1442 ExplodedNode<ValueState>* PrevN,
1443 ExplodedGraph<ValueState>& G,
1444 BugReporter& BR);
1445 };
1446
1447
1448} // end anonymous namespace
1449
1450void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1451 GRSimpleVals::RegisterChecks(Eng);
1452 Eng.Register(new UseAfterRelease(*this));
1453 Eng.Register(new BadRelease(*this));
1454 Eng.Register(new Leak(*this));
1455}
1456
1457PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1458 ExplodedNode<ValueState>* PrevN,
1459 ExplodedGraph<ValueState>& G,
1460 BugReporter& BR) {
1461
1462 // Check if the type state has changed.
1463
1464 ValueState* PrevSt = PrevN->getState();
1465 ValueState* CurrSt = N->getState();
1466
1467 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1468 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1469
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001470 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1471 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001472
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001473 if (!CurrT)
1474 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001475
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001476 const char* Msg = NULL;
1477 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001478
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001479 if (!PrevT) {
1480
1481 // Check for the point where we start tracking the value.
1482
1483 if (CurrV.isOwned())
1484 Msg = "Function call returns 'Owned' Core Foundation object.";
1485 else {
1486 assert (CurrV.isNotOwned());
1487 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1488 }
1489
1490 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1491 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1492 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1493
1494 if (Expr* Exp = dyn_cast<Expr>(S))
1495 P->addRange(Exp->getSourceRange());
1496
1497 return P;
1498 }
1499
1500 // Determine if the typestate has changed.
1501
1502 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1503
1504 if (PrevV == CurrV)
1505 return NULL;
1506
1507 // The typestate has changed.
1508
1509 std::ostringstream os;
1510
1511 switch (CurrV.getKind()) {
1512 case RefVal::Owned:
1513 case RefVal::NotOwned:
1514 assert (PrevV.getKind() == CurrV.getKind());
1515
1516 if (PrevV.getCount() > CurrV.getCount())
1517 os << "Reference count decremented.";
1518 else
1519 os << "Reference count incremented.";
1520
Ted Kremenek79c140b2008-04-18 05:32:44 +00001521 if (CurrV.getCount()) {
1522 os << " Object has +" << CurrV.getCount();
1523
1524 if (CurrV.getCount() > 1)
1525 os << " reference counts.";
1526 else
1527 os << " reference count.";
1528 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001529
1530 Msg = os.str().c_str();
1531
1532 break;
1533
1534 case RefVal::Released:
1535 Msg = "Object released.";
1536 break;
1537
1538 case RefVal::ReturnedOwned:
1539 Msg = "Object returned to caller. "
1540 "Caller gets ownership of object.";
1541 break;
1542
1543 case RefVal::ReturnedNotOwned:
1544 Msg = "Object returned to caller. "
1545 "Caller does not get ownership of object.";
1546 break;
1547
1548 default:
1549 return NULL;
1550 }
1551
1552 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1553 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1554 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1555
1556 // Add the range by scanning the children of the statement for any bindings
1557 // to Sym.
1558
1559 ValueStateManager& VSM = BR.getEngine().getStateManager();
1560
1561 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1562 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1563 RVal X = VSM.GetRVal(CurrSt, Exp);
1564
1565 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1566 if (SV->getSymbol() == Sym) {
1567 P->addRange(Exp->getSourceRange()); break;
1568 }
1569 }
1570
1571 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001572}
1573
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001574void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001575
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001576 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1577 E = TF.use_after_end(); I != E; ++I) {
1578
Ted Kremenek8dd56462008-04-18 03:39:05 +00001579 CFRefReport report(*this, I->first, I->second.second);
1580 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00001581 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001582 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001583}
1584
1585void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001586
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001587 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1588 E = TF.bad_release_end(); I != E; ++I) {
1589
Ted Kremenek8dd56462008-04-18 03:39:05 +00001590 CFRefReport report(*this, I->first, I->second.second);
1591 report.addRange(I->second.first->getSourceRange());
1592 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001593 }
1594}
Ted Kremenekfa34b332008-04-09 01:10:13 +00001595
Ted Kremenek989d5192008-04-17 23:43:50 +00001596void Leak::EmitWarnings(BugReporter& BR) {
1597
1598 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1599 E = TF.leaks_end(); I != E; ++I) {
1600
Ted Kremenek8dd56462008-04-18 03:39:05 +00001601 std::vector<SymbolID>& SymV = *(I->second);
1602 unsigned n = SymV.size();
1603
1604 for (unsigned i = 0; i < n; ++i) {
1605 CFRefReport report(*this, I->first, SymV[i]);
1606 BR.EmitWarning(report);
1607 }
Ted Kremenek989d5192008-04-17 23:43:50 +00001608 }
1609}
1610
Ted Kremenekcb612922008-04-18 19:23:43 +00001611void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1612 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1613 I!=E; ++I)
1614 Nodes.push_back(I->first);
1615}
1616
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001617//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00001618// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001619//===----------------------------------------------------------------------===//
1620
Ted Kremeneke5c30122008-04-29 05:13:59 +00001621GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled) {
1622 return new CFRefCount(Ctx, GCEnabled);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00001623}