blob: aa1d122c132b88f48e242da9a47b686360c47f14 [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,
Ted Kremeneka8c3c432008-05-05 22:11:16 +000066 NotOwnedSymbol = 0x3, ReceiverAlias=0x4 };
Ted Kremeneka7338b42008-03-11 06:39:11 +000067
68private:
69 unsigned Data;
Ted Kremeneka8c3c432008-05-05 22:11:16 +000070 RetEffect(Kind k, unsigned D) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek827f93b2008-03-06 00:08:09 +000071
Ted Kremeneka7338b42008-03-11 06:39:11 +000072public:
73
Ted Kremeneka8c3c432008-05-05 22:11:16 +000074 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremeneka7338b42008-03-11 06:39:11 +000075
76 unsigned getValue() const {
77 assert(getKind() == Alias);
Ted Kremeneka8c3c432008-05-05 22:11:16 +000078 return Data >> 3;
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 Kremeneka8c3c432008-05-05 22:11:16 +000083 static RetEffect MakeReceiverAlias() { return RetEffect(ReceiverAlias, 0); }
84
Ted Kremeneka7338b42008-03-11 06:39:11 +000085 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek827f93b2008-03-06 00:08:09 +000086
Ted Kremeneka7338b42008-03-11 06:39:11 +000087 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
88
Ted Kremenekab2fa2a2008-04-10 23:44:06 +000089 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
90
Ted Kremeneka7338b42008-03-11 06:39:11 +000091 operator Kind() const { return getKind(); }
92
93 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
94};
95
96
Ted Kremeneka8c3c432008-05-05 22:11:16 +000097class RetainSummary : public llvm::FoldingSetNode {
Ted Kremeneka7338b42008-03-11 06:39:11 +000098 ArgEffects* Args;
99 RetEffect Ret;
100public:
101
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000102 RetainSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000103
104 unsigned getNumArgs() const { return Args->size(); }
105
Ted Kremenek0d721572008-03-11 17:48:22 +0000106 ArgEffect getArg(unsigned idx) const {
Ted Kremenekae855d42008-04-24 17:22:33 +0000107 if (!Args)
108 return DoNothing;
109
110 // If Args is present, it is likely to contain only 1 element.
111 // Just do a linear search. Do it from the back because functions with
112 // large numbers of arguments will be tail heavy with respect to which
113 // argument they actually modify with respect to the reference count.
114
115 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
116 I!=E; ++I) {
117
118 if (idx > I->first)
119 return DoNothing;
120
121 if (idx == I->first)
122 return I->second;
123 }
124
125 return DoNothing;
Ted Kremenek0d721572008-03-11 17:48:22 +0000126 }
127
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000128 RetEffect getRet() const {
129 return Ret;
130 }
131
Ted Kremeneka7338b42008-03-11 06:39:11 +0000132 typedef ArgEffects::const_iterator arg_iterator;
133
134 arg_iterator begin_args() const { return Args->begin(); }
135 arg_iterator end_args() const { return Args->end(); }
136
137 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
138 ID.AddPointer(A);
139 ID.Add(R);
140 }
141
142 void Profile(llvm::FoldingSetNodeID& ID) const {
143 Profile(ID, Args, Ret);
144 }
145};
146
147
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000148class RetainSummaryManager {
149
150 //==-----------------------------------------------------------------==//
151 // Typedefs.
152 //==-----------------------------------------------------------------==//
Ted Kremeneka7338b42008-03-11 06:39:11 +0000153
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000154 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
155 ArgEffectsSetTy;
156
157 typedef llvm::FoldingSet<RetainSummary>
158 SummarySetTy;
159
160 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
161 FuncSummariesTy;
162
163 typedef llvm::DenseMap<Selector, RetainSummary*>
164 ObjCMethodSummariesTy;
165
166 //==-----------------------------------------------------------------==//
167 // Data.
168 //==-----------------------------------------------------------------==//
169
170 // Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000171 ASTContext& Ctx;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000172
173 // GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000174 const bool GCEnabled;
175
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000176 // SummarySet - A FoldingSet of uniqued summaries.
Ted Kremeneka4c74292008-04-10 22:58:08 +0000177 SummarySetTy SummarySet;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000178
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000179 // FuncSummaries - A map from FunctionDecls to summaries.
180 FuncSummariesTy FuncSummaries;
181
182 // ObjCInstanceMethodSummaries - A map from selectors (for instance methods)
183 // to summaries.
184 ObjCMethodSummariesTy ObjCInstanceMethodSummaries;
185
186 // ObjCMethodSummaries - A map from selectors to summaries.
187 ObjCMethodSummariesTy ObjCMethodSummaries;
188
189 // ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
190 ArgEffectsSetTy ArgEffectsSet;
191
192 // BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
193 // and all other data used by the checker.
194 llvm::BumpPtrAllocator BPAlloc;
195
196 // ScratchArgs - A holding buffer for construct ArgEffects.
197 ArgEffects ScratchArgs;
198
199 //==-----------------------------------------------------------------==//
200 // Methods.
201 //==-----------------------------------------------------------------==//
202
203 // getArgEffects - Returns a persistent ArgEffects object based on the
204 // data in ScratchArgs.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000205 ArgEffects* getArgEffects();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000206
Ted Kremenek562c1302008-05-05 16:51:50 +0000207 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000208 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000209
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000210 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
211 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000212
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000213 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
214 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000215
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000216 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
Ted Kremenek42ea0322008-05-05 23:55:01 +0000217
218 RetainSummary* getInstanceMethodSummary(Selector S);
219
220 RetainSummary* getMethodSummary(Selector S);
221 RetainSummary* getInitMethodSummary(Selector S);
222
Ted Kremeneka7338b42008-03-11 06:39:11 +0000223public:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000224
225 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000226 : Ctx(ctx), GCEnabled(gcenabled) {}
227
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000228 ~RetainSummaryManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000229
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000230 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
231
232 bool isGCEnabled() const { return GCEnabled; }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000233};
234
235} // end anonymous namespace
236
237//===----------------------------------------------------------------------===//
238// Implementation of checker data structures.
239//===----------------------------------------------------------------------===//
240
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000241RetainSummaryManager::~RetainSummaryManager() {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000242
243 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
244 // mitigating the need to do explicit cleanup of the
245 // Argument-Effect summaries.
246
Ted Kremenek42ea0322008-05-05 23:55:01 +0000247 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
248 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremeneka7338b42008-03-11 06:39:11 +0000249 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000250}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000251
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000252ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000253
Ted Kremenekae855d42008-04-24 17:22:33 +0000254 if (ScratchArgs.empty())
255 return NULL;
256
257 // Compute a profile for a non-empty ScratchArgs.
258
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000259 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000260
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000261 profile.Add(ScratchArgs);
262 void* InsertPos;
263
Ted Kremenekae855d42008-04-24 17:22:33 +0000264 // Look up the uniqued copy, or create a new one.
265
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000266 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000267 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000268
Ted Kremenekae855d42008-04-24 17:22:33 +0000269 if (E) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000270 ScratchArgs.clear();
271 return &E->getValue();
272 }
273
274 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
275 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
276
277 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000278 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000279
280 ScratchArgs.clear();
281 return &E->getValue();
282}
283
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000284RetainSummary* RetainSummaryManager::getPersistentSummary(ArgEffects* AE,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000285 RetEffect RE) {
286
Ted Kremenekae855d42008-04-24 17:22:33 +0000287 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000288 llvm::FoldingSetNodeID profile;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000289 RetainSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000290
Ted Kremenekae855d42008-04-24 17:22:33 +0000291 // Look up the uniqued summary, or create one if it doesn't exist.
292 void* InsertPos;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000293 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000294
295 if (Summ)
296 return Summ;
297
Ted Kremenekae855d42008-04-24 17:22:33 +0000298 // Create the summary and return it.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000299 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
300 new (Summ) RetainSummary(AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000301 SummarySet.InsertNode(Summ, InsertPos);
302
303 return Summ;
304}
305
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000306//===----------------------------------------------------------------------===//
307// Summary creation for functions (largely uses of Core Foundation).
308//===----------------------------------------------------------------------===//
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000309
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000310RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000311 ASTContext& Ctx) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000312
313 SourceLocation Loc = FD->getLocation();
314
315 if (!Loc.isFileID())
316 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000317
Ted Kremenekae855d42008-04-24 17:22:33 +0000318 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000319 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenekae855d42008-04-24 17:22:33 +0000320
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000321 if (I != FuncSummaries.end())
Ted Kremenekae855d42008-04-24 17:22:33 +0000322 return I->second;
323
324 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000325 const char* FName = FD->getIdentifier()->getName();
326
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000327 RetainSummary *S = 0;
Ted Kremenek562c1302008-05-05 16:51:50 +0000328
329 if (FName[0] == 'C' && FName[1] == 'F')
330 S = getCFSummary(FD, FName);
331 else if (FName[0] == 'N' && FName[1] == 'S')
332 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000333
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000334 FuncSummaries[FD] = S;
Ted Kremenek562c1302008-05-05 16:51:50 +0000335 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000336}
337
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000338RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000339 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000340 FName += 2;
341
342 if (strcmp(FName, "MakeCollectable") == 0)
343 return getUnarySummary(FD, cfmakecollectable);
344
345 return 0;
346}
347
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000348RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek42ea0322008-05-05 23:55:01 +0000349 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000350
351 FName += 2;
352
353 if (strcmp(FName, "Retain") == 0)
354 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000355
Ted Kremenek562c1302008-05-05 16:51:50 +0000356 if (strcmp(FName, "Release") == 0)
357 return getUnarySummary(FD, cfrelease);
358
359 if (strcmp(FName, "MakeCollectable") == 0)
360 return getUnarySummary(FD, cfmakecollectable);
361
362 if (strstr(FName, "Create") || strstr(FName, "Copy"))
363 return getCFSummaryCreateRule(FD);
364
365 if (strstr(FName, "Get"))
366 return getCFSummaryGetRule(FD);
367
368 return 0;
369}
370
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000371RetainSummary*
372RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000373
374 FunctionTypeProto* FT =
375 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
376
Ted Kremenek562c1302008-05-05 16:51:50 +0000377 if (FT) {
378
379 if (FT->getNumArgs() != 1)
380 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000381
Ted Kremenek562c1302008-05-05 16:51:50 +0000382 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
383
384 if (!ArgT)
385 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000386
Ted Kremenek562c1302008-05-05 16:51:50 +0000387 if (!ArgT->isPointerType())
388 return NULL;
389 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000390
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000391 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000392
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000393 switch (func) {
394 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000395 ScratchArgs.push_back(std::make_pair(0, IncRef));
396 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
397 }
398
399 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000400 ScratchArgs.push_back(std::make_pair(0, DecRef));
401 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
402 }
403
404 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000405 if (GCEnabled)
406 ScratchArgs.push_back(std::make_pair(0, DecRef));
407
Ted Kremenek562c1302008-05-05 16:51:50 +0000408 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000409 }
410
411 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000412 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000413 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000414}
415
416static bool isCFRefType(QualType T) {
417
418 if (!T->isPointerType())
419 return false;
420
421 // Check the typedef for the name "CF" and the substring "Ref".
422
423 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
424
425 if (!TD)
426 return false;
427
428 const char* TDName = TD->getDecl()->getIdentifier()->getName();
429 assert (TDName);
430
431 if (TDName[0] != 'C' || TDName[1] != 'F')
432 return false;
433
434 if (strstr(TDName, "Ref") == 0)
435 return false;
436
437 return true;
438}
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000439
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000440RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000441
Ted Kremenek562c1302008-05-05 16:51:50 +0000442 FunctionTypeProto* FT =
443 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
444
445 if (FT && !isCFRefType(FT->getResultType()))
446 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000447
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000448 // FIXME: Add special-cases for functions that retain/release. For now
449 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000450
451 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000452 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
453}
454
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000455RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000456
Ted Kremenek562c1302008-05-05 16:51:50 +0000457 FunctionTypeProto* FT =
458 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000459
Ted Kremenek562c1302008-05-05 16:51:50 +0000460 if (FT) {
461 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000462
Ted Kremenek562c1302008-05-05 16:51:50 +0000463 // FIXME: For now we assume that all pointer types returned are referenced
464 // counted. Since this is the "Get" rule, we assume non-ownership, which
465 // works fine for things that are not reference counted. We do this because
466 // some generic data structures return "void*". We need something better
467 // in the future.
468
469 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
470 return 0;
471 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000472
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000473 // FIXME: Add special-cases for functions that retain/release. For now
474 // just handle the default case.
475
Ted Kremenekae855d42008-04-24 17:22:33 +0000476 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000477 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
478}
479
Ted Kremeneka7338b42008-03-11 06:39:11 +0000480//===----------------------------------------------------------------------===//
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000481// Summary creation for Selectors.
482//===----------------------------------------------------------------------===//
483
Ted Kremenek42ea0322008-05-05 23:55:01 +0000484RetainSummary* RetainSummaryManager::getInitMethodSummary(Selector S) {
485 assert(ScratchArgs.empty());
486
487 RetainSummary* Summ =
488 getPersistentSummary(getArgEffects(), RetEffect::MakeReceiverAlias());
489
490 ObjCMethodSummaries[S] = Summ;
491 return Summ;
492}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000493
Ted Kremenek42ea0322008-05-05 23:55:01 +0000494RetainSummary* RetainSummaryManager::getMethodSummary(Selector S) {
495
496 // Look up a summary in our cache of Selectors -> Summaries.
497 ObjCMethodSummariesTy::iterator I = ObjCMethodSummaries.find(S);
498
499 if (I != ObjCMethodSummaries.end())
500 return I->second;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000501
Ted Kremenek42ea0322008-05-05 23:55:01 +0000502 // "initXXX": pass-through for receiver.
503
504 const char* s = S.getIdentifierInfoForSlot(0)->getName();
505
506 if (s[0] == 'i' && s[10] == 'n' && s[2] == 'i' && s[3] == 't')
507 return getInitMethodSummary(S);
508
509 return 0;
510}
511
512RetainSummary* RetainSummaryManager::getInstanceMethodSummary(Selector S) {
513
514 // Look up a summary in our cache of Selectors -> Summaries.
515 ObjCMethodSummariesTy::iterator I = ObjCInstanceMethodSummaries.find(S);
516
517 if (I != ObjCInstanceMethodSummaries.end())
518 return I->second;
519
520 return 0;
521}
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000522
523//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000524// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000525//===----------------------------------------------------------------------===//
526
Ted Kremeneka7338b42008-03-11 06:39:11 +0000527namespace {
528
Ted Kremenek7d421f32008-04-09 23:49:11 +0000529class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000530public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000531
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000532 enum Kind {
533 Owned = 0, // Owning reference.
534 NotOwned, // Reference is not owned by still valid (not freed).
535 Released, // Object has been released.
536 ReturnedOwned, // Returned object passes ownership to caller.
537 ReturnedNotOwned, // Return object does not pass ownership to caller.
538 ErrorUseAfterRelease, // Object used after released.
539 ErrorReleaseNotOwned, // Release of an object that was not owned.
540 ErrorLeak // A memory leak due to excessive reference counts.
541 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000542
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000543private:
544
545 Kind kind;
546 unsigned Cnt;
547
548 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
549
550 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000551
552public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000553
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000554 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000555
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000556 unsigned getCount() const { return Cnt; }
557
558 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000559
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000560 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
561
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000562 static bool isLeak(Kind k) { return k == ErrorLeak; }
563
Ted Kremenekffefc352008-04-11 22:25:11 +0000564 bool isOwned() const {
565 return getKind() == Owned;
566 }
567
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000568 bool isNotOwned() const {
569 return getKind() == NotOwned;
570 }
571
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000572 bool isReturnedOwned() const {
573 return getKind() == ReturnedOwned;
574 }
575
576 bool isReturnedNotOwned() const {
577 return getKind() == ReturnedNotOwned;
578 }
579
580 bool isNonLeakError() const {
581 Kind k = getKind();
582 return isError(k) && !isLeak(k);
583 }
584
585 // State creation: normal state.
586
Ted Kremenekc4f81022008-04-10 23:09:18 +0000587 static RefVal makeOwned(unsigned Count = 0) {
588 return RefVal(Owned, Count);
589 }
590
591 static RefVal makeNotOwned(unsigned Count = 0) {
592 return RefVal(NotOwned, Count);
593 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000594
595 static RefVal makeReturnedOwned(unsigned Count) {
596 return RefVal(ReturnedOwned, Count);
597 }
598
599 static RefVal makeReturnedNotOwned() {
600 return RefVal(ReturnedNotOwned);
601 }
602
603 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000604
Ted Kremenek9363fd92008-05-05 17:53:17 +0000605 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000606 static RefVal makeReleased() { return RefVal(Released); }
607 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
608 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000609
610 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000611
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000612 bool operator==(const RefVal& X) const {
613 return kind == X.kind && Cnt == X.Cnt;
614 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000615
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000616 void Profile(llvm::FoldingSetNodeID& ID) const {
617 ID.AddInteger((unsigned) kind);
618 ID.AddInteger(Cnt);
619 }
620
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000621 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000622};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000623
624void RefVal::print(std::ostream& Out) const {
625 switch (getKind()) {
626 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000627 case Owned: {
628 Out << "Owned";
629 unsigned cnt = getCount();
630 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000631 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000632 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000633
Ted Kremenekc4f81022008-04-10 23:09:18 +0000634 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000635 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000636 unsigned cnt = getCount();
637 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000638 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000639 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000640
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000641 case ReturnedOwned: {
642 Out << "ReturnedOwned";
643 unsigned cnt = getCount();
644 if (cnt) Out << " (+ " << cnt << ")";
645 break;
646 }
647
648 case ReturnedNotOwned: {
649 Out << "ReturnedNotOwned";
650 unsigned cnt = getCount();
651 if (cnt) Out << " (+ " << cnt << ")";
652 break;
653 }
654
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000655 case Released:
656 Out << "Released";
657 break;
658
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000659 case ErrorLeak:
660 Out << "Leaked";
661 break;
662
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000663 case ErrorUseAfterRelease:
664 Out << "Use-After-Release [ERROR]";
665 break;
666
667 case ErrorReleaseNotOwned:
668 Out << "Release of Not-Owned [ERROR]";
669 break;
670 }
671}
Ted Kremenek0d721572008-03-11 17:48:22 +0000672
Ted Kremenek9363fd92008-05-05 17:53:17 +0000673static inline unsigned GetCount(RefVal V) {
674 switch (V.getKind()) {
675 default:
676 return V.getCount();
677
678 case RefVal::Owned:
679 return V.getCount()+1;
680 }
681}
682
Ted Kremenek7aef4842008-04-16 20:40:59 +0000683//===----------------------------------------------------------------------===//
684// Transfer functions.
685//===----------------------------------------------------------------------===//
686
Ted Kremenek7d421f32008-04-09 23:49:11 +0000687class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000688public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000689 // Type definitions.
690
Ted Kremenek0d721572008-03-11 17:48:22 +0000691 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000692 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000693
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000694 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
695 ReleasesNotOwnedTy;
696
697 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
698
699 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000700 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000701
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000702 class BindingsPrinter : public ValueState::CheckerStatePrinter {
703 public:
704 virtual void PrintCheckerState(std::ostream& Out, void* State,
705 const char* nl, const char* sep);
706 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000707
708private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000709 // Instance variables.
710
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000711 RetainSummaryManager Summaries;
712 const bool EmitStandardWarnings;
713 const LangOptions& LOpts;
714 RefBFactoryTy RefBFactory;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000715
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000716 UseAfterReleasesTy UseAfterReleases;
717 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000718 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000719
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000720 BindingsPrinter Printer;
721
Ted Kremenek1feab292008-04-16 04:28:53 +0000722 Selector RetainSelector;
723 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000724 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000725
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000726public:
727
Ted Kremeneka7338b42008-03-11 06:39:11 +0000728 static RefBindings GetRefBindings(ValueState& StImpl) {
729 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
730 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000731
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000732private:
733
Ted Kremeneka7338b42008-03-11 06:39:11 +0000734 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
735 StImpl.CheckerState = B.getRoot();
736 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000737
Ted Kremeneka7338b42008-03-11 06:39:11 +0000738 RefBindings Remove(RefBindings B, SymbolID sym) {
739 return RefBFactory.Remove(B, sym);
740 }
741
Ted Kremenek0d721572008-03-11 17:48:22 +0000742 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000743 RefVal::Kind& hasErr);
744
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000745 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
746 GRStmtNodeBuilder<ValueState>& Builder,
747 Expr* NodeExpr, Expr* ErrorExpr,
748 ExplodedNode<ValueState>* Pred,
749 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000750 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000751
752 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
753 SymbolID sid, RefVal V, bool& hasLeak);
754
755 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
756 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000757
758public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000759
Ted Kremenek2f62f352008-05-02 18:01:49 +0000760 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
761 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000762 : Summaries(Ctx, gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000763 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000764 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000765 RetainSelector(GetNullarySelector("retain", Ctx)),
766 ReleaseSelector(GetNullarySelector("release", Ctx)),
767 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000768
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000769 virtual ~CFRefCount() {
770 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
771 delete I->second;
772 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000773
774 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000775
776 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
777 return &Printer;
778 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000779
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000780 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000781 const LangOptions& getLangOptions() const { return LOpts; }
782
Ted Kremeneka7338b42008-03-11 06:39:11 +0000783 // Calls.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000784
785 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
786 GRExprEngine& Eng,
787 GRStmtNodeBuilder<ValueState>& Builder,
788 Expr* Ex,
789 Expr* Receiver,
790 RetainSummary* Summ,
791 Expr** arg_beg, Expr** arg_end,
792 ExplodedNode<ValueState>* Pred);
793
Ted Kremeneka7338b42008-03-11 06:39:11 +0000794 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000795 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000796 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000797 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000798 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000799
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000800
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000801 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
802 GRExprEngine& Engine,
803 GRStmtNodeBuilder<ValueState>& Builder,
804 ObjCMessageExpr* ME,
805 ExplodedNode<ValueState>* Pred);
806
807 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
808 GRExprEngine& Engine,
809 GRStmtNodeBuilder<ValueState>& Builder,
810 ObjCMessageExpr* ME,
811 ExplodedNode<ValueState>* Pred);
812
Ted Kremenek7aef4842008-04-16 20:40:59 +0000813 // Stores.
814
815 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
816 GRExprEngine& Engine,
817 GRStmtNodeBuilder<ValueState>& Builder,
818 Expr* E, ExplodedNode<ValueState>* Pred,
819 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000820 // End-of-path.
821
822 virtual void EvalEndPath(GRExprEngine& Engine,
823 GREndPathNodeBuilder<ValueState>& Builder);
824
Ted Kremenek541db372008-04-24 23:57:27 +0000825 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
826 GRExprEngine& Engine,
827 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000828 ExplodedNode<ValueState>* Pred,
829 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000830 ValueState* St,
831 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000832 // Return statements.
833
834 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
835 GRExprEngine& Engine,
836 GRStmtNodeBuilder<ValueState>& Builder,
837 ReturnStmt* S,
838 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +0000839
840 // Assumptions.
841
842 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
843 RVal Cond, bool Assumption, bool& isFeasible);
844
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000845 // Error iterators.
846
847 typedef UseAfterReleasesTy::iterator use_after_iterator;
848 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000849 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000850
Ted Kremenek7d421f32008-04-09 23:49:11 +0000851 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
852 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000853
Ted Kremenek7d421f32008-04-09 23:49:11 +0000854 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
855 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000856
857 leaks_iterator leaks_begin() { return Leaks.begin(); }
858 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000859};
860
861} // end anonymous namespace
862
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000863
Ted Kremenek7d421f32008-04-09 23:49:11 +0000864
865
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000866void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
867 void* State, const char* nl,
868 const char* sep) {
869 RefBindings B((RefBindings::TreeTy*) State);
870
871 if (State)
872 Out << sep << nl;
873
874 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
875 Out << (*I).first << " : ";
876 (*I).second.print(Out);
877 Out << nl;
878 }
879}
880
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000881static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000882 return Summ ? Summ->getArg(idx) : DoNothing;
883}
884
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000885static inline RetEffect GetRetE(RetainSummary* Summ) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000886 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
887}
888
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000889void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
890 GRStmtNodeBuilder<ValueState>& Builder,
891 Expr* NodeExpr, Expr* ErrorExpr,
892 ExplodedNode<ValueState>* Pred,
893 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000894 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000895 Builder.BuildSinks = true;
896 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
897
898 if (!N) return;
899
900 switch (hasErr) {
901 default: assert(false);
902 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000903 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000904 break;
905
906 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000907 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000908 break;
909 }
910}
911
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000912void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
913 GRExprEngine& Eng,
914 GRStmtNodeBuilder<ValueState>& Builder,
915 Expr* Ex,
916 Expr* Receiver,
917 RetainSummary* Summ,
918 Expr** arg_beg, Expr** arg_end,
919 ExplodedNode<ValueState>* Pred) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000920
Ted Kremenek827f93b2008-03-06 00:08:09 +0000921
Ted Kremeneka7338b42008-03-11 06:39:11 +0000922 // Get the state.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000923 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000924 ValueState* St = Builder.GetState(Pred);
925
926 // Evaluate the effects of the call.
927
928 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000929 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000930
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000931 // This function has a summary. Evaluate the effect of the arguments.
932
933 unsigned idx = 0;
934
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000935 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000936 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000937
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000938 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000939
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000940 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000941
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000942 if (isa<lval::SymbolVal>(V)) {
943 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000944 RefBindings B = GetRefBindings(StVals);
945
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000946 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000947 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000948 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000949
Ted Kremenek1feab292008-04-16 04:28:53 +0000950 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000951 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000952 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000953 break;
954 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000955 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000956 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000957 else if (isa<LVal>(V)) {
958 // Nuke all arguments passed by reference.
Ted Kremenek455dd862008-04-11 20:23:24 +0000959 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000960 }
Ted Kremenekbe621292008-04-22 21:39:21 +0000961 else if (isa<nonlval::LValAsInteger>(V))
962 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000963 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000964
965 St = StateMgr.getPersistentState(StVals);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000966
Ted Kremenek1feab292008-04-16 04:28:53 +0000967 if (hasErr) {
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000968 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000969 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000970 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000971 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000972
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000973 // Finally, consult the summary for the return value.
974
Ted Kremenek455dd862008-04-11 20:23:24 +0000975 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000976
977 switch (RE.getKind()) {
978 default:
979 assert (false && "Unhandled RetEffect."); break;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000980
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000981 case RetEffect::NoRet:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000982
Ted Kremenek455dd862008-04-11 20:23:24 +0000983 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000984 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
985 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000986
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000987 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000988 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000989 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek455dd862008-04-11 20:23:24 +0000990
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000991 RVal X = Ex->getType()->isPointerType()
992 ? cast<RVal>(lval::SymbolVal(Sym))
993 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenek455dd862008-04-11 20:23:24 +0000994
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000995 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek455dd862008-04-11 20:23:24 +0000996 }
997
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000998 break;
999
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001000 case RetEffect::Alias: {
1001 unsigned idx = RE.getValue();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001002 assert ((arg_end - arg_beg) >= 0);
1003 assert (idx < (unsigned) (arg_end - arg_beg));
1004 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1005 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001006 break;
1007 }
1008
1009 case RetEffect::OwnedSymbol: {
1010 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001011 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1012
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001013 ValueState StImpl = *St;
1014 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001015 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001016
1017 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001018 Ex, lval::SymbolVal(Sym),
1019 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001020
1021 break;
1022 }
1023
1024 case RetEffect::NotOwnedSymbol: {
1025 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001026 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001027
1028 ValueState StImpl = *St;
1029 RefBindings B = GetRefBindings(StImpl);
1030 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1031
1032 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001033 Ex, lval::SymbolVal(Sym),
1034 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001035
1036 break;
1037 }
1038 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001039
1040 Builder.MakeNode(Dst, Ex, Pred, St);
1041}
1042
1043
1044void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1045 GRExprEngine& Eng,
1046 GRStmtNodeBuilder<ValueState>& Builder,
1047 CallExpr* CE, RVal L,
1048 ExplodedNode<ValueState>* Pred) {
1049
1050
1051 RetainSummary* Summ = NULL;
1052
1053 // Get the summary.
1054
1055 if (isa<lval::FuncVal>(L)) {
1056 lval::FuncVal FV = cast<lval::FuncVal>(L);
1057 FunctionDecl* FD = FV.getDecl();
1058 Summ = Summaries.getSummary(FD, Eng.getContext());
1059 }
1060
1061 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1062 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek827f93b2008-03-06 00:08:09 +00001063}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001064
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001065
1066void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1067 GRExprEngine& Eng,
1068 GRStmtNodeBuilder<ValueState>& Builder,
1069 ObjCMessageExpr* ME,
1070 ExplodedNode<ValueState>* Pred) {
1071
Ted Kremenek33661802008-05-01 21:31:50 +00001072 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
1073 return;
1074
1075 // The basic transfer function logic for message expressions does nothing.
1076 // We just invalidate all arguments passed in by references.
1077
1078 ValueStateManager& StateMgr = Eng.getStateManager();
1079 ValueState* St = Builder.GetState(Pred);
1080 RefBindings B = GetRefBindings(*St);
1081
1082 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
1083 I != E; ++I) {
1084
1085 RVal V = StateMgr.GetRVal(St, *I);
1086
1087 if (isa<LVal>(V)) {
1088
1089 LVal lv = cast<LVal>(V);
1090
1091 // Did the lval bind to a symbol?
1092 RVal X = StateMgr.GetRVal(St, lv);
1093
1094 if (isa<lval::SymbolVal>(X)) {
Ted Kremenek6a24ec02008-05-01 23:38:35 +00001095 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
Ted Kremenek33661802008-05-01 21:31:50 +00001096 B = Remove(B, Sym);
1097
1098 // Create a new state with the updated bindings.
1099 ValueState StVals = *St;
1100 SetRefBindings(StVals, B);
1101 St = StateMgr.getPersistentState(StVals);
1102 }
1103
1104 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
1105 }
1106 }
1107
1108 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001109}
1110
1111bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1112 GRExprEngine& Eng,
1113 GRStmtNodeBuilder<ValueState>& Builder,
1114 ObjCMessageExpr* ME,
1115 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001116
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001117 if (isGCEnabled())
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001118 return true;
1119
Ted Kremenek1feab292008-04-16 04:28:53 +00001120 // Handle "toll-free bridging" of calls to "Release" and "Retain".
1121
1122 // FIXME: track the underlying object type associated so that we can
1123 // flag illegal uses of toll-free bridging (or at least handle it
1124 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001125
1126 Selector S = ME->getSelector();
1127
1128 if (!S.isUnarySelector())
1129 return true;
1130
Ted Kremenek1feab292008-04-16 04:28:53 +00001131 Expr* Receiver = ME->getReceiver();
1132
1133 if (!Receiver)
1134 return true;
1135
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001136 // Check if we are calling "autorelease".
1137
1138 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001139
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001140 if (S == AutoreleaseSelector)
1141 mode = IsAutorelease;
1142 else if (S == RetainSelector)
1143 mode = IsRetain;
1144 else if (S == ReleaseSelector)
1145 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001146
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001147 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001148 return true;
1149
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001150 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001151 ValueStateManager& StateMgr = Eng.getStateManager();
1152 ValueState* St = Builder.GetState(Pred);
1153 RVal V = StateMgr.GetRVal(St, Receiver);
1154
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001155 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001156 if (!isa<lval::SymbolVal>(V))
1157 return true;
1158
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001159 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001160 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1161 RefBindings B = GetRefBindings(*St);
1162
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001163 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001164 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001165
Ted Kremenek1feab292008-04-16 04:28:53 +00001166 if (!T)
1167 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001168
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001169 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001170
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001171 // Update the bindings.
1172 switch (mode) {
1173 case IsNone:
1174 assert(false);
1175
1176 case IsRelease:
1177 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1178 break;
1179
1180 case IsRetain:
1181 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1182 break;
1183
1184 case IsAutorelease:
1185 // For now we just stop tracking a value if we see
1186 // it sent "autorelease." In the future we can potentially
1187 // track the associated pool.
1188 B = Remove(B, Sym);
1189 break;
1190 }
1191
1192 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001193 ValueState StVals = *St;
1194 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001195 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001196
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001197 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001198 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001199 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001200 else
1201 Builder.MakeNode(Dst, ME, Pred, St);
1202
1203 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001204}
1205
Ted Kremenek7aef4842008-04-16 20:40:59 +00001206// Stores.
1207
1208void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1209 GRExprEngine& Eng,
1210 GRStmtNodeBuilder<ValueState>& Builder,
1211 Expr* E, ExplodedNode<ValueState>* Pred,
1212 ValueState* St, RVal TargetLV, RVal Val) {
1213
1214 // Check if we have a binding for "Val" and if we are storing it to something
1215 // we don't understand or otherwise the value "escapes" the function.
1216
1217 if (!isa<lval::SymbolVal>(Val))
1218 return;
1219
1220 // Are we storing to something that causes the value to "escape"?
1221
1222 bool escapes = false;
1223
1224 if (!isa<lval::DeclVal>(TargetLV))
1225 escapes = true;
1226 else
1227 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1228
1229 if (!escapes)
1230 return;
1231
1232 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1233 RefBindings B = GetRefBindings(*St);
1234 RefBindings::TreeTy* T = B.SlimFind(Sym);
1235
1236 if (!T)
1237 return;
1238
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001239 // Nuke the binding.
1240 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001241
1242 // Hand of the remaining logic to the parent implementation.
1243 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1244}
1245
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001246
1247ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1248 SymbolID sid) {
1249 ValueState StImpl = *St;
1250 RefBindings B = GetRefBindings(StImpl);
1251 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1252 return VMgr.getPersistentState(StImpl);
1253}
1254
Ted Kremenekffefc352008-04-11 22:25:11 +00001255// End-of-path.
1256
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001257ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1258 ValueState* St, SymbolID sid,
1259 RefVal V, bool& hasLeak) {
1260
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001261 hasLeak = V.isOwned() ||
1262 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001263
1264 if (!hasLeak)
1265 return NukeBinding(VMgr, St, sid);
1266
1267 RefBindings B = GetRefBindings(*St);
1268 ValueState StImpl = *St;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001269
1270 StImpl.CheckerState =
1271 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1272
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001273 return VMgr.getPersistentState(StImpl);
1274}
1275
1276void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001277 GREndPathNodeBuilder<ValueState>& Builder) {
1278
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001279 ValueState* St = Builder.getState();
1280 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001281
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001282 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001283
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001284 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1285 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001286
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001287 St = HandleSymbolDeath(Eng.getStateManager(), St,
1288 (*I).first, (*I).second, hasLeak);
1289
1290 if (hasLeak) Leaked.push_back((*I).first);
1291 }
Ted Kremenek541db372008-04-24 23:57:27 +00001292
1293 if (Leaked.empty())
1294 return;
1295
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001296 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001297
Ted Kremenek541db372008-04-24 23:57:27 +00001298 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001299 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001300
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001301 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1302 assert (!LeaksAtNode);
1303 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001304
1305 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1306 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001307 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001308}
1309
Ted Kremenek541db372008-04-24 23:57:27 +00001310// Dead symbols.
1311
1312void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1313 GRExprEngine& Eng,
1314 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001315 ExplodedNode<ValueState>* Pred,
1316 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001317 ValueState* St,
1318 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001319
Ted Kremenek541db372008-04-24 23:57:27 +00001320 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1321
1322 RefBindings B = GetRefBindings(*St);
1323 llvm::SmallVector<SymbolID, 10> Leaked;
1324
1325 for (ValueStateManager::DeadSymbolsTy::const_iterator
1326 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1327
1328 RefBindings::TreeTy* T = B.SlimFind(*I);
1329
1330 if (!T)
1331 continue;
1332
1333 bool hasLeak = false;
1334
1335 St = HandleSymbolDeath(Eng.getStateManager(), St,
1336 *I, T->getValue().second, hasLeak);
1337
1338 if (hasLeak) Leaked.push_back(*I);
1339 }
1340
1341 if (Leaked.empty())
1342 return;
1343
1344 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1345
1346 if (!N)
1347 return;
1348
1349 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1350 assert (!LeaksAtNode);
1351 LeaksAtNode = new std::vector<SymbolID>();
1352
1353 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1354 E = Leaked.end(); I != E; ++I)
1355 (*LeaksAtNode).push_back(*I);
1356}
1357
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001358 // Return statements.
1359
1360void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1361 GRExprEngine& Eng,
1362 GRStmtNodeBuilder<ValueState>& Builder,
1363 ReturnStmt* S,
1364 ExplodedNode<ValueState>* Pred) {
1365
1366 Expr* RetE = S->getRetValue();
1367 if (!RetE) return;
1368
1369 ValueStateManager& StateMgr = Eng.getStateManager();
1370 ValueState* St = Builder.GetState(Pred);
1371 RVal V = StateMgr.GetRVal(St, RetE);
1372
1373 if (!isa<lval::SymbolVal>(V))
1374 return;
1375
1376 // Get the reference count binding (if any).
1377 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1378 RefBindings B = GetRefBindings(*St);
1379 RefBindings::TreeTy* T = B.SlimFind(Sym);
1380
1381 if (!T)
1382 return;
1383
1384 // Change the reference count.
1385
1386 RefVal X = T->getValue().second;
1387
1388 switch (X.getKind()) {
1389
1390 case RefVal::Owned: {
1391 unsigned cnt = X.getCount();
1392 X = RefVal::makeReturnedOwned(cnt);
1393 break;
1394 }
1395
1396 case RefVal::NotOwned: {
1397 unsigned cnt = X.getCount();
1398 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1399 : RefVal::makeReturnedNotOwned();
1400 break;
1401 }
1402
1403 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001404 return;
1405 }
1406
1407 // Update the binding.
1408
1409 ValueState StImpl = *St;
1410 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1411 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1412}
1413
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001414// Assumptions.
1415
1416ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1417 RVal Cond, bool Assumption,
1418 bool& isFeasible) {
1419
1420 // FIXME: We may add to the interface of EvalAssume the list of symbols
1421 // whose assumptions have changed. For now we just iterate through the
1422 // bindings and check if any of the tracked symbols are NULL. This isn't
1423 // too bad since the number of symbols we will track in practice are
1424 // probably small and EvalAssume is only called at branches and a few
1425 // other places.
1426
1427 RefBindings B = GetRefBindings(*St);
1428
1429 if (B.isEmpty())
1430 return St;
1431
1432 bool changed = false;
1433
1434 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1435
1436 // Check if the symbol is null (or equal to any constant).
1437 // If this is the case, stop tracking the symbol.
1438
1439 if (St->getSymVal(I.getKey())) {
1440 changed = true;
1441 B = RefBFactory.Remove(B, I.getKey());
1442 }
1443 }
1444
1445 if (!changed)
1446 return St;
1447
1448 ValueState StImpl = *St;
1449 StImpl.CheckerState = B.getRoot();
1450 return Eng.getStateManager().getPersistentState(StImpl);
1451}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001452
1453CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001454 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001455 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001456
Ted Kremenek0d721572008-03-11 17:48:22 +00001457 // FIXME: This dispatch can potentially be sped up by unifiying it into
1458 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001459
Ted Kremenek0d721572008-03-11 17:48:22 +00001460 switch (E) {
1461 default:
1462 assert (false && "Unhandled CFRef transition.");
1463
1464 case DoNothing:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001465 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001466 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001467 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001468 break;
1469 }
1470
Ted Kremenek0d721572008-03-11 17:48:22 +00001471 return B;
1472
1473 case IncRef:
1474 switch (V.getKind()) {
1475 default:
1476 assert(false);
1477
1478 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001479 V = RefVal::makeOwned(V.getCount()+1);
1480 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001481
Ted Kremenek0d721572008-03-11 17:48:22 +00001482 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001483 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001484 break;
1485
1486 case RefVal::Released:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001487 if (isGCEnabled())
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001488 V = RefVal::makeOwned();
1489 else {
1490 V = RefVal::makeUseAfterRelease();
1491 hasErr = V.getKind();
1492 }
1493
Ted Kremenek0d721572008-03-11 17:48:22 +00001494 break;
1495 }
1496
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001497 break;
1498
Ted Kremenek0d721572008-03-11 17:48:22 +00001499 case DecRef:
1500 switch (V.getKind()) {
1501 default:
1502 assert (false);
1503
1504 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001505 unsigned Count = V.getCount();
1506 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001507 break;
1508 }
1509
Ted Kremenekc4f81022008-04-10 23:09:18 +00001510 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001511 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001512
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001513 if (Count > 0)
1514 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001515 else {
1516 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001517 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001518 }
1519
Ted Kremenek0d721572008-03-11 17:48:22 +00001520 break;
1521 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001522
1523 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001524 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001525 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001526 break;
1527 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001528
1529 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001530 }
1531
1532 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001533}
1534
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001535
1536//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001537// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001538//===----------------------------------------------------------------------===//
1539
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001540namespace {
1541
1542 //===-------------===//
1543 // Bug Descriptions. //
1544 //===-------------===//
1545
Ted Kremeneke3769852008-04-18 20:54:29 +00001546 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001547 protected:
1548 CFRefCount& TF;
1549
1550 public:
1551 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001552
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001553 CFRefCount& getTF() { return TF; }
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001554 const CFRefCount& getTF() const { return TF; }
1555
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001556 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001557 };
1558
1559 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1560 public:
1561 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1562
1563 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001564 return "Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001565 }
1566 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001567 return "Reference-counted object is used"
1568 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001569 }
1570
1571 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001572 };
1573
1574 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1575 public:
1576 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1577
1578 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001579 return "Bad Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001580 }
1581 virtual const char* getDescription() const {
1582 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001583 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001584 "The object is not owned at this point by the caller.";
1585 }
1586
1587 virtual void EmitWarnings(BugReporter& BR);
1588 };
1589
1590 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1591 public:
1592 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1593
1594 virtual const char* getName() const {
Ted Kremenek0ff3f202008-05-05 23:16:31 +00001595 return getTF().isGCEnabled() ? "Memory Leak (GC)" : "Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001596 }
1597
1598 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001599 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001600 }
1601
1602 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001603 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001604 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001605 };
1606
1607 //===---------===//
1608 // Bug Reports. //
1609 //===---------===//
1610
1611 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1612 SymbolID Sym;
1613 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001614 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001615 : RangedBugReport(D, n), Sym(sym) {}
1616
1617 virtual ~CFRefReport() {}
1618
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001619 CFRefBug& getBugType() {
1620 return (CFRefBug&) RangedBugReport::getBugType();
1621 }
1622 const CFRefBug& getBugType() const {
1623 return (const CFRefBug&) RangedBugReport::getBugType();
1624 }
1625
1626 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1627 const SourceRange*& end) {
1628
Ted Kremenek198cae02008-05-02 20:53:50 +00001629 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001630 RangedBugReport::getRanges(BR, beg, end);
1631 else {
1632 beg = 0;
1633 end = 0;
1634 }
1635 }
1636
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001637 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1638 ExplodedNode<ValueState>* N);
1639
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001640 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001641
1642 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1643 ExplodedNode<ValueState>* PrevN,
1644 ExplodedGraph<ValueState>& G,
1645 BugReporter& BR);
1646 };
1647
1648
1649} // end anonymous namespace
1650
1651void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001652 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001653 Eng.Register(new UseAfterRelease(*this));
1654 Eng.Register(new BadRelease(*this));
1655 Eng.Register(new Leak(*this));
1656}
1657
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001658
1659static const char* Msgs[] = {
1660 "Code is compiled in garbage collection only mode" // GC only
1661 " (the bug occurs with garbage collection enabled).",
1662
1663 "Code is compiled without garbage collection.", // No GC.
1664
1665 "Code is compiled for use with and without garbage collection (GC)."
1666 " The bug occurs with GC enabled.", // Hybrid, with GC.
1667
1668 "Code is compiled for use with and without garbage collection (GC)."
1669 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1670};
1671
1672std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1673 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1674
1675 switch (TF.getLangOptions().getGCMode()) {
1676 default:
1677 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001678
1679 case LangOptions::GCOnly:
1680 assert (TF.isGCEnabled());
1681 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001682
1683 case LangOptions::NonGC:
1684 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001685 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1686
1687 case LangOptions::HybridGC:
1688 if (TF.isGCEnabled())
1689 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1690 else
1691 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1692 }
1693}
1694
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001695PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1696 ExplodedNode<ValueState>* PrevN,
1697 ExplodedGraph<ValueState>& G,
1698 BugReporter& BR) {
1699
1700 // Check if the type state has changed.
1701
1702 ValueState* PrevSt = PrevN->getState();
1703 ValueState* CurrSt = N->getState();
1704
1705 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1706 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1707
Ted Kremeneka8503952008-04-18 04:55:01 +00001708 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1709 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001710
Ted Kremeneka8503952008-04-18 04:55:01 +00001711 if (!CurrT)
1712 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001713
Ted Kremeneka8503952008-04-18 04:55:01 +00001714 const char* Msg = NULL;
1715 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001716
Ted Kremeneka8503952008-04-18 04:55:01 +00001717 if (!PrevT) {
1718
Ted Kremenek9363fd92008-05-05 17:53:17 +00001719 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1720
1721 if (CurrV.isOwned()) {
1722
1723 if (isa<CallExpr>(S))
1724 Msg = "Function call returns an object with a +1 retain count"
1725 " (owning reference).";
1726 else {
1727 assert (isa<ObjCMessageExpr>(S));
1728 Msg = "Method returns an object with a +1 retain count"
1729 " (owning reference).";
1730 }
1731 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001732 else {
1733 assert (CurrV.isNotOwned());
Ted Kremenek9363fd92008-05-05 17:53:17 +00001734
1735 if (isa<CallExpr>(S))
1736 Msg = "Function call returns an object with a +0 retain count"
1737 " (non-owning reference).";
1738 else {
1739 assert (isa<ObjCMessageExpr>(S));
1740 Msg = "Method returns an object with a +0 retain count"
1741 " (non-owning reference).";
1742 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001743 }
Ted Kremenek9363fd92008-05-05 17:53:17 +00001744
Ted Kremeneka8503952008-04-18 04:55:01 +00001745 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1746 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1747
1748 if (Expr* Exp = dyn_cast<Expr>(S))
1749 P->addRange(Exp->getSourceRange());
1750
1751 return P;
1752 }
1753
1754 // Determine if the typestate has changed.
1755
1756 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1757
1758 if (PrevV == CurrV)
1759 return NULL;
1760
1761 // The typestate has changed.
1762
1763 std::ostringstream os;
1764
1765 switch (CurrV.getKind()) {
1766 case RefVal::Owned:
1767 case RefVal::NotOwned:
1768 assert (PrevV.getKind() == CurrV.getKind());
1769
1770 if (PrevV.getCount() > CurrV.getCount())
1771 os << "Reference count decremented.";
1772 else
1773 os << "Reference count incremented.";
1774
Ted Kremenek9363fd92008-05-05 17:53:17 +00001775 if (unsigned Count = GetCount(CurrV)) {
1776
1777 os << " Object has +" << Count;
Ted Kremenek752b5842008-04-18 05:32:44 +00001778
Ted Kremenek9363fd92008-05-05 17:53:17 +00001779 if (Count > 1)
1780 os << " retain counts.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001781 else
Ted Kremenek9363fd92008-05-05 17:53:17 +00001782 os << " retain count.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001783 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001784
1785 Msg = os.str().c_str();
1786
1787 break;
1788
1789 case RefVal::Released:
1790 Msg = "Object released.";
1791 break;
1792
1793 case RefVal::ReturnedOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001794 Msg = "Object returned to caller as owning reference (single retain count"
1795 " transferred to caller).";
Ted Kremeneka8503952008-04-18 04:55:01 +00001796 break;
1797
1798 case RefVal::ReturnedNotOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001799 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremeneka8503952008-04-18 04:55:01 +00001800 break;
1801
1802 default:
1803 return NULL;
1804 }
1805
1806 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1807 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1808 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1809
1810 // Add the range by scanning the children of the statement for any bindings
1811 // to Sym.
1812
1813 ValueStateManager& VSM = BR.getEngine().getStateManager();
1814
1815 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1816 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1817 RVal X = VSM.GetRVal(CurrSt, Exp);
1818
1819 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1820 if (SV->getSymbol() == Sym) {
1821 P->addRange(Exp->getSourceRange()); break;
1822 }
1823 }
1824
1825 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001826}
1827
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001828PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremenekea794e92008-05-05 18:50:19 +00001829 ExplodedNode<ValueState>* EndN) {
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001830
1831 if (!getBugType().isLeak())
Ted Kremenekea794e92008-05-05 18:50:19 +00001832 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001833
Ted Kremenek9363fd92008-05-05 17:53:17 +00001834 typedef CFRefCount::RefBindings RefBindings;
1835
1836 // Get the retain count.
1837 unsigned long RetCount = 0;
1838
1839 {
Ted Kremenekea794e92008-05-05 18:50:19 +00001840 ValueState* St = EndN->getState();
Ted Kremenek9363fd92008-05-05 17:53:17 +00001841 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1842 RefBindings::TreeTy* T = B.SlimFind(Sym);
1843 assert (T);
1844 RetCount = GetCount(T->getValue().second);
1845 }
1846
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001847 // We are a leak. Walk up the graph to get to the first node where the
1848 // symbol appeared.
1849
Ted Kremenekea794e92008-05-05 18:50:19 +00001850 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001851 ExplodedNode<ValueState>* Last = N;
Ted Kremenekea794e92008-05-05 18:50:19 +00001852
Ted Kremenek198cae02008-05-02 20:53:50 +00001853 // Find the first node that referred to the tracked symbol. We also
1854 // try and find the first VarDecl the value was stored to.
1855
1856 VarDecl* FirstDecl = 0;
Ted Kremenekea794e92008-05-05 18:50:19 +00001857
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001858 while (N) {
1859 ValueState* St = N->getState();
1860 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001861 RefBindings::TreeTy* T = B.SlimFind(Sym);
1862
1863 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001864 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00001865
1866 VarDecl* VD = 0;
1867
1868 // Determine if there is an LVal binding to the symbol.
1869 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1870 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1871 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1872 continue;
1873
1874 if (VD) { // Multiple decls map to this symbol.
1875 VD = 0;
1876 break;
1877 }
1878
1879 VD = I->first;
1880 }
1881
1882 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001883
1884 Last = N;
1885 N = N->pred_empty() ? NULL : *(N->pred_begin());
1886 }
1887
Ted Kremenekea794e92008-05-05 18:50:19 +00001888 // Get the allocate site.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001889
1890 assert (Last);
1891 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1892
Ted Kremenekea794e92008-05-05 18:50:19 +00001893 SourceManager& SMgr = BR.getContext().getSourceManager();
1894 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001895
Ted Kremenekea794e92008-05-05 18:50:19 +00001896 // Get the leak site. We may have multiple ExplodedNodes (one with the
1897 // leak) that occur on the same line number; if the node with the leak
1898 // has any immediate predecessor nodes with the same line number, find
1899 // any transitive-successors that have a different statement and use that
1900 // line number instead. This avoids emiting a diagnostic like:
1901 //
1902 // // 'y' is leaked.
1903 // int x = foo(y);
1904 //
1905 // instead we want:
1906 //
1907 // int x = foo(y);
1908 // // 'y' is leaked.
1909
1910 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
1911 assert (S);
1912 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
1913
1914 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
1915 // it occur on the same line?
1916
1917 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
1918 N = *(EndN->pred_begin());
1919
1920 do {
1921 ProgramPoint P = N->getLocation();
1922
1923 if (!isa<PostStmt>(P))
1924 break;
1925
1926 // Predecessor at same line?
1927
1928 Stmt* SPred = cast<PostStmt>(P).getStmt();
1929
1930 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine)
1931 break;
1932
1933 // The predecessor (where the object was not yet leaked) is a statement
1934 // on the same line. Get the first successor statement that appears
1935 // on a different line. For this operation, we can traverse the
1936 // non-trimmed graph.
1937
1938 N = getEndNode(); // This is the node where the leak occured in the
1939 // original graph.
1940
1941 while (!N->succ_empty()) {
1942
1943 N = *(N->succ_begin());
1944 ProgramPoint P = N->getLocation();
1945
1946 if (!isa<PostStmt>(P))
1947 continue;
1948
1949 Stmt* SSucc = cast<PostStmt>(P).getStmt();
1950
1951 if (SMgr.getLogicalLineNumber(SSucc->getLocStart()) != EndLine) {
1952 S = SSucc;
1953 break;
1954 }
1955 }
1956 }
1957 while (false);
1958
1959 // Construct the location.
1960
1961 FullSourceLoc L(S->getLocStart(), SMgr);
1962
1963 // Generate the diagnostic.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001964 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00001965
Ted Kremenekea794e92008-05-05 18:50:19 +00001966 os << "Object allocated on line " << AllocLine;
Ted Kremenek198cae02008-05-02 20:53:50 +00001967
1968 if (FirstDecl)
1969 os << " and stored into '" << FirstDecl->getName() << '\'';
1970
Ted Kremenek9363fd92008-05-05 17:53:17 +00001971 os << " is no longer referenced after this point and has a retain count of +"
1972 << RetCount << " (object leaked).";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001973
Ted Kremenekea794e92008-05-05 18:50:19 +00001974 return new PathDiagnosticPiece(L, os.str());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001975}
1976
Ted Kremenek7d421f32008-04-09 23:49:11 +00001977void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001978
Ted Kremenek7d421f32008-04-09 23:49:11 +00001979 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1980 E = TF.use_after_end(); I != E; ++I) {
1981
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001982 CFRefReport report(*this, I->first, I->second.second);
1983 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00001984 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001985 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001986}
1987
1988void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001989
Ted Kremenek7d421f32008-04-09 23:49:11 +00001990 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1991 E = TF.bad_release_end(); I != E; ++I) {
1992
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001993 CFRefReport report(*this, I->first, I->second.second);
1994 report.addRange(I->second.first->getSourceRange());
1995 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00001996 }
1997}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001998
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001999void Leak::EmitWarnings(BugReporter& BR) {
2000
2001 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2002 E = TF.leaks_end(); I != E; ++I) {
2003
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00002004 std::vector<SymbolID>& SymV = *(I->second);
2005 unsigned n = SymV.size();
2006
2007 for (unsigned i = 0; i < n; ++i) {
2008 CFRefReport report(*this, I->first, SymV[i]);
2009 BR.EmitWarning(report);
2010 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00002011 }
2012}
2013
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00002014void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2015 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2016 I!=E; ++I)
2017 Nodes.push_back(I->first);
2018}
2019
Ted Kremeneka7338b42008-03-11 06:39:11 +00002020//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00002021// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00002022//===----------------------------------------------------------------------===//
2023
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002024GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00002025 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00002026 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00002027 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00002028}