blob: 08bad5b155fc16806d1cca7a9fbd66fa7047bde2 [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 Kremenek036dce02008-04-30 20:01:29 +0000338 assert (ArgT->isPointerType() || ArgT->isObjCQualifiedIdType());
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000339
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000340 QualType RetTy = FT->getResultType();
341
Ted Kremenek377e2302008-04-29 05:33:51 +0000342 switch (func) {
343 case cfretain: {
344
345 // CFRetain: the return type should also be "CFTypeRef".
346 if (RetTy.getTypePtr() != ArgT)
347 return NULL;
348
349 // The function's interface checks out. Generate a canned summary.
350 assert (ScratchArgs.empty());
351 ScratchArgs.push_back(std::make_pair(0, IncRef));
352 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
353 }
354
355 case cfrelease: {
356
357 // CFRelease: the return type should be void.
358
359 if (RetTy != Ctx.VoidTy)
360 return NULL;
361
362 assert (ScratchArgs.empty());
363 ScratchArgs.push_back(std::make_pair(0, DecRef));
364 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
365 }
366
367 case cfmakecollectable: {
368
369 // CFRetain: the return type should also be "CFTypeRef".
370 if (RetTy.getTypePtr() != ArgT)
371 return NULL;
372
373 // The function's interface checks out. Generate a canned summary.
374 assert (ScratchArgs.empty());
375
376 if (GCEnabled)
377 ScratchArgs.push_back(std::make_pair(0, DecRef));
378
379 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
380
381
382 }
383
384 default:
385 assert (false && "Not a support unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000386 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000387}
388
389static bool isCFRefType(QualType T) {
390
391 if (!T->isPointerType())
392 return false;
393
394 // Check the typedef for the name "CF" and the substring "Ref".
395
396 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
397
398 if (!TD)
399 return false;
400
401 const char* TDName = TD->getDecl()->getIdentifier()->getName();
402 assert (TDName);
403
404 if (TDName[0] != 'C' || TDName[1] != 'F')
405 return false;
406
407 if (strstr(TDName, "Ref") == 0)
408 return false;
409
410 return true;
411}
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000412
413CFRefSummary*
414CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
415
416 if (!isCFRefType(FT->getResultType()))
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000417 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000418
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000419 // FIXME: Add special-cases for functions that retain/release. For now
420 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000421
422 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000423 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
424}
425
426CFRefSummary*
427CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
428
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000429 QualType RetTy = FT->getResultType();
430
431 // FIXME: For now we assume that all pointer types returned are referenced
432 // counted. Since this is the "Get" rule, we assume non-ownership, which
433 // works fine for things that are not reference counted. We do this because
434 // some generic data structures return "void*". We need something better
435 // in the future.
436
437 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
438 return NULL;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000439
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000440 // FIXME: Add special-cases for functions that retain/release. For now
441 // just handle the default case.
442
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000443 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000444 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
445}
446
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000447//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000448// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000449//===----------------------------------------------------------------------===//
450
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000451namespace {
452
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000453class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000454public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000455
Ted Kremenek4fd88972008-04-17 18:12:53 +0000456 enum Kind {
457 Owned = 0, // Owning reference.
458 NotOwned, // Reference is not owned by still valid (not freed).
459 Released, // Object has been released.
460 ReturnedOwned, // Returned object passes ownership to caller.
461 ReturnedNotOwned, // Return object does not pass ownership to caller.
462 ErrorUseAfterRelease, // Object used after released.
463 ErrorReleaseNotOwned, // Release of an object that was not owned.
464 ErrorLeak // A memory leak due to excessive reference counts.
465 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000466
Ted Kremenek4fd88972008-04-17 18:12:53 +0000467private:
468
469 Kind kind;
470 unsigned Cnt;
471
472 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
473
474 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000475
476public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000477
Ted Kremenek4fd88972008-04-17 18:12:53 +0000478 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000479
Ted Kremenek4fd88972008-04-17 18:12:53 +0000480 unsigned getCount() const { return Cnt; }
481
482 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000483
Ted Kremenek73c750b2008-03-11 18:14:09 +0000484 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
485
Ted Kremenekdb863712008-04-16 22:32:20 +0000486 static bool isLeak(Kind k) { return k == ErrorLeak; }
487
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000488 bool isOwned() const {
489 return getKind() == Owned;
490 }
491
Ted Kremenekdb863712008-04-16 22:32:20 +0000492 bool isNotOwned() const {
493 return getKind() == NotOwned;
494 }
495
Ted Kremenek4fd88972008-04-17 18:12:53 +0000496 bool isReturnedOwned() const {
497 return getKind() == ReturnedOwned;
498 }
499
500 bool isReturnedNotOwned() const {
501 return getKind() == ReturnedNotOwned;
502 }
503
504 bool isNonLeakError() const {
505 Kind k = getKind();
506 return isError(k) && !isLeak(k);
507 }
508
509 // State creation: normal state.
510
Ted Kremenek61b9f872008-04-10 23:09:18 +0000511 static RefVal makeOwned(unsigned Count = 0) {
512 return RefVal(Owned, Count);
513 }
514
515 static RefVal makeNotOwned(unsigned Count = 0) {
516 return RefVal(NotOwned, Count);
517 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000518
519 static RefVal makeReturnedOwned(unsigned Count) {
520 return RefVal(ReturnedOwned, Count);
521 }
522
523 static RefVal makeReturnedNotOwned() {
524 return RefVal(ReturnedNotOwned);
525 }
526
527 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000528
Ted Kremenekdb863712008-04-16 22:32:20 +0000529 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000530 static RefVal makeReleased() { return RefVal(Released); }
531 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
532 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000533
534 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000535
Ted Kremenek4fd88972008-04-17 18:12:53 +0000536 bool operator==(const RefVal& X) const {
537 return kind == X.kind && Cnt == X.Cnt;
538 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000539
Ted Kremenek4fd88972008-04-17 18:12:53 +0000540 void Profile(llvm::FoldingSetNodeID& ID) const {
541 ID.AddInteger((unsigned) kind);
542 ID.AddInteger(Cnt);
543 }
544
Ted Kremenekf3948042008-03-11 19:44:10 +0000545 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000546};
Ted Kremenekf3948042008-03-11 19:44:10 +0000547
548void RefVal::print(std::ostream& Out) const {
549 switch (getKind()) {
550 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000551 case Owned: {
552 Out << "Owned";
553 unsigned cnt = getCount();
554 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000555 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000556 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000557
Ted Kremenek61b9f872008-04-10 23:09:18 +0000558 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000559 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000560 unsigned cnt = getCount();
561 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000562 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000563 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000564
Ted Kremenek4fd88972008-04-17 18:12:53 +0000565 case ReturnedOwned: {
566 Out << "ReturnedOwned";
567 unsigned cnt = getCount();
568 if (cnt) Out << " (+ " << cnt << ")";
569 break;
570 }
571
572 case ReturnedNotOwned: {
573 Out << "ReturnedNotOwned";
574 unsigned cnt = getCount();
575 if (cnt) Out << " (+ " << cnt << ")";
576 break;
577 }
578
Ted Kremenekf3948042008-03-11 19:44:10 +0000579 case Released:
580 Out << "Released";
581 break;
582
Ted Kremenekdb863712008-04-16 22:32:20 +0000583 case ErrorLeak:
584 Out << "Leaked";
585 break;
586
Ted Kremenekf3948042008-03-11 19:44:10 +0000587 case ErrorUseAfterRelease:
588 Out << "Use-After-Release [ERROR]";
589 break;
590
591 case ErrorReleaseNotOwned:
592 Out << "Release of Not-Owned [ERROR]";
593 break;
594 }
595}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000596
Ted Kremenek13922612008-04-16 20:40:59 +0000597//===----------------------------------------------------------------------===//
598// Transfer functions.
599//===----------------------------------------------------------------------===//
600
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000601class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000602public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000603 // Type definitions.
604
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000605 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000606 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000607
Ted Kremenek8dd56462008-04-18 03:39:05 +0000608 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
609 ReleasesNotOwnedTy;
610
611 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
612
613 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000614 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000615
Ted Kremenekf3948042008-03-11 19:44:10 +0000616 class BindingsPrinter : public ValueState::CheckerStatePrinter {
617 public:
618 virtual void PrintCheckerState(std::ostream& Out, void* State,
619 const char* nl, const char* sep);
620 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000621
622private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000623 // Instance variables.
624
Ted Kremeneke5c30122008-04-29 05:13:59 +0000625 CFRefSummaryManager Summaries;
626 const bool GCEnabled;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000627 RefBFactoryTy RefBFactory;
628
Ted Kremenek73c750b2008-03-11 18:14:09 +0000629 UseAfterReleasesTy UseAfterReleases;
630 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000631 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000632
Ted Kremenekf3948042008-03-11 19:44:10 +0000633 BindingsPrinter Printer;
634
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000635 Selector RetainSelector;
636 Selector ReleaseSelector;
637
Ted Kremenek8dd56462008-04-18 03:39:05 +0000638public:
639
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000640 static RefBindings GetRefBindings(ValueState& StImpl) {
641 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
642 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000643
Ted Kremenek8dd56462008-04-18 03:39:05 +0000644private:
645
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000646 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
647 StImpl.CheckerState = B.getRoot();
648 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000649
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000650 RefBindings Remove(RefBindings B, SymbolID sym) {
651 return RefBFactory.Remove(B, sym);
652 }
653
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000654 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000655 RefVal::Kind& hasErr);
656
Ted Kremenekdb863712008-04-16 22:32:20 +0000657 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
658 GRStmtNodeBuilder<ValueState>& Builder,
659 Expr* NodeExpr, Expr* ErrorExpr,
660 ExplodedNode<ValueState>* Pred,
661 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000662 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000663
664 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
665 SymbolID sid, RefVal V, bool& hasLeak);
666
667 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
668 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000669
670public:
Ted Kremenek13922612008-04-16 20:40:59 +0000671
Ted Kremeneke5c30122008-04-29 05:13:59 +0000672 CFRefCount(ASTContext& Ctx, bool gcenabled)
Ted Kremenek377e2302008-04-29 05:33:51 +0000673 : Summaries(Ctx, gcenabled),
Ted Kremeneke5c30122008-04-29 05:13:59 +0000674 GCEnabled(gcenabled),
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000675 RetainSelector(GetUnarySelector("retain", Ctx)),
676 ReleaseSelector(GetUnarySelector("release", Ctx)) {}
677
Ted Kremenek8dd56462008-04-18 03:39:05 +0000678 virtual ~CFRefCount() {
679 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
680 delete I->second;
681 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000682
683 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000684
685 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
686 return &Printer;
687 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000688
689 // Calls.
690
691 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000692 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000693 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000694 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000695 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000696
Ted Kremenek85348202008-04-15 23:44:31 +0000697 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
698 GRExprEngine& Engine,
699 GRStmtNodeBuilder<ValueState>& Builder,
700 ObjCMessageExpr* ME,
701 ExplodedNode<ValueState>* Pred);
702
703 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
704 GRExprEngine& Engine,
705 GRStmtNodeBuilder<ValueState>& Builder,
706 ObjCMessageExpr* ME,
707 ExplodedNode<ValueState>* Pred);
708
Ted Kremenek13922612008-04-16 20:40:59 +0000709 // Stores.
710
711 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
712 GRExprEngine& Engine,
713 GRStmtNodeBuilder<ValueState>& Builder,
714 Expr* E, ExplodedNode<ValueState>* Pred,
715 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000716 // End-of-path.
717
718 virtual void EvalEndPath(GRExprEngine& Engine,
719 GREndPathNodeBuilder<ValueState>& Builder);
720
Ted Kremenek652adc62008-04-24 23:57:27 +0000721 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
722 GRExprEngine& Engine,
723 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +0000724 ExplodedNode<ValueState>* Pred,
725 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +0000726 ValueState* St,
727 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +0000728 // Return statements.
729
730 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
731 GRExprEngine& Engine,
732 GRStmtNodeBuilder<ValueState>& Builder,
733 ReturnStmt* S,
734 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +0000735
736 // Assumptions.
737
738 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
739 RVal Cond, bool Assumption, bool& isFeasible);
740
Ted Kremenekfa34b332008-04-09 01:10:13 +0000741 // Error iterators.
742
743 typedef UseAfterReleasesTy::iterator use_after_iterator;
744 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000745 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000746
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000747 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
748 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000749
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000750 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
751 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000752
753 leaks_iterator leaks_begin() { return Leaks.begin(); }
754 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000755};
756
757} // end anonymous namespace
758
Ted Kremenek8dd56462008-04-18 03:39:05 +0000759
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000760
761
Ted Kremenekf3948042008-03-11 19:44:10 +0000762void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
763 void* State, const char* nl,
764 const char* sep) {
765 RefBindings B((RefBindings::TreeTy*) State);
766
767 if (State)
768 Out << sep << nl;
769
770 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
771 Out << (*I).first << " : ";
772 (*I).second.print(Out);
773 Out << nl;
774 }
775}
776
Ted Kremenekf9561e52008-04-11 20:23:24 +0000777static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
778 return Summ ? Summ->getArg(idx) : DoNothing;
779}
780
781static inline RetEffect GetRetE(CFRefSummary* Summ) {
782 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
783}
784
Ted Kremenekdb863712008-04-16 22:32:20 +0000785void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
786 GRStmtNodeBuilder<ValueState>& Builder,
787 Expr* NodeExpr, Expr* ErrorExpr,
788 ExplodedNode<ValueState>* Pred,
789 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000790 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000791 Builder.BuildSinks = true;
792 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
793
794 if (!N) return;
795
796 switch (hasErr) {
797 default: assert(false);
798 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000799 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000800 break;
801
802 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +0000803 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000804 break;
805 }
806}
807
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000808void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000809 GRExprEngine& Eng,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000810 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000811 CallExpr* CE, RVal L,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000812 ExplodedNode<ValueState>* Pred) {
813
Ted Kremenek199e1a02008-03-12 21:06:49 +0000814 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000815
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000816 CFRefSummary* Summ = NULL;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000817
818 // Get the summary.
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000819
Ted Kremenek7ded73c2008-04-14 17:45:13 +0000820 if (isa<lval::FuncVal>(L)) {
821 lval::FuncVal FV = cast<lval::FuncVal>(L);
822 FunctionDecl* FD = FV.getDecl();
823 Summ = Summaries.getSummary(FD, Eng.getContext());
824 }
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000825
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000826 // Get the state.
827
828 ValueState* St = Builder.GetState(Pred);
829
830 // Evaluate the effects of the call.
831
832 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000833 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenekf9561e52008-04-11 20:23:24 +0000834
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000835 // This function has a summary. Evaluate the effect of the arguments.
836
837 unsigned idx = 0;
838
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000839 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000840 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000841
842 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
843 I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000844
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000845 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000846
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000847 if (isa<lval::SymbolVal>(V)) {
848 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +0000849 RefBindings B = GetRefBindings(StVals);
850
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000851 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000852 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000853 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000854
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000855 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000856 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000857 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +0000858 break;
859 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000860 }
Ted Kremenekb8873552008-04-11 20:51:02 +0000861 }
862 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
863
864 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
865 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000866 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +0000867 }
Ted Kremeneka5488462008-04-22 21:39:21 +0000868 else if (isa<nonlval::LValAsInteger>(V))
869 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000870 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000871
872 St = StateMgr.getPersistentState(StVals);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000873
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000874 if (hasErr) {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000875 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
876 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000877 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000878 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000879
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000880 // Finally, consult the summary for the return value.
881
Ted Kremenekf9561e52008-04-11 20:23:24 +0000882 RetEffect RE = GetRetE(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000883
884 switch (RE.getKind()) {
885 default:
886 assert (false && "Unhandled RetEffect."); break;
887
Ted Kremenek940b1d82008-04-10 23:44:06 +0000888 case RetEffect::NoRet:
Ted Kremenekf9561e52008-04-11 20:23:24 +0000889
890 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +0000891 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
892 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +0000893
894 if (CE->getType() != Eng.getContext().VoidTy) {
895 unsigned Count = Builder.getCurrentBlockCount();
896 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
897
898 RVal X = CE->getType()->isPointerType()
899 ? cast<RVal>(lval::SymbolVal(Sym))
900 : cast<RVal>(nonlval::SymbolVal(Sym));
901
902 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
903 }
904
Ted Kremenek940b1d82008-04-10 23:44:06 +0000905 break;
906
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000907 case RetEffect::Alias: {
908 unsigned idx = RE.getValue();
909 assert (idx < CE->getNumArgs());
910 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenek199e1a02008-03-12 21:06:49 +0000911 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000912 break;
913 }
914
915 case RetEffect::OwnedSymbol: {
916 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000917 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000918
919 ValueState StImpl = *St;
920 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000921 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000922
923 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
924 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000925 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000926
927 break;
928 }
929
930 case RetEffect::NotOwnedSymbol: {
931 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000932 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000933
934 ValueState StImpl = *St;
935 RefBindings B = GetRefBindings(StImpl);
936 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
937
938 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
939 CE, lval::SymbolVal(Sym),
Ted Kremenek199e1a02008-03-12 21:06:49 +0000940 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000941
942 break;
943 }
944 }
945
Ted Kremenek0e561a32008-03-21 21:30:14 +0000946 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000947}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000948
Ted Kremenek85348202008-04-15 23:44:31 +0000949
950void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
951 GRExprEngine& Eng,
952 GRStmtNodeBuilder<ValueState>& Builder,
953 ObjCMessageExpr* ME,
954 ExplodedNode<ValueState>* Pred) {
955
956 if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
957 GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred);
958}
959
960bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
961 GRExprEngine& Eng,
962 GRStmtNodeBuilder<ValueState>& Builder,
963 ObjCMessageExpr* ME,
964 ExplodedNode<ValueState>* Pred) {
Ted Kremenek377e2302008-04-29 05:33:51 +0000965
966 if (GCEnabled)
967 return true;
968
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000969 // Handle "toll-free bridging" of calls to "Release" and "Retain".
970
971 // FIXME: track the underlying object type associated so that we can
972 // flag illegal uses of toll-free bridging (or at least handle it
973 // at casts).
Ted Kremenek85348202008-04-15 23:44:31 +0000974
975 Selector S = ME->getSelector();
976
977 if (!S.isUnarySelector())
978 return true;
979
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000980 Expr* Receiver = ME->getReceiver();
981
982 if (!Receiver)
983 return true;
984
985 // Check if we are calling "Retain" or "Release".
986
987 bool isRetain = false;
988
989 if (S == RetainSelector)
990 isRetain = true;
991 else if (S != ReleaseSelector)
992 return true;
993
994 // We have "Retain" or "Release". Get the reference binding.
995
996 ValueStateManager& StateMgr = Eng.getStateManager();
997 ValueState* St = Builder.GetState(Pred);
998 RVal V = StateMgr.GetRVal(St, Receiver);
999
1000 if (!isa<lval::SymbolVal>(V))
1001 return true;
1002
1003 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1004 RefBindings B = GetRefBindings(*St);
1005
1006 RefBindings::TreeTy* T = B.SlimFind(Sym);
1007
1008 if (!T)
1009 return true;
1010
1011 RefVal::Kind hasErr = (RefVal::Kind) 0;
1012 B = Update(B, Sym, T->getValue().second, isRetain ? IncRef : DecRef, hasErr);
1013
1014 // Create a new state with the updated bindings.
1015
1016 ValueState StVals = *St;
1017 SetRefBindings(StVals, B);
1018 St = StateMgr.getPersistentState(StVals);
1019
1020 // Create an error node if it exists.
1021
1022 if (hasErr)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001023 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001024 else
1025 Builder.MakeNode(Dst, ME, Pred, St);
1026
1027 return false;
Ted Kremenek85348202008-04-15 23:44:31 +00001028}
1029
Ted Kremenek13922612008-04-16 20:40:59 +00001030// Stores.
1031
1032void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1033 GRExprEngine& Eng,
1034 GRStmtNodeBuilder<ValueState>& Builder,
1035 Expr* E, ExplodedNode<ValueState>* Pred,
1036 ValueState* St, RVal TargetLV, RVal Val) {
1037
1038 // Check if we have a binding for "Val" and if we are storing it to something
1039 // we don't understand or otherwise the value "escapes" the function.
1040
1041 if (!isa<lval::SymbolVal>(Val))
1042 return;
1043
1044 // Are we storing to something that causes the value to "escape"?
1045
1046 bool escapes = false;
1047
1048 if (!isa<lval::DeclVal>(TargetLV))
1049 escapes = true;
1050 else
1051 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1052
1053 if (!escapes)
1054 return;
1055
1056 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1057 RefBindings B = GetRefBindings(*St);
1058 RefBindings::TreeTy* T = B.SlimFind(Sym);
1059
1060 if (!T)
1061 return;
1062
Ted Kremenekdb863712008-04-16 22:32:20 +00001063 // Nuke the binding.
1064 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001065
1066 // Hand of the remaining logic to the parent implementation.
1067 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1068}
1069
Ted Kremenekdb863712008-04-16 22:32:20 +00001070
1071ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1072 SymbolID sid) {
1073 ValueState StImpl = *St;
1074 RefBindings B = GetRefBindings(StImpl);
1075 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1076 return VMgr.getPersistentState(StImpl);
1077}
1078
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001079// End-of-path.
1080
Ted Kremenekdb863712008-04-16 22:32:20 +00001081ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1082 ValueState* St, SymbolID sid,
1083 RefVal V, bool& hasLeak) {
1084
Ted Kremenek4fd88972008-04-17 18:12:53 +00001085 hasLeak = V.isOwned() ||
1086 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001087
1088 if (!hasLeak)
1089 return NukeBinding(VMgr, St, sid);
1090
1091 RefBindings B = GetRefBindings(*St);
1092 ValueState StImpl = *St;
1093 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1094 return VMgr.getPersistentState(StImpl);
1095}
1096
1097void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001098 GREndPathNodeBuilder<ValueState>& Builder) {
1099
Ted Kremenekdb863712008-04-16 22:32:20 +00001100 ValueState* St = Builder.getState();
1101 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001102
Ted Kremenekdb863712008-04-16 22:32:20 +00001103 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001104
Ted Kremenekdb863712008-04-16 22:32:20 +00001105 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1106 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001107
Ted Kremenekdb863712008-04-16 22:32:20 +00001108 St = HandleSymbolDeath(Eng.getStateManager(), St,
1109 (*I).first, (*I).second, hasLeak);
1110
1111 if (hasLeak) Leaked.push_back((*I).first);
1112 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001113
1114 if (Leaked.empty())
1115 return;
1116
Ted Kremenek8dd56462008-04-18 03:39:05 +00001117 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001118
Ted Kremenek652adc62008-04-24 23:57:27 +00001119 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001120 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001121
Ted Kremenek8dd56462008-04-18 03:39:05 +00001122 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1123 assert (!LeaksAtNode);
1124 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001125
1126 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1127 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001128 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001129}
1130
Ted Kremenek652adc62008-04-24 23:57:27 +00001131// Dead symbols.
1132
1133void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1134 GRExprEngine& Eng,
1135 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001136 ExplodedNode<ValueState>* Pred,
1137 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001138 ValueState* St,
1139 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001140
Ted Kremenek652adc62008-04-24 23:57:27 +00001141 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1142
1143 RefBindings B = GetRefBindings(*St);
1144 llvm::SmallVector<SymbolID, 10> Leaked;
1145
1146 for (ValueStateManager::DeadSymbolsTy::const_iterator
1147 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1148
1149 RefBindings::TreeTy* T = B.SlimFind(*I);
1150
1151 if (!T)
1152 continue;
1153
1154 bool hasLeak = false;
1155
1156 St = HandleSymbolDeath(Eng.getStateManager(), St,
1157 *I, T->getValue().second, hasLeak);
1158
1159 if (hasLeak) Leaked.push_back(*I);
1160 }
1161
1162 if (Leaked.empty())
1163 return;
1164
1165 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1166
1167 if (!N)
1168 return;
1169
1170 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1171 assert (!LeaksAtNode);
1172 LeaksAtNode = new std::vector<SymbolID>();
1173
1174 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1175 E = Leaked.end(); I != E; ++I)
1176 (*LeaksAtNode).push_back(*I);
1177}
1178
Ted Kremenek4fd88972008-04-17 18:12:53 +00001179 // Return statements.
1180
1181void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1182 GRExprEngine& Eng,
1183 GRStmtNodeBuilder<ValueState>& Builder,
1184 ReturnStmt* S,
1185 ExplodedNode<ValueState>* Pred) {
1186
1187 Expr* RetE = S->getRetValue();
1188 if (!RetE) return;
1189
1190 ValueStateManager& StateMgr = Eng.getStateManager();
1191 ValueState* St = Builder.GetState(Pred);
1192 RVal V = StateMgr.GetRVal(St, RetE);
1193
1194 if (!isa<lval::SymbolVal>(V))
1195 return;
1196
1197 // Get the reference count binding (if any).
1198 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1199 RefBindings B = GetRefBindings(*St);
1200 RefBindings::TreeTy* T = B.SlimFind(Sym);
1201
1202 if (!T)
1203 return;
1204
1205 // Change the reference count.
1206
1207 RefVal X = T->getValue().second;
1208
1209 switch (X.getKind()) {
1210
1211 case RefVal::Owned: {
1212 unsigned cnt = X.getCount();
1213 X = RefVal::makeReturnedOwned(cnt);
1214 break;
1215 }
1216
1217 case RefVal::NotOwned: {
1218 unsigned cnt = X.getCount();
1219 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1220 : RefVal::makeReturnedNotOwned();
1221 break;
1222 }
1223
1224 default:
1225 // None of the error states should be possible at this point.
1226 // A symbol could not have been leaked (yet) if we are returning it
1227 // (and thus it is still live), and the other errors are hard errors.
1228 assert(false);
1229 return;
1230 }
1231
1232 // Update the binding.
1233
1234 ValueState StImpl = *St;
1235 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1236 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1237}
1238
Ted Kremenekcb612922008-04-18 19:23:43 +00001239// Assumptions.
1240
1241ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1242 RVal Cond, bool Assumption,
1243 bool& isFeasible) {
1244
1245 // FIXME: We may add to the interface of EvalAssume the list of symbols
1246 // whose assumptions have changed. For now we just iterate through the
1247 // bindings and check if any of the tracked symbols are NULL. This isn't
1248 // too bad since the number of symbols we will track in practice are
1249 // probably small and EvalAssume is only called at branches and a few
1250 // other places.
1251
1252 RefBindings B = GetRefBindings(*St);
1253
1254 if (B.isEmpty())
1255 return St;
1256
1257 bool changed = false;
1258
1259 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1260
1261 // Check if the symbol is null (or equal to any constant).
1262 // If this is the case, stop tracking the symbol.
1263
1264 if (St->getSymVal(I.getKey())) {
1265 changed = true;
1266 B = RefBFactory.Remove(B, I.getKey());
1267 }
1268 }
1269
1270 if (!changed)
1271 return St;
1272
1273 ValueState StImpl = *St;
1274 StImpl.CheckerState = B.getRoot();
1275 return Eng.getStateManager().getPersistentState(StImpl);
1276}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001277
1278CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001279 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001280 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001281
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001282 // FIXME: This dispatch can potentially be sped up by unifiying it into
1283 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001284
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001285 switch (E) {
1286 default:
1287 assert (false && "Unhandled CFRef transition.");
1288
1289 case DoNothing:
Ted Kremenek65c91652008-04-29 05:44:10 +00001290 if (!GCEnabled && V.getKind() == RefVal::Released) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001291 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001292 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001293 break;
1294 }
1295
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001296 return B;
1297
1298 case IncRef:
1299 switch (V.getKind()) {
1300 default:
1301 assert(false);
1302
1303 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001304 V = RefVal::makeOwned(V.getCount()+1);
1305 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001306
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001307 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001308 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001309 break;
1310
1311 case RefVal::Released:
Ted Kremenek65c91652008-04-29 05:44:10 +00001312 if (GCEnabled)
1313 V = RefVal::makeOwned();
1314 else {
1315 V = RefVal::makeUseAfterRelease();
1316 hasErr = V.getKind();
1317 }
1318
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001319 break;
1320 }
1321
Ted Kremenek940b1d82008-04-10 23:44:06 +00001322 break;
1323
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001324 case DecRef:
1325 switch (V.getKind()) {
1326 default:
1327 assert (false);
1328
1329 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001330 unsigned Count = V.getCount();
1331 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001332 break;
1333 }
1334
Ted Kremenek61b9f872008-04-10 23:09:18 +00001335 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001336 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001337
Ted Kremenek4fd88972008-04-17 18:12:53 +00001338 if (Count > 0)
1339 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001340 else {
1341 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001342 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001343 }
1344
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001345 break;
1346 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001347
1348 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001349 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001350 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001351 break;
1352 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001353
1354 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001355 }
1356
1357 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001358}
1359
Ted Kremenekfa34b332008-04-09 01:10:13 +00001360
1361//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001362// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001363//===----------------------------------------------------------------------===//
1364
Ted Kremenek8dd56462008-04-18 03:39:05 +00001365namespace {
1366
1367 //===-------------===//
1368 // Bug Descriptions. //
1369 //===-------------===//
1370
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001371 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001372 protected:
1373 CFRefCount& TF;
1374
1375 public:
1376 CFRefBug(CFRefCount& tf) : TF(tf) {}
1377 };
1378
1379 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1380 public:
1381 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1382
1383 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001384 return "Core Foundation: Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001385 }
1386 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001387 return "Reference-counted object is used"
1388 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001389 }
1390
1391 virtual void EmitWarnings(BugReporter& BR);
1392
1393 };
1394
1395 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1396 public:
1397 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1398
1399 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001400 return "Core Foundation: Release of non-owned object";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001401 }
1402 virtual const char* getDescription() const {
1403 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001404 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001405 "The object is not owned at this point by the caller.";
1406 }
1407
1408 virtual void EmitWarnings(BugReporter& BR);
1409 };
1410
1411 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1412 public:
1413 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1414
1415 virtual const char* getName() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001416 return "Core Foundation: Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001417 }
1418
1419 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001420 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001421 }
1422
1423 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekcb612922008-04-18 19:23:43 +00001424 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001425 };
1426
1427 //===---------===//
1428 // Bug Reports. //
1429 //===---------===//
1430
1431 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1432 SymbolID Sym;
1433 public:
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001434 CFRefReport(BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001435 : RangedBugReport(D, n), Sym(sym) {}
1436
1437 virtual ~CFRefReport() {}
1438
1439
1440 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1441 ExplodedNode<ValueState>* PrevN,
1442 ExplodedGraph<ValueState>& G,
1443 BugReporter& BR);
1444 };
1445
1446
1447} // end anonymous namespace
1448
1449void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
1450 GRSimpleVals::RegisterChecks(Eng);
1451 Eng.Register(new UseAfterRelease(*this));
1452 Eng.Register(new BadRelease(*this));
1453 Eng.Register(new Leak(*this));
1454}
1455
1456PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1457 ExplodedNode<ValueState>* PrevN,
1458 ExplodedGraph<ValueState>& G,
1459 BugReporter& BR) {
1460
1461 // Check if the type state has changed.
1462
1463 ValueState* PrevSt = PrevN->getState();
1464 ValueState* CurrSt = N->getState();
1465
1466 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1467 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1468
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001469 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1470 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001471
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001472 if (!CurrT)
1473 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001474
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001475 const char* Msg = NULL;
1476 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001477
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001478 if (!PrevT) {
1479
1480 // Check for the point where we start tracking the value.
1481
1482 if (CurrV.isOwned())
1483 Msg = "Function call returns 'Owned' Core Foundation object.";
1484 else {
1485 assert (CurrV.isNotOwned());
1486 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1487 }
1488
1489 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1490 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1491 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1492
1493 if (Expr* Exp = dyn_cast<Expr>(S))
1494 P->addRange(Exp->getSourceRange());
1495
1496 return P;
1497 }
1498
1499 // Determine if the typestate has changed.
1500
1501 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1502
1503 if (PrevV == CurrV)
1504 return NULL;
1505
1506 // The typestate has changed.
1507
1508 std::ostringstream os;
1509
1510 switch (CurrV.getKind()) {
1511 case RefVal::Owned:
1512 case RefVal::NotOwned:
1513 assert (PrevV.getKind() == CurrV.getKind());
1514
1515 if (PrevV.getCount() > CurrV.getCount())
1516 os << "Reference count decremented.";
1517 else
1518 os << "Reference count incremented.";
1519
Ted Kremenek79c140b2008-04-18 05:32:44 +00001520 if (CurrV.getCount()) {
1521 os << " Object has +" << CurrV.getCount();
1522
1523 if (CurrV.getCount() > 1)
1524 os << " reference counts.";
1525 else
1526 os << " reference count.";
1527 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001528
1529 Msg = os.str().c_str();
1530
1531 break;
1532
1533 case RefVal::Released:
1534 Msg = "Object released.";
1535 break;
1536
1537 case RefVal::ReturnedOwned:
1538 Msg = "Object returned to caller. "
1539 "Caller gets ownership of object.";
1540 break;
1541
1542 case RefVal::ReturnedNotOwned:
1543 Msg = "Object returned to caller. "
1544 "Caller does not get ownership of object.";
1545 break;
1546
1547 default:
1548 return NULL;
1549 }
1550
1551 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1552 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1553 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1554
1555 // Add the range by scanning the children of the statement for any bindings
1556 // to Sym.
1557
1558 ValueStateManager& VSM = BR.getEngine().getStateManager();
1559
1560 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1561 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1562 RVal X = VSM.GetRVal(CurrSt, Exp);
1563
1564 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1565 if (SV->getSymbol() == Sym) {
1566 P->addRange(Exp->getSourceRange()); break;
1567 }
1568 }
1569
1570 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001571}
1572
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001573void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001574
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001575 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1576 E = TF.use_after_end(); I != E; ++I) {
1577
Ted Kremenek8dd56462008-04-18 03:39:05 +00001578 CFRefReport report(*this, I->first, I->second.second);
1579 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00001580 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001581 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001582}
1583
1584void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00001585
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001586 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1587 E = TF.bad_release_end(); I != E; ++I) {
1588
Ted Kremenek8dd56462008-04-18 03:39:05 +00001589 CFRefReport report(*this, I->first, I->second.second);
1590 report.addRange(I->second.first->getSourceRange());
1591 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001592 }
1593}
Ted Kremenekfa34b332008-04-09 01:10:13 +00001594
Ted Kremenek989d5192008-04-17 23:43:50 +00001595void Leak::EmitWarnings(BugReporter& BR) {
1596
1597 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1598 E = TF.leaks_end(); I != E; ++I) {
1599
Ted Kremenek8dd56462008-04-18 03:39:05 +00001600 std::vector<SymbolID>& SymV = *(I->second);
1601 unsigned n = SymV.size();
1602
1603 for (unsigned i = 0; i < n; ++i) {
1604 CFRefReport report(*this, I->first, SymV[i]);
1605 BR.EmitWarning(report);
1606 }
Ted Kremenek989d5192008-04-17 23:43:50 +00001607 }
1608}
1609
Ted Kremenekcb612922008-04-18 19:23:43 +00001610void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1611 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1612 I!=E; ++I)
1613 Nodes.push_back(I->first);
1614}
1615
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001616//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00001617// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001618//===----------------------------------------------------------------------===//
1619
Ted Kremeneke5c30122008-04-29 05:13:59 +00001620GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled) {
1621 return new CFRefCount(Ctx, GCEnabled);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00001622}