blob: bfd998859b540bff9dd4ec9b889330f49a480c91 [file] [log] [blame]
Chris Lattnerbe1a7a02008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek827f93b2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif2224fcb2008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek827f93b2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremeneka7338b42008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenekfe30beb2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenekfe4d2312008-05-01 23:13:35 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenekdd0126b2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek827f93b2008-03-06 00:08:09 +000020#include "clang/Analysis/LocalCheckers.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000021#include "clang/Analysis/PathDiagnostic.h"
22#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremeneka7338b42008-03-11 06:39:11 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek10fe66d2008-04-09 01:10:13 +000026#include "llvm/Support/Compiler.h"
Ted Kremenek3b11f7a2008-03-11 19:44:10 +000027#include <ostream>
Ted Kremeneka8503952008-04-18 04:55:01 +000028#include <sstream>
Ted Kremenek827f93b2008-03-06 00:08:09 +000029
30using namespace clang;
31
Ted Kremenek7d421f32008-04-09 23:49:11 +000032//===----------------------------------------------------------------------===//
Ted Kremenekd9ccf682008-04-17 18:12:53 +000033// Utility functions.
34//===----------------------------------------------------------------------===//
35
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +000036static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenekd9ccf682008-04-17 18:12:53 +000037 IdentifierInfo* II = &Ctx.Idents.get(name);
38 return Ctx.Selectors.getSelector(0, &II);
39}
40
41//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +000042// Symbolic Evaluation of Reference Counting Logic
43//===----------------------------------------------------------------------===//
44
Ted Kremeneka7338b42008-03-11 06:39:11 +000045namespace {
46 enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenekae855d42008-04-24 17:22:33 +000047 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremeneka7338b42008-03-11 06:39:11 +000048}
Ted Kremenek827f93b2008-03-06 00:08:09 +000049
Ted Kremeneka7338b42008-03-11 06:39:11 +000050namespace llvm {
51 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremeneka4c74292008-04-10 22:58:08 +000052 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenekae855d42008-04-24 17:22:33 +000053 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
54 ID.AddInteger(I->first);
55 ID.AddInteger((unsigned) I->second);
56 }
Ted Kremeneka4c74292008-04-10 22:58:08 +000057 }
Ted Kremeneka7338b42008-03-11 06:39:11 +000058 };
59} // end llvm namespace
60
61namespace {
Ted Kremenek827f93b2008-03-06 00:08:09 +000062
Ted Kremeneka7338b42008-03-11 06:39:11 +000063class RetEffect {
64public:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000065 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
66 NotOwnedSymbol = 0x3 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000067
68private:
69 unsigned Data;
Ted Kremeneka4c74292008-04-10 22:58:08 +000070 RetEffect(Kind k, unsigned D) { Data = (D << 2) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000071
Ted Kremeneka7338b42008-03-11 06:39:11 +000072public:
73
74 Kind getKind() const { return (Kind) (Data & 0x3); }
75
76 unsigned getValue() const {
77 assert(getKind() == Alias);
Ted Kremeneka4c74292008-04-10 22:58:08 +000078 return Data >> 2;
Ted Kremeneka7338b42008-03-11 06:39:11 +000079 }
Ted Kremenekffefc352008-04-11 22:25:11 +000080
Ted Kremeneka7338b42008-03-11 06:39:11 +000081 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000082
Ted Kremeneka7338b42008-03-11 06:39:11 +000083 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000084
Ted Kremeneka7338b42008-03-11 06:39:11 +000085 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
86
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000087 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
88
Ted Kremeneka7338b42008-03-11 06:39:11 +000089 operator Kind() const { return getKind(); }
90
91 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
92};
93
94
95class CFRefSummary : public llvm::FoldingSetNode {
96 ArgEffects* Args;
97 RetEffect Ret;
98public:
99
100 CFRefSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
101
102 unsigned getNumArgs() const { return Args->size(); }
103
Ted Kremenek0d721572008-03-11 17:48:22 +0000104 ArgEffect getArg(unsigned idx) const {
Ted Kremenekae855d42008-04-24 17:22:33 +0000105 if (!Args)
106 return DoNothing;
107
108 // If Args is present, it is likely to contain only 1 element.
109 // Just do a linear search. Do it from the back because functions with
110 // large numbers of arguments will be tail heavy with respect to which
111 // argument they actually modify with respect to the reference count.
112
113 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
114 I!=E; ++I) {
115
116 if (idx > I->first)
117 return DoNothing;
118
119 if (idx == I->first)
120 return I->second;
121 }
122
123 return DoNothing;
Ted Kremenek0d721572008-03-11 17:48:22 +0000124 }
125
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000126 RetEffect getRet() const {
127 return Ret;
128 }
129
Ted Kremeneka7338b42008-03-11 06:39:11 +0000130 typedef ArgEffects::const_iterator arg_iterator;
131
132 arg_iterator begin_args() const { return Args->begin(); }
133 arg_iterator end_args() const { return Args->end(); }
134
135 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
136 ID.AddPointer(A);
137 ID.Add(R);
138 }
139
140 void Profile(llvm::FoldingSetNodeID& ID) const {
141 Profile(ID, Args, Ret);
142 }
143};
144
145
146class CFRefSummaryManager {
147 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> > AESetTy;
148 typedef llvm::FoldingSet<CFRefSummary> SummarySetTy;
149 typedef llvm::DenseMap<FunctionDecl*, CFRefSummary*> SummaryMapTy;
150
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000151 ASTContext& Ctx;
152 const bool GCEnabled;
153
Ted Kremeneka4c74292008-04-10 22:58:08 +0000154 SummarySetTy SummarySet;
155 SummaryMapTy SummaryMap;
156 AESetTy AESet;
157 llvm::BumpPtrAllocator BPAlloc;
Ted Kremenekae855d42008-04-24 17:22:33 +0000158 ArgEffects ScratchArgs;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000159
160 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000161
Ted Kremenek562c1302008-05-05 16:51:50 +0000162 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
163 CFRefSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000164
Ted Kremenek562c1302008-05-05 16:51:50 +0000165 CFRefSummary* getNSSummary(FunctionDecl* FD, const char* FName);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000166 CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
167
Ted Kremenek562c1302008-05-05 16:51:50 +0000168 CFRefSummary* getCFSummaryCreateRule(FunctionDecl* FD);
169 CFRefSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000170
171 CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenekae855d42008-04-24 17:22:33 +0000172
Ted Kremeneka7338b42008-03-11 06:39:11 +0000173public:
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000174 CFRefSummaryManager(ASTContext& ctx, bool gcenabled)
175 : Ctx(ctx), GCEnabled(gcenabled) {}
176
Ted Kremeneka7338b42008-03-11 06:39:11 +0000177 ~CFRefSummaryManager();
178
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000179 CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000180};
181
182} // end anonymous namespace
183
184//===----------------------------------------------------------------------===//
185// Implementation of checker data structures.
186//===----------------------------------------------------------------------===//
187
188CFRefSummaryManager::~CFRefSummaryManager() {
189
190 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
191 // mitigating the need to do explicit cleanup of the
192 // Argument-Effect summaries.
193
194 for (AESetTy::iterator I = AESet.begin(), E = AESet.end(); I!=E; ++I)
195 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000196}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000197
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000198ArgEffects* CFRefSummaryManager::getArgEffects() {
199
Ted Kremenekae855d42008-04-24 17:22:33 +0000200 if (ScratchArgs.empty())
201 return NULL;
202
203 // Compute a profile for a non-empty ScratchArgs.
204
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000205 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000206
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000207 profile.Add(ScratchArgs);
208 void* InsertPos;
209
Ted Kremenekae855d42008-04-24 17:22:33 +0000210 // Look up the uniqued copy, or create a new one.
211
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000212 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
213 AESet.FindNodeOrInsertPos(profile, InsertPos);
214
Ted Kremenekae855d42008-04-24 17:22:33 +0000215 if (E) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000216 ScratchArgs.clear();
217 return &E->getValue();
218 }
219
220 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
221 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
222
223 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
224 AESet.InsertNode(E, InsertPos);
225
226 ScratchArgs.clear();
227 return &E->getValue();
228}
229
230CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
231 RetEffect RE) {
232
Ted Kremenekae855d42008-04-24 17:22:33 +0000233 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000234 llvm::FoldingSetNodeID profile;
235 CFRefSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000236
Ted Kremenekae855d42008-04-24 17:22:33 +0000237 // Look up the uniqued summary, or create one if it doesn't exist.
238 void* InsertPos;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000239 CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
240
241 if (Summ)
242 return Summ;
243
Ted Kremenekae855d42008-04-24 17:22:33 +0000244 // Create the summary and return it.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000245 Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
246 new (Summ) CFRefSummary(AE, RE);
247 SummarySet.InsertNode(Summ, InsertPos);
248
249 return Summ;
250}
251
252
253CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
254 ASTContext& Ctx) {
255
256 SourceLocation Loc = FD->getLocation();
257
258 if (!Loc.isFileID())
259 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000260
Ted Kremenekae855d42008-04-24 17:22:33 +0000261 // Look up a summary in our cache of FunctionDecls -> Summaries.
262 SummaryMapTy::iterator I = SummaryMap.find(FD);
263
264 if (I != SummaryMap.end())
265 return I->second;
266
267 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000268 const char* FName = FD->getIdentifier()->getName();
269
Ted Kremenek562c1302008-05-05 16:51:50 +0000270 CFRefSummary *S = 0;
271
272 if (FName[0] == 'C' && FName[1] == 'F')
273 S = getCFSummary(FD, FName);
274 else if (FName[0] == 'N' && FName[1] == 'S')
275 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000276
Ted Kremenek562c1302008-05-05 16:51:50 +0000277 SummaryMap[FD] = S;
278 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000279}
280
Ted Kremenek562c1302008-05-05 16:51:50 +0000281CFRefSummary* CFRefSummaryManager::getNSSummary(FunctionDecl* FD,
282 const char* FName) {
283 FName += 2;
284
285 if (strcmp(FName, "MakeCollectable") == 0)
286 return getUnarySummary(FD, cfmakecollectable);
287
288 return 0;
289}
290
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000291CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
292 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000293
294 FName += 2;
295
296 if (strcmp(FName, "Retain") == 0)
297 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000298
Ted Kremenek562c1302008-05-05 16:51:50 +0000299 if (strcmp(FName, "Release") == 0)
300 return getUnarySummary(FD, cfrelease);
301
302 if (strcmp(FName, "MakeCollectable") == 0)
303 return getUnarySummary(FD, cfmakecollectable);
304
305 if (strstr(FName, "Create") || strstr(FName, "Copy"))
306 return getCFSummaryCreateRule(FD);
307
308 if (strstr(FName, "Get"))
309 return getCFSummaryGetRule(FD);
310
311 return 0;
312}
313
314CFRefSummary*
315CFRefSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000316
317 FunctionTypeProto* FT =
318 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
319
Ted Kremenek562c1302008-05-05 16:51:50 +0000320 if (FT) {
321
322 if (FT->getNumArgs() != 1)
323 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000324
Ted Kremenek562c1302008-05-05 16:51:50 +0000325 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
326
327 if (!ArgT)
328 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000329
Ted Kremenek562c1302008-05-05 16:51:50 +0000330 if (!ArgT->isPointerType())
331 return NULL;
332 }
Ted Kremenek33661802008-05-01 21:31:50 +0000333
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000334 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000335
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000336 switch (func) {
337 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000338 ScratchArgs.push_back(std::make_pair(0, IncRef));
339 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
340 }
341
342 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000343 ScratchArgs.push_back(std::make_pair(0, DecRef));
344 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
345 }
346
347 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000348 if (GCEnabled)
349 ScratchArgs.push_back(std::make_pair(0, DecRef));
350
Ted Kremenek562c1302008-05-05 16:51:50 +0000351 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000352 }
353
354 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000355 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000356 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000357}
358
359static bool isCFRefType(QualType T) {
360
361 if (!T->isPointerType())
362 return false;
363
364 // Check the typedef for the name "CF" and the substring "Ref".
365
366 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
367
368 if (!TD)
369 return false;
370
371 const char* TDName = TD->getDecl()->getIdentifier()->getName();
372 assert (TDName);
373
374 if (TDName[0] != 'C' || TDName[1] != 'F')
375 return false;
376
377 if (strstr(TDName, "Ref") == 0)
378 return false;
379
380 return true;
381}
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000382
383CFRefSummary*
Ted Kremenek562c1302008-05-05 16:51:50 +0000384CFRefSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000385
Ted Kremenek562c1302008-05-05 16:51:50 +0000386 FunctionTypeProto* FT =
387 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
388
389 if (FT && !isCFRefType(FT->getResultType()))
390 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000391
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000392 // FIXME: Add special-cases for functions that retain/release. For now
393 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000394
395 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000396 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
397}
398
399CFRefSummary*
Ted Kremenek562c1302008-05-05 16:51:50 +0000400CFRefSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000401
Ted Kremenek562c1302008-05-05 16:51:50 +0000402 FunctionTypeProto* FT =
403 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000404
Ted Kremenek562c1302008-05-05 16:51:50 +0000405 if (FT) {
406 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000407
Ted Kremenek562c1302008-05-05 16:51:50 +0000408 // FIXME: For now we assume that all pointer types returned are referenced
409 // counted. Since this is the "Get" rule, we assume non-ownership, which
410 // works fine for things that are not reference counted. We do this because
411 // some generic data structures return "void*". We need something better
412 // in the future.
413
414 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
415 return 0;
416 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000417
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000418 // FIXME: Add special-cases for functions that retain/release. For now
419 // just handle the default case.
420
Ted Kremenekae855d42008-04-24 17:22:33 +0000421 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000422 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
423}
424
Ted Kremeneka7338b42008-03-11 06:39:11 +0000425//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000426// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000427//===----------------------------------------------------------------------===//
428
Ted Kremeneka7338b42008-03-11 06:39:11 +0000429namespace {
430
Ted Kremenek7d421f32008-04-09 23:49:11 +0000431class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000432public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000433
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000434 enum Kind {
435 Owned = 0, // Owning reference.
436 NotOwned, // Reference is not owned by still valid (not freed).
437 Released, // Object has been released.
438 ReturnedOwned, // Returned object passes ownership to caller.
439 ReturnedNotOwned, // Return object does not pass ownership to caller.
440 ErrorUseAfterRelease, // Object used after released.
441 ErrorReleaseNotOwned, // Release of an object that was not owned.
442 ErrorLeak // A memory leak due to excessive reference counts.
443 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000444
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000445private:
446
447 Kind kind;
448 unsigned Cnt;
449
450 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
451
452 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000453
454public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000455
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000456 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000457
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000458 unsigned getCount() const { return Cnt; }
459
460 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000461
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000462 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
463
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000464 static bool isLeak(Kind k) { return k == ErrorLeak; }
465
Ted Kremenekffefc352008-04-11 22:25:11 +0000466 bool isOwned() const {
467 return getKind() == Owned;
468 }
469
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000470 bool isNotOwned() const {
471 return getKind() == NotOwned;
472 }
473
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000474 bool isReturnedOwned() const {
475 return getKind() == ReturnedOwned;
476 }
477
478 bool isReturnedNotOwned() const {
479 return getKind() == ReturnedNotOwned;
480 }
481
482 bool isNonLeakError() const {
483 Kind k = getKind();
484 return isError(k) && !isLeak(k);
485 }
486
487 // State creation: normal state.
488
Ted Kremenekc4f81022008-04-10 23:09:18 +0000489 static RefVal makeOwned(unsigned Count = 0) {
490 return RefVal(Owned, Count);
491 }
492
493 static RefVal makeNotOwned(unsigned Count = 0) {
494 return RefVal(NotOwned, Count);
495 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000496
497 static RefVal makeReturnedOwned(unsigned Count) {
498 return RefVal(ReturnedOwned, Count);
499 }
500
501 static RefVal makeReturnedNotOwned() {
502 return RefVal(ReturnedNotOwned);
503 }
504
505 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000506
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000507 static RefVal makeLeak() { return RefVal(ErrorLeak); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000508 static RefVal makeReleased() { return RefVal(Released); }
509 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
510 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000511
512 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000513
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000514 bool operator==(const RefVal& X) const {
515 return kind == X.kind && Cnt == X.Cnt;
516 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000517
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000518 void Profile(llvm::FoldingSetNodeID& ID) const {
519 ID.AddInteger((unsigned) kind);
520 ID.AddInteger(Cnt);
521 }
522
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000523 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000524};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000525
526void RefVal::print(std::ostream& Out) const {
527 switch (getKind()) {
528 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000529 case Owned: {
530 Out << "Owned";
531 unsigned cnt = getCount();
532 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000533 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000534 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000535
Ted Kremenekc4f81022008-04-10 23:09:18 +0000536 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000537 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000538 unsigned cnt = getCount();
539 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000540 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000541 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000542
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000543 case ReturnedOwned: {
544 Out << "ReturnedOwned";
545 unsigned cnt = getCount();
546 if (cnt) Out << " (+ " << cnt << ")";
547 break;
548 }
549
550 case ReturnedNotOwned: {
551 Out << "ReturnedNotOwned";
552 unsigned cnt = getCount();
553 if (cnt) Out << " (+ " << cnt << ")";
554 break;
555 }
556
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000557 case Released:
558 Out << "Released";
559 break;
560
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000561 case ErrorLeak:
562 Out << "Leaked";
563 break;
564
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000565 case ErrorUseAfterRelease:
566 Out << "Use-After-Release [ERROR]";
567 break;
568
569 case ErrorReleaseNotOwned:
570 Out << "Release of Not-Owned [ERROR]";
571 break;
572 }
573}
Ted Kremenek0d721572008-03-11 17:48:22 +0000574
Ted Kremenek7aef4842008-04-16 20:40:59 +0000575//===----------------------------------------------------------------------===//
576// Transfer functions.
577//===----------------------------------------------------------------------===//
578
Ted Kremenek7d421f32008-04-09 23:49:11 +0000579class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000580public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000581 // Type definitions.
582
Ted Kremenek0d721572008-03-11 17:48:22 +0000583 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000584 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000585
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000586 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
587 ReleasesNotOwnedTy;
588
589 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
590
591 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000592 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000593
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000594 class BindingsPrinter : public ValueState::CheckerStatePrinter {
595 public:
596 virtual void PrintCheckerState(std::ostream& Out, void* State,
597 const char* nl, const char* sep);
598 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000599
600private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000601 // Instance variables.
602
Ted Kremenek102d42e2008-04-29 05:13:59 +0000603 CFRefSummaryManager Summaries;
Ted Kremenek2f62f352008-05-02 18:01:49 +0000604 const bool GCEnabled;
605 const bool EmitStandardWarnings;
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000606 const LangOptions& LOpts;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000607 RefBFactoryTy RefBFactory;
608
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000609 UseAfterReleasesTy UseAfterReleases;
610 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000611 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000612
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000613 BindingsPrinter Printer;
614
Ted Kremenek1feab292008-04-16 04:28:53 +0000615 Selector RetainSelector;
616 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000617 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000618
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000619public:
620
Ted Kremeneka7338b42008-03-11 06:39:11 +0000621 static RefBindings GetRefBindings(ValueState& StImpl) {
622 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
623 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000624
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000625private:
626
Ted Kremeneka7338b42008-03-11 06:39:11 +0000627 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
628 StImpl.CheckerState = B.getRoot();
629 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000630
Ted Kremeneka7338b42008-03-11 06:39:11 +0000631 RefBindings Remove(RefBindings B, SymbolID sym) {
632 return RefBFactory.Remove(B, sym);
633 }
634
Ted Kremenek0d721572008-03-11 17:48:22 +0000635 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000636 RefVal::Kind& hasErr);
637
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000638 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
639 GRStmtNodeBuilder<ValueState>& Builder,
640 Expr* NodeExpr, Expr* ErrorExpr,
641 ExplodedNode<ValueState>* Pred,
642 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000643 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000644
645 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
646 SymbolID sid, RefVal V, bool& hasLeak);
647
648 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
649 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000650
651public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000652
Ted Kremenek2f62f352008-05-02 18:01:49 +0000653 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
654 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000655 : Summaries(Ctx, gcenabled),
Ted Kremenek102d42e2008-04-29 05:13:59 +0000656 GCEnabled(gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000657 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000658 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000659 RetainSelector(GetNullarySelector("retain", Ctx)),
660 ReleaseSelector(GetNullarySelector("release", Ctx)),
661 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000662
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000663 virtual ~CFRefCount() {
664 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
665 delete I->second;
666 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000667
668 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000669
670 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
671 return &Printer;
672 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000673
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000674 bool isGCEnabled() const { return GCEnabled; }
675 const LangOptions& getLangOptions() const { return LOpts; }
676
Ted Kremeneka7338b42008-03-11 06:39:11 +0000677 // Calls.
678
679 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000680 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000681 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000682 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000683 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000684
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000685 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
686 GRExprEngine& Engine,
687 GRStmtNodeBuilder<ValueState>& Builder,
688 ObjCMessageExpr* ME,
689 ExplodedNode<ValueState>* Pred);
690
691 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
692 GRExprEngine& Engine,
693 GRStmtNodeBuilder<ValueState>& Builder,
694 ObjCMessageExpr* ME,
695 ExplodedNode<ValueState>* Pred);
696
Ted Kremenek7aef4842008-04-16 20:40:59 +0000697 // Stores.
698
699 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
700 GRExprEngine& Engine,
701 GRStmtNodeBuilder<ValueState>& Builder,
702 Expr* E, ExplodedNode<ValueState>* Pred,
703 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000704 // End-of-path.
705
706 virtual void EvalEndPath(GRExprEngine& Engine,
707 GREndPathNodeBuilder<ValueState>& Builder);
708
Ted Kremenek541db372008-04-24 23:57:27 +0000709 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
710 GRExprEngine& Engine,
711 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000712 ExplodedNode<ValueState>* Pred,
713 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000714 ValueState* St,
715 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000716 // Return statements.
717
718 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
719 GRExprEngine& Engine,
720 GRStmtNodeBuilder<ValueState>& Builder,
721 ReturnStmt* S,
722 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +0000723
724 // Assumptions.
725
726 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
727 RVal Cond, bool Assumption, bool& isFeasible);
728
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000729 // Error iterators.
730
731 typedef UseAfterReleasesTy::iterator use_after_iterator;
732 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000733 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000734
Ted Kremenek7d421f32008-04-09 23:49:11 +0000735 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
736 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000737
Ted Kremenek7d421f32008-04-09 23:49:11 +0000738 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
739 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000740
741 leaks_iterator leaks_begin() { return Leaks.begin(); }
742 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000743};
744
745} // end anonymous namespace
746
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000747
Ted Kremenek7d421f32008-04-09 23:49:11 +0000748
749
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000750void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
751 void* State, const char* nl,
752 const char* sep) {
753 RefBindings B((RefBindings::TreeTy*) State);
754
755 if (State)
756 Out << sep << nl;
757
758 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
759 Out << (*I).first << " : ";
760 (*I).second.print(Out);
761 Out << nl;
762 }
763}
764
Ted Kremenek455dd862008-04-11 20:23:24 +0000765static inline ArgEffect GetArgE(CFRefSummary* Summ, unsigned idx) {
766 return Summ ? Summ->getArg(idx) : DoNothing;
767}
768
769static inline RetEffect GetRetE(CFRefSummary* Summ) {
770 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
771}
772
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000773void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
774 GRStmtNodeBuilder<ValueState>& Builder,
775 Expr* NodeExpr, Expr* ErrorExpr,
776 ExplodedNode<ValueState>* Pred,
777 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000778 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000779 Builder.BuildSinks = true;
780 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
781
782 if (!N) return;
783
784 switch (hasErr) {
785 default: assert(false);
786 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000787 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000788 break;
789
790 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000791 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000792 break;
793 }
794}
795
Ted Kremenek827f93b2008-03-06 00:08:09 +0000796void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000797 GRExprEngine& Eng,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000798 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000799 CallExpr* CE, RVal L,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000800 ExplodedNode<ValueState>* Pred) {
801
Ted Kremenekce0767f2008-03-12 21:06:49 +0000802 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000803
Ted Kremenek73ba0472008-04-14 17:45:13 +0000804 CFRefSummary* Summ = NULL;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000805
806 // Get the summary.
Ted Kremenek827f93b2008-03-06 00:08:09 +0000807
Ted Kremenek73ba0472008-04-14 17:45:13 +0000808 if (isa<lval::FuncVal>(L)) {
809 lval::FuncVal FV = cast<lval::FuncVal>(L);
810 FunctionDecl* FD = FV.getDecl();
811 Summ = Summaries.getSummary(FD, Eng.getContext());
812 }
Ted Kremenek827f93b2008-03-06 00:08:09 +0000813
Ted Kremeneka7338b42008-03-11 06:39:11 +0000814 // Get the state.
815
816 ValueState* St = Builder.GetState(Pred);
817
818 // Evaluate the effects of the call.
819
820 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000821 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek455dd862008-04-11 20:23:24 +0000822
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000823 // This function has a summary. Evaluate the effect of the arguments.
824
825 unsigned idx = 0;
826
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000827 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000828 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000829
830 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
831 I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000832
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000833 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000834
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000835 if (isa<lval::SymbolVal>(V)) {
836 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000837 RefBindings B = GetRefBindings(StVals);
838
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000839 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000840 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000841 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000842
Ted Kremenek1feab292008-04-16 04:28:53 +0000843 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000844 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000845 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000846 break;
847 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000848 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000849 }
850 else if (isa<LVal>(V)) { // Nuke all arguments passed by reference.
851
852 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
853 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000854 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000855 }
Ted Kremenekbe621292008-04-22 21:39:21 +0000856 else if (isa<nonlval::LValAsInteger>(V))
857 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000858 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000859
860 St = StateMgr.getPersistentState(StVals);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000861
Ted Kremenek1feab292008-04-16 04:28:53 +0000862 if (hasErr) {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000863 ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
864 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000865 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000866 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000867
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000868 // Finally, consult the summary for the return value.
869
Ted Kremenek455dd862008-04-11 20:23:24 +0000870 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000871
872 switch (RE.getKind()) {
873 default:
874 assert (false && "Unhandled RetEffect."); break;
875
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000876 case RetEffect::NoRet:
Ted Kremenek455dd862008-04-11 20:23:24 +0000877
878 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000879 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
880 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000881
882 if (CE->getType() != Eng.getContext().VoidTy) {
883 unsigned Count = Builder.getCurrentBlockCount();
884 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
885
886 RVal X = CE->getType()->isPointerType()
887 ? cast<RVal>(lval::SymbolVal(Sym))
888 : cast<RVal>(nonlval::SymbolVal(Sym));
889
890 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
891 }
892
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000893 break;
894
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000895 case RetEffect::Alias: {
896 unsigned idx = RE.getValue();
897 assert (idx < CE->getNumArgs());
898 RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
Ted Kremenekce0767f2008-03-12 21:06:49 +0000899 St = StateMgr.SetRVal(St, CE, V, Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000900 break;
901 }
902
903 case RetEffect::OwnedSymbol: {
904 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000905 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000906
907 ValueState StImpl = *St;
908 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000909 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000910
911 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
912 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000913 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000914
915 break;
916 }
917
918 case RetEffect::NotOwnedSymbol: {
919 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd4676512008-03-12 21:45:47 +0000920 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000921
922 ValueState StImpl = *St;
923 RefBindings B = GetRefBindings(StImpl);
924 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
925
926 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
927 CE, lval::SymbolVal(Sym),
Ted Kremenekce0767f2008-03-12 21:06:49 +0000928 Eng.getCFG().isBlkExpr(CE), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000929
930 break;
931 }
932 }
933
Ted Kremenekf10f2882008-03-21 21:30:14 +0000934 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek827f93b2008-03-06 00:08:09 +0000935}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000936
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000937
938void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
939 GRExprEngine& Eng,
940 GRStmtNodeBuilder<ValueState>& Builder,
941 ObjCMessageExpr* ME,
942 ExplodedNode<ValueState>* Pred) {
943
Ted Kremenek33661802008-05-01 21:31:50 +0000944 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
945 return;
946
947 // The basic transfer function logic for message expressions does nothing.
948 // We just invalidate all arguments passed in by references.
949
950 ValueStateManager& StateMgr = Eng.getStateManager();
951 ValueState* St = Builder.GetState(Pred);
952 RefBindings B = GetRefBindings(*St);
953
954 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
955 I != E; ++I) {
956
957 RVal V = StateMgr.GetRVal(St, *I);
958
959 if (isa<LVal>(V)) {
960
961 LVal lv = cast<LVal>(V);
962
963 // Did the lval bind to a symbol?
964 RVal X = StateMgr.GetRVal(St, lv);
965
966 if (isa<lval::SymbolVal>(X)) {
Ted Kremenek6a24ec02008-05-01 23:38:35 +0000967 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
Ted Kremenek33661802008-05-01 21:31:50 +0000968 B = Remove(B, Sym);
969
970 // Create a new state with the updated bindings.
971 ValueState StVals = *St;
972 SetRefBindings(StVals, B);
973 St = StateMgr.getPersistentState(StVals);
974 }
975
976 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
977 }
978 }
979
980 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000981}
982
983bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
984 GRExprEngine& Eng,
985 GRStmtNodeBuilder<ValueState>& Builder,
986 ObjCMessageExpr* ME,
987 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000988
989 if (GCEnabled)
990 return true;
991
Ted Kremenek1feab292008-04-16 04:28:53 +0000992 // Handle "toll-free bridging" of calls to "Release" and "Retain".
993
994 // FIXME: track the underlying object type associated so that we can
995 // flag illegal uses of toll-free bridging (or at least handle it
996 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000997
998 Selector S = ME->getSelector();
999
1000 if (!S.isUnarySelector())
1001 return true;
1002
Ted Kremenek1feab292008-04-16 04:28:53 +00001003 Expr* Receiver = ME->getReceiver();
1004
1005 if (!Receiver)
1006 return true;
1007
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001008 // Check if we are calling "autorelease".
1009
1010 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001011
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001012 if (S == AutoreleaseSelector)
1013 mode = IsAutorelease;
1014 else if (S == RetainSelector)
1015 mode = IsRetain;
1016 else if (S == ReleaseSelector)
1017 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001018
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001019 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001020 return true;
1021
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001022 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001023 ValueStateManager& StateMgr = Eng.getStateManager();
1024 ValueState* St = Builder.GetState(Pred);
1025 RVal V = StateMgr.GetRVal(St, Receiver);
1026
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001027 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001028 if (!isa<lval::SymbolVal>(V))
1029 return true;
1030
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001031 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001032 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1033 RefBindings B = GetRefBindings(*St);
1034
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001035 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001036 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001037
Ted Kremenek1feab292008-04-16 04:28:53 +00001038 if (!T)
1039 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001040
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001041 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001042
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001043 // Update the bindings.
1044 switch (mode) {
1045 case IsNone:
1046 assert(false);
1047
1048 case IsRelease:
1049 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1050 break;
1051
1052 case IsRetain:
1053 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1054 break;
1055
1056 case IsAutorelease:
1057 // For now we just stop tracking a value if we see
1058 // it sent "autorelease." In the future we can potentially
1059 // track the associated pool.
1060 B = Remove(B, Sym);
1061 break;
1062 }
1063
1064 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001065 ValueState StVals = *St;
1066 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001067 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001068
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001069 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001070 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001071 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001072 else
1073 Builder.MakeNode(Dst, ME, Pred, St);
1074
1075 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001076}
1077
Ted Kremenek7aef4842008-04-16 20:40:59 +00001078// Stores.
1079
1080void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1081 GRExprEngine& Eng,
1082 GRStmtNodeBuilder<ValueState>& Builder,
1083 Expr* E, ExplodedNode<ValueState>* Pred,
1084 ValueState* St, RVal TargetLV, RVal Val) {
1085
1086 // Check if we have a binding for "Val" and if we are storing it to something
1087 // we don't understand or otherwise the value "escapes" the function.
1088
1089 if (!isa<lval::SymbolVal>(Val))
1090 return;
1091
1092 // Are we storing to something that causes the value to "escape"?
1093
1094 bool escapes = false;
1095
1096 if (!isa<lval::DeclVal>(TargetLV))
1097 escapes = true;
1098 else
1099 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1100
1101 if (!escapes)
1102 return;
1103
1104 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1105 RefBindings B = GetRefBindings(*St);
1106 RefBindings::TreeTy* T = B.SlimFind(Sym);
1107
1108 if (!T)
1109 return;
1110
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001111 // Nuke the binding.
1112 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001113
1114 // Hand of the remaining logic to the parent implementation.
1115 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1116}
1117
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001118
1119ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1120 SymbolID sid) {
1121 ValueState StImpl = *St;
1122 RefBindings B = GetRefBindings(StImpl);
1123 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1124 return VMgr.getPersistentState(StImpl);
1125}
1126
Ted Kremenekffefc352008-04-11 22:25:11 +00001127// End-of-path.
1128
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001129ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1130 ValueState* St, SymbolID sid,
1131 RefVal V, bool& hasLeak) {
1132
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001133 hasLeak = V.isOwned() ||
1134 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001135
1136 if (!hasLeak)
1137 return NukeBinding(VMgr, St, sid);
1138
1139 RefBindings B = GetRefBindings(*St);
1140 ValueState StImpl = *St;
1141 StImpl.CheckerState = RefBFactory.Add(B, sid, RefVal::makeLeak()).getRoot();
1142 return VMgr.getPersistentState(StImpl);
1143}
1144
1145void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001146 GREndPathNodeBuilder<ValueState>& Builder) {
1147
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001148 ValueState* St = Builder.getState();
1149 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001150
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001151 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001152
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001153 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1154 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001155
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001156 St = HandleSymbolDeath(Eng.getStateManager(), St,
1157 (*I).first, (*I).second, hasLeak);
1158
1159 if (hasLeak) Leaked.push_back((*I).first);
1160 }
Ted Kremenek541db372008-04-24 23:57:27 +00001161
1162 if (Leaked.empty())
1163 return;
1164
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001165 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001166
Ted Kremenek541db372008-04-24 23:57:27 +00001167 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001168 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001169
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001170 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1171 assert (!LeaksAtNode);
1172 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001173
1174 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1175 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001176 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001177}
1178
Ted Kremenek541db372008-04-24 23:57:27 +00001179// Dead symbols.
1180
1181void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1182 GRExprEngine& Eng,
1183 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001184 ExplodedNode<ValueState>* Pred,
1185 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001186 ValueState* St,
1187 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001188
Ted Kremenek541db372008-04-24 23:57:27 +00001189 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1190
1191 RefBindings B = GetRefBindings(*St);
1192 llvm::SmallVector<SymbolID, 10> Leaked;
1193
1194 for (ValueStateManager::DeadSymbolsTy::const_iterator
1195 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1196
1197 RefBindings::TreeTy* T = B.SlimFind(*I);
1198
1199 if (!T)
1200 continue;
1201
1202 bool hasLeak = false;
1203
1204 St = HandleSymbolDeath(Eng.getStateManager(), St,
1205 *I, T->getValue().second, hasLeak);
1206
1207 if (hasLeak) Leaked.push_back(*I);
1208 }
1209
1210 if (Leaked.empty())
1211 return;
1212
1213 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1214
1215 if (!N)
1216 return;
1217
1218 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1219 assert (!LeaksAtNode);
1220 LeaksAtNode = new std::vector<SymbolID>();
1221
1222 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1223 E = Leaked.end(); I != E; ++I)
1224 (*LeaksAtNode).push_back(*I);
1225}
1226
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001227 // Return statements.
1228
1229void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1230 GRExprEngine& Eng,
1231 GRStmtNodeBuilder<ValueState>& Builder,
1232 ReturnStmt* S,
1233 ExplodedNode<ValueState>* Pred) {
1234
1235 Expr* RetE = S->getRetValue();
1236 if (!RetE) return;
1237
1238 ValueStateManager& StateMgr = Eng.getStateManager();
1239 ValueState* St = Builder.GetState(Pred);
1240 RVal V = StateMgr.GetRVal(St, RetE);
1241
1242 if (!isa<lval::SymbolVal>(V))
1243 return;
1244
1245 // Get the reference count binding (if any).
1246 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1247 RefBindings B = GetRefBindings(*St);
1248 RefBindings::TreeTy* T = B.SlimFind(Sym);
1249
1250 if (!T)
1251 return;
1252
1253 // Change the reference count.
1254
1255 RefVal X = T->getValue().second;
1256
1257 switch (X.getKind()) {
1258
1259 case RefVal::Owned: {
1260 unsigned cnt = X.getCount();
1261 X = RefVal::makeReturnedOwned(cnt);
1262 break;
1263 }
1264
1265 case RefVal::NotOwned: {
1266 unsigned cnt = X.getCount();
1267 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1268 : RefVal::makeReturnedNotOwned();
1269 break;
1270 }
1271
1272 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001273 return;
1274 }
1275
1276 // Update the binding.
1277
1278 ValueState StImpl = *St;
1279 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1280 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1281}
1282
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001283// Assumptions.
1284
1285ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1286 RVal Cond, bool Assumption,
1287 bool& isFeasible) {
1288
1289 // FIXME: We may add to the interface of EvalAssume the list of symbols
1290 // whose assumptions have changed. For now we just iterate through the
1291 // bindings and check if any of the tracked symbols are NULL. This isn't
1292 // too bad since the number of symbols we will track in practice are
1293 // probably small and EvalAssume is only called at branches and a few
1294 // other places.
1295
1296 RefBindings B = GetRefBindings(*St);
1297
1298 if (B.isEmpty())
1299 return St;
1300
1301 bool changed = false;
1302
1303 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1304
1305 // Check if the symbol is null (or equal to any constant).
1306 // If this is the case, stop tracking the symbol.
1307
1308 if (St->getSymVal(I.getKey())) {
1309 changed = true;
1310 B = RefBFactory.Remove(B, I.getKey());
1311 }
1312 }
1313
1314 if (!changed)
1315 return St;
1316
1317 ValueState StImpl = *St;
1318 StImpl.CheckerState = B.getRoot();
1319 return Eng.getStateManager().getPersistentState(StImpl);
1320}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001321
1322CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001323 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001324 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001325
Ted Kremenek0d721572008-03-11 17:48:22 +00001326 // FIXME: This dispatch can potentially be sped up by unifiying it into
1327 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001328
Ted Kremenek0d721572008-03-11 17:48:22 +00001329 switch (E) {
1330 default:
1331 assert (false && "Unhandled CFRef transition.");
1332
1333 case DoNothing:
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001334 if (!GCEnabled && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001335 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001336 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001337 break;
1338 }
1339
Ted Kremenek0d721572008-03-11 17:48:22 +00001340 return B;
1341
1342 case IncRef:
1343 switch (V.getKind()) {
1344 default:
1345 assert(false);
1346
1347 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001348 V = RefVal::makeOwned(V.getCount()+1);
1349 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001350
Ted Kremenek0d721572008-03-11 17:48:22 +00001351 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001352 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001353 break;
1354
1355 case RefVal::Released:
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001356 if (GCEnabled)
1357 V = RefVal::makeOwned();
1358 else {
1359 V = RefVal::makeUseAfterRelease();
1360 hasErr = V.getKind();
1361 }
1362
Ted Kremenek0d721572008-03-11 17:48:22 +00001363 break;
1364 }
1365
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001366 break;
1367
Ted Kremenek0d721572008-03-11 17:48:22 +00001368 case DecRef:
1369 switch (V.getKind()) {
1370 default:
1371 assert (false);
1372
1373 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001374 unsigned Count = V.getCount();
1375 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001376 break;
1377 }
1378
Ted Kremenekc4f81022008-04-10 23:09:18 +00001379 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001380 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001381
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001382 if (Count > 0)
1383 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001384 else {
1385 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001386 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001387 }
1388
Ted Kremenek0d721572008-03-11 17:48:22 +00001389 break;
1390 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001391
1392 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001393 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001394 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001395 break;
1396 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001397
1398 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001399 }
1400
1401 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001402}
1403
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001404
1405//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001406// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001407//===----------------------------------------------------------------------===//
1408
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001409namespace {
1410
1411 //===-------------===//
1412 // Bug Descriptions. //
1413 //===-------------===//
1414
Ted Kremeneke3769852008-04-18 20:54:29 +00001415 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001416 protected:
1417 CFRefCount& TF;
1418
1419 public:
1420 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001421
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001422 CFRefCount& getTF() { return TF; }
1423
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001424 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001425 };
1426
1427 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1428 public:
1429 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1430
1431 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001432 return "Core Foundation: Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001433 }
1434 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001435 return "Reference-counted object is used"
1436 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001437 }
1438
1439 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001440 };
1441
1442 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1443 public:
1444 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1445
1446 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001447 return "Core Foundation: Release of non-owned object";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001448 }
1449 virtual const char* getDescription() const {
1450 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001451 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001452 "The object is not owned at this point by the caller.";
1453 }
1454
1455 virtual void EmitWarnings(BugReporter& BR);
1456 };
1457
1458 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1459 public:
1460 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1461
1462 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001463 return "Core Foundation: Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001464 }
1465
1466 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001467 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001468 }
1469
1470 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001471 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001472 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001473 };
1474
1475 //===---------===//
1476 // Bug Reports. //
1477 //===---------===//
1478
1479 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1480 SymbolID Sym;
1481 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001482 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001483 : RangedBugReport(D, n), Sym(sym) {}
1484
1485 virtual ~CFRefReport() {}
1486
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001487 CFRefBug& getBugType() {
1488 return (CFRefBug&) RangedBugReport::getBugType();
1489 }
1490 const CFRefBug& getBugType() const {
1491 return (const CFRefBug&) RangedBugReport::getBugType();
1492 }
1493
1494 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1495 const SourceRange*& end) {
1496
Ted Kremenek198cae02008-05-02 20:53:50 +00001497 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001498 RangedBugReport::getRanges(BR, beg, end);
1499 else {
1500 beg = 0;
1501 end = 0;
1502 }
1503 }
1504
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001505 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1506 ExplodedNode<ValueState>* N);
1507
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001508 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001509
1510 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1511 ExplodedNode<ValueState>* PrevN,
1512 ExplodedGraph<ValueState>& G,
1513 BugReporter& BR);
1514 };
1515
1516
1517} // end anonymous namespace
1518
1519void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001520 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001521 Eng.Register(new UseAfterRelease(*this));
1522 Eng.Register(new BadRelease(*this));
1523 Eng.Register(new Leak(*this));
1524}
1525
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001526
1527static const char* Msgs[] = {
1528 "Code is compiled in garbage collection only mode" // GC only
1529 " (the bug occurs with garbage collection enabled).",
1530
1531 "Code is compiled without garbage collection.", // No GC.
1532
1533 "Code is compiled for use with and without garbage collection (GC)."
1534 " The bug occurs with GC enabled.", // Hybrid, with GC.
1535
1536 "Code is compiled for use with and without garbage collection (GC)."
1537 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1538};
1539
1540std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1541 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1542
1543 switch (TF.getLangOptions().getGCMode()) {
1544 default:
1545 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001546
1547 case LangOptions::GCOnly:
1548 assert (TF.isGCEnabled());
1549 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001550
1551 case LangOptions::NonGC:
1552 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001553 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1554
1555 case LangOptions::HybridGC:
1556 if (TF.isGCEnabled())
1557 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1558 else
1559 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1560 }
1561}
1562
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001563PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1564 ExplodedNode<ValueState>* PrevN,
1565 ExplodedGraph<ValueState>& G,
1566 BugReporter& BR) {
1567
1568 // Check if the type state has changed.
1569
1570 ValueState* PrevSt = PrevN->getState();
1571 ValueState* CurrSt = N->getState();
1572
1573 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1574 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1575
Ted Kremeneka8503952008-04-18 04:55:01 +00001576 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1577 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001578
Ted Kremeneka8503952008-04-18 04:55:01 +00001579 if (!CurrT)
1580 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001581
Ted Kremeneka8503952008-04-18 04:55:01 +00001582 const char* Msg = NULL;
1583 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001584
Ted Kremeneka8503952008-04-18 04:55:01 +00001585 if (!PrevT) {
1586
1587 // Check for the point where we start tracking the value.
1588
1589 if (CurrV.isOwned())
1590 Msg = "Function call returns 'Owned' Core Foundation object.";
1591 else {
1592 assert (CurrV.isNotOwned());
1593 Msg = "Function call returns 'Non-Owned' Core Foundation object.";
1594 }
1595
1596 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1597 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1598 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1599
1600 if (Expr* Exp = dyn_cast<Expr>(S))
1601 P->addRange(Exp->getSourceRange());
1602
1603 return P;
1604 }
1605
1606 // Determine if the typestate has changed.
1607
1608 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1609
1610 if (PrevV == CurrV)
1611 return NULL;
1612
1613 // The typestate has changed.
1614
1615 std::ostringstream os;
1616
1617 switch (CurrV.getKind()) {
1618 case RefVal::Owned:
1619 case RefVal::NotOwned:
1620 assert (PrevV.getKind() == CurrV.getKind());
1621
1622 if (PrevV.getCount() > CurrV.getCount())
1623 os << "Reference count decremented.";
1624 else
1625 os << "Reference count incremented.";
1626
Ted Kremenek752b5842008-04-18 05:32:44 +00001627 if (CurrV.getCount()) {
1628 os << " Object has +" << CurrV.getCount();
1629
1630 if (CurrV.getCount() > 1)
1631 os << " reference counts.";
1632 else
1633 os << " reference count.";
1634 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001635
1636 Msg = os.str().c_str();
1637
1638 break;
1639
1640 case RefVal::Released:
1641 Msg = "Object released.";
1642 break;
1643
1644 case RefVal::ReturnedOwned:
1645 Msg = "Object returned to caller. "
1646 "Caller gets ownership of object.";
1647 break;
1648
1649 case RefVal::ReturnedNotOwned:
1650 Msg = "Object returned to caller. "
1651 "Caller does not get ownership of object.";
1652 break;
1653
1654 default:
1655 return NULL;
1656 }
1657
1658 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1659 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1660 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1661
1662 // Add the range by scanning the children of the statement for any bindings
1663 // to Sym.
1664
1665 ValueStateManager& VSM = BR.getEngine().getStateManager();
1666
1667 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1668 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1669 RVal X = VSM.GetRVal(CurrSt, Exp);
1670
1671 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1672 if (SV->getSymbol() == Sym) {
1673 P->addRange(Exp->getSourceRange()); break;
1674 }
1675 }
1676
1677 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001678}
1679
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001680PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
1681 ExplodedNode<ValueState>* N) {
1682
1683 if (!getBugType().isLeak())
1684 return RangedBugReport::getEndPath(BR, N);
1685
1686 // We are a leak. Walk up the graph to get to the first node where the
1687 // symbol appeared.
1688
1689 ExplodedNode<ValueState>* Last = N;
1690 typedef CFRefCount::RefBindings RefBindings;
1691
Ted Kremenek198cae02008-05-02 20:53:50 +00001692 // Find the first node that referred to the tracked symbol. We also
1693 // try and find the first VarDecl the value was stored to.
1694
1695 VarDecl* FirstDecl = 0;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001696
1697 while (N) {
1698 ValueState* St = N->getState();
1699 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001700 RefBindings::TreeTy* T = B.SlimFind(Sym);
1701
1702 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001703 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00001704
1705 VarDecl* VD = 0;
1706
1707 // Determine if there is an LVal binding to the symbol.
1708 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1709 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1710 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1711 continue;
1712
1713 if (VD) { // Multiple decls map to this symbol.
1714 VD = 0;
1715 break;
1716 }
1717
1718 VD = I->first;
1719 }
1720
1721 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001722
1723 Last = N;
1724 N = N->pred_empty() ? NULL : *(N->pred_begin());
1725 }
1726
1727 // Get the location.
1728
1729 assert (Last);
1730 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1731
1732 unsigned Line =
1733 BR.getSourceManager().getLogicalLineNumber(FirstStmt->getLocStart());
1734
1735 // FIXME: Also get the name of the variable.
1736
1737 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00001738
1739 os << "Object allocated on line " << Line;
1740
1741 if (FirstDecl)
1742 os << " and stored into '" << FirstDecl->getName() << '\'';
1743
1744 os << " is leaked.";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001745
1746 Stmt* S = getStmt(BR);
1747 assert (S);
1748 FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
1749 PathDiagnosticPiece* P = new PathDiagnosticPiece(L, os.str());
1750
1751 return P;
1752}
1753
Ted Kremenek7d421f32008-04-09 23:49:11 +00001754void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001755
Ted Kremenek7d421f32008-04-09 23:49:11 +00001756 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1757 E = TF.use_after_end(); I != E; ++I) {
1758
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001759 CFRefReport report(*this, I->first, I->second.second);
1760 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00001761 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001762 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001763}
1764
1765void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001766
Ted Kremenek7d421f32008-04-09 23:49:11 +00001767 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1768 E = TF.bad_release_end(); I != E; ++I) {
1769
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001770 CFRefReport report(*this, I->first, I->second.second);
1771 report.addRange(I->second.first->getSourceRange());
1772 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00001773 }
1774}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001775
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001776void Leak::EmitWarnings(BugReporter& BR) {
1777
1778 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1779 E = TF.leaks_end(); I != E; ++I) {
1780
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001781 std::vector<SymbolID>& SymV = *(I->second);
1782 unsigned n = SymV.size();
1783
1784 for (unsigned i = 0; i < n; ++i) {
1785 CFRefReport report(*this, I->first, SymV[i]);
1786 BR.EmitWarning(report);
1787 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001788 }
1789}
1790
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001791void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1792 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1793 I!=E; ++I)
1794 Nodes.push_back(I->first);
1795}
1796
Ted Kremeneka7338b42008-03-11 06:39:11 +00001797//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001798// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001799//===----------------------------------------------------------------------===//
1800
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001801GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00001802 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001803 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001804 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00001805}