blob: ed8c595745af5aa6d99db309231bb33618729fd2 [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 Kremenekae855d42008-04-24 17:22:33 +0000217
Ted Kremeneka7338b42008-03-11 06:39:11 +0000218public:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000219
220 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000221 : Ctx(ctx), GCEnabled(gcenabled) {}
222
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000223 ~RetainSummaryManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000224
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000225 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
226
227 bool isGCEnabled() const { return GCEnabled; }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000228};
229
230} // end anonymous namespace
231
232//===----------------------------------------------------------------------===//
233// Implementation of checker data structures.
234//===----------------------------------------------------------------------===//
235
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000236RetainSummaryManager::~RetainSummaryManager() {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000237
238 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
239 // mitigating the need to do explicit cleanup of the
240 // Argument-Effect summaries.
241
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000242 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(), E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremeneka7338b42008-03-11 06:39:11 +0000243 I->getValue().~ArgEffects();
Ted Kremenek827f93b2008-03-06 00:08:09 +0000244}
Ted Kremeneka7338b42008-03-11 06:39:11 +0000245
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000246ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000247
Ted Kremenekae855d42008-04-24 17:22:33 +0000248 if (ScratchArgs.empty())
249 return NULL;
250
251 // Compute a profile for a non-empty ScratchArgs.
252
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000253 llvm::FoldingSetNodeID profile;
Ted Kremenekae855d42008-04-24 17:22:33 +0000254
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000255 profile.Add(ScratchArgs);
256 void* InsertPos;
257
Ted Kremenekae855d42008-04-24 17:22:33 +0000258 // Look up the uniqued copy, or create a new one.
259
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000260 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000261 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000262
Ted Kremenekae855d42008-04-24 17:22:33 +0000263 if (E) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000264 ScratchArgs.clear();
265 return &E->getValue();
266 }
267
268 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
269 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
270
271 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000272 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000273
274 ScratchArgs.clear();
275 return &E->getValue();
276}
277
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000278RetainSummary* RetainSummaryManager::getPersistentSummary(ArgEffects* AE,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000279 RetEffect RE) {
280
Ted Kremenekae855d42008-04-24 17:22:33 +0000281 // Generate a profile for the summary.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000282 llvm::FoldingSetNodeID profile;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000283 RetainSummary::Profile(profile, AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000284
Ted Kremenekae855d42008-04-24 17:22:33 +0000285 // Look up the uniqued summary, or create one if it doesn't exist.
286 void* InsertPos;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000287 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000288
289 if (Summ)
290 return Summ;
291
Ted Kremenekae855d42008-04-24 17:22:33 +0000292 // Create the summary and return it.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000293 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
294 new (Summ) RetainSummary(AE, RE);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000295 SummarySet.InsertNode(Summ, InsertPos);
296
297 return Summ;
298}
299
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000300//===----------------------------------------------------------------------===//
301// Summary creation for functions (largely uses of Core Foundation).
302//===----------------------------------------------------------------------===//
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000303
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000304RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000305 ASTContext& Ctx) {
306
307 SourceLocation Loc = FD->getLocation();
308
309 if (!Loc.isFileID())
310 return NULL;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000311
Ted Kremenekae855d42008-04-24 17:22:33 +0000312 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000313 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenekae855d42008-04-24 17:22:33 +0000314
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000315 if (I != FuncSummaries.end())
Ted Kremenekae855d42008-04-24 17:22:33 +0000316 return I->second;
317
318 // No summary. Generate one.
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000319 const char* FName = FD->getIdentifier()->getName();
320
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000321 RetainSummary *S = 0;
Ted Kremenek562c1302008-05-05 16:51:50 +0000322
323 if (FName[0] == 'C' && FName[1] == 'F')
324 S = getCFSummary(FD, FName);
325 else if (FName[0] == 'N' && FName[1] == 'S')
326 S = getNSSummary(FD, FName);
Ted Kremenekae855d42008-04-24 17:22:33 +0000327
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000328 FuncSummaries[FD] = S;
Ted Kremenek562c1302008-05-05 16:51:50 +0000329 return S;
Ted Kremenek827f93b2008-03-06 00:08:09 +0000330}
331
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000332RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek562c1302008-05-05 16:51:50 +0000333 const char* FName) {
334 FName += 2;
335
336 if (strcmp(FName, "MakeCollectable") == 0)
337 return getUnarySummary(FD, cfmakecollectable);
338
339 return 0;
340}
341
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000342RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000343 const char* FName) {
Ted Kremenek562c1302008-05-05 16:51:50 +0000344
345 FName += 2;
346
347 if (strcmp(FName, "Retain") == 0)
348 return getUnarySummary(FD, cfretain);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000349
Ted Kremenek562c1302008-05-05 16:51:50 +0000350 if (strcmp(FName, "Release") == 0)
351 return getUnarySummary(FD, cfrelease);
352
353 if (strcmp(FName, "MakeCollectable") == 0)
354 return getUnarySummary(FD, cfmakecollectable);
355
356 if (strstr(FName, "Create") || strstr(FName, "Copy"))
357 return getCFSummaryCreateRule(FD);
358
359 if (strstr(FName, "Get"))
360 return getCFSummaryGetRule(FD);
361
362 return 0;
363}
364
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000365RetainSummary*
366RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000367
368 FunctionTypeProto* FT =
369 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
370
Ted Kremenek562c1302008-05-05 16:51:50 +0000371 if (FT) {
372
373 if (FT->getNumArgs() != 1)
374 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000375
Ted Kremenek562c1302008-05-05 16:51:50 +0000376 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
377
378 if (!ArgT)
379 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000380
Ted Kremenek562c1302008-05-05 16:51:50 +0000381 if (!ArgT->isPointerType())
382 return NULL;
383 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000384
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000385 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000386
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000387 switch (func) {
388 case cfretain: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000389 ScratchArgs.push_back(std::make_pair(0, IncRef));
390 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
391 }
392
393 case cfrelease: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000394 ScratchArgs.push_back(std::make_pair(0, DecRef));
395 return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
396 }
397
398 case cfmakecollectable: {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000399 if (GCEnabled)
400 ScratchArgs.push_back(std::make_pair(0, DecRef));
401
Ted Kremenek562c1302008-05-05 16:51:50 +0000402 return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000403 }
404
405 default:
Ted Kremenek562c1302008-05-05 16:51:50 +0000406 assert (false && "Not a supported unary function.");
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000407 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000408}
409
410static bool isCFRefType(QualType T) {
411
412 if (!T->isPointerType())
413 return false;
414
415 // Check the typedef for the name "CF" and the substring "Ref".
416
417 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
418
419 if (!TD)
420 return false;
421
422 const char* TDName = TD->getDecl()->getIdentifier()->getName();
423 assert (TDName);
424
425 if (TDName[0] != 'C' || TDName[1] != 'F')
426 return false;
427
428 if (strstr(TDName, "Ref") == 0)
429 return false;
430
431 return true;
432}
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000433
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000434RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000435
Ted Kremenek562c1302008-05-05 16:51:50 +0000436 FunctionTypeProto* FT =
437 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
438
439 if (FT && !isCFRefType(FT->getResultType()))
440 return 0;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000441
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000442 // FIXME: Add special-cases for functions that retain/release. For now
443 // just handle the default case.
Ted Kremenekae855d42008-04-24 17:22:33 +0000444
445 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000446 return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
447}
448
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000449RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000450
Ted Kremenek562c1302008-05-05 16:51:50 +0000451 FunctionTypeProto* FT =
452 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremenekd4244d42008-04-11 20:11:19 +0000453
Ted Kremenek562c1302008-05-05 16:51:50 +0000454 if (FT) {
455 QualType RetTy = FT->getResultType();
Ted Kremenekd4244d42008-04-11 20:11:19 +0000456
Ted Kremenek562c1302008-05-05 16:51:50 +0000457 // FIXME: For now we assume that all pointer types returned are referenced
458 // counted. Since this is the "Get" rule, we assume non-ownership, which
459 // works fine for things that are not reference counted. We do this because
460 // some generic data structures return "void*". We need something better
461 // in the future.
462
463 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
464 return 0;
465 }
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000466
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000467 // FIXME: Add special-cases for functions that retain/release. For now
468 // just handle the default case.
469
Ted Kremenekae855d42008-04-24 17:22:33 +0000470 assert (ScratchArgs.empty());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000471 return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
472}
473
Ted Kremeneka7338b42008-03-11 06:39:11 +0000474//===----------------------------------------------------------------------===//
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000475// Summary creation for Selectors.
476//===----------------------------------------------------------------------===//
477
478
479
480
481//===----------------------------------------------------------------------===//
Ted Kremenek7aef4842008-04-16 20:40:59 +0000482// Reference-counting logic (typestate + counts).
Ted Kremeneka7338b42008-03-11 06:39:11 +0000483//===----------------------------------------------------------------------===//
484
Ted Kremeneka7338b42008-03-11 06:39:11 +0000485namespace {
486
Ted Kremenek7d421f32008-04-09 23:49:11 +0000487class VISIBILITY_HIDDEN RefVal {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000488public:
Ted Kremenek0d721572008-03-11 17:48:22 +0000489
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000490 enum Kind {
491 Owned = 0, // Owning reference.
492 NotOwned, // Reference is not owned by still valid (not freed).
493 Released, // Object has been released.
494 ReturnedOwned, // Returned object passes ownership to caller.
495 ReturnedNotOwned, // Return object does not pass ownership to caller.
496 ErrorUseAfterRelease, // Object used after released.
497 ErrorReleaseNotOwned, // Release of an object that was not owned.
498 ErrorLeak // A memory leak due to excessive reference counts.
499 };
Ted Kremenek0d721572008-03-11 17:48:22 +0000500
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000501private:
502
503 Kind kind;
504 unsigned Cnt;
505
506 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
507
508 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek0d721572008-03-11 17:48:22 +0000509
510public:
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000511
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000512 Kind getKind() const { return kind; }
Ted Kremenek0d721572008-03-11 17:48:22 +0000513
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000514 unsigned getCount() const { return Cnt; }
515
516 // Useful predicates.
Ted Kremenek0d721572008-03-11 17:48:22 +0000517
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000518 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
519
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000520 static bool isLeak(Kind k) { return k == ErrorLeak; }
521
Ted Kremenekffefc352008-04-11 22:25:11 +0000522 bool isOwned() const {
523 return getKind() == Owned;
524 }
525
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000526 bool isNotOwned() const {
527 return getKind() == NotOwned;
528 }
529
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000530 bool isReturnedOwned() const {
531 return getKind() == ReturnedOwned;
532 }
533
534 bool isReturnedNotOwned() const {
535 return getKind() == ReturnedNotOwned;
536 }
537
538 bool isNonLeakError() const {
539 Kind k = getKind();
540 return isError(k) && !isLeak(k);
541 }
542
543 // State creation: normal state.
544
Ted Kremenekc4f81022008-04-10 23:09:18 +0000545 static RefVal makeOwned(unsigned Count = 0) {
546 return RefVal(Owned, Count);
547 }
548
549 static RefVal makeNotOwned(unsigned Count = 0) {
550 return RefVal(NotOwned, Count);
551 }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000552
553 static RefVal makeReturnedOwned(unsigned Count) {
554 return RefVal(ReturnedOwned, Count);
555 }
556
557 static RefVal makeReturnedNotOwned() {
558 return RefVal(ReturnedNotOwned);
559 }
560
561 // State creation: errors.
Ted Kremenekc4f81022008-04-10 23:09:18 +0000562
Ted Kremenek9363fd92008-05-05 17:53:17 +0000563 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek0d721572008-03-11 17:48:22 +0000564 static RefVal makeReleased() { return RefVal(Released); }
565 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
566 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000567
568 // Comparison, profiling, and pretty-printing.
Ted Kremenek0d721572008-03-11 17:48:22 +0000569
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000570 bool operator==(const RefVal& X) const {
571 return kind == X.kind && Cnt == X.Cnt;
572 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000573
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000574 void Profile(llvm::FoldingSetNodeID& ID) const {
575 ID.AddInteger((unsigned) kind);
576 ID.AddInteger(Cnt);
577 }
578
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000579 void print(std::ostream& Out) const;
Ted Kremenek0d721572008-03-11 17:48:22 +0000580};
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000581
582void RefVal::print(std::ostream& Out) const {
583 switch (getKind()) {
584 default: assert(false);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000585 case Owned: {
586 Out << "Owned";
587 unsigned cnt = getCount();
588 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000589 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000590 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000591
Ted Kremenekc4f81022008-04-10 23:09:18 +0000592 case NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000593 Out << "NotOwned";
Ted Kremenekc4f81022008-04-10 23:09:18 +0000594 unsigned cnt = getCount();
595 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000596 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +0000597 }
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000598
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000599 case ReturnedOwned: {
600 Out << "ReturnedOwned";
601 unsigned cnt = getCount();
602 if (cnt) Out << " (+ " << cnt << ")";
603 break;
604 }
605
606 case ReturnedNotOwned: {
607 Out << "ReturnedNotOwned";
608 unsigned cnt = getCount();
609 if (cnt) Out << " (+ " << cnt << ")";
610 break;
611 }
612
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000613 case Released:
614 Out << "Released";
615 break;
616
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000617 case ErrorLeak:
618 Out << "Leaked";
619 break;
620
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000621 case ErrorUseAfterRelease:
622 Out << "Use-After-Release [ERROR]";
623 break;
624
625 case ErrorReleaseNotOwned:
626 Out << "Release of Not-Owned [ERROR]";
627 break;
628 }
629}
Ted Kremenek0d721572008-03-11 17:48:22 +0000630
Ted Kremenek9363fd92008-05-05 17:53:17 +0000631static inline unsigned GetCount(RefVal V) {
632 switch (V.getKind()) {
633 default:
634 return V.getCount();
635
636 case RefVal::Owned:
637 return V.getCount()+1;
638 }
639}
640
Ted Kremenek7aef4842008-04-16 20:40:59 +0000641//===----------------------------------------------------------------------===//
642// Transfer functions.
643//===----------------------------------------------------------------------===//
644
Ted Kremenek7d421f32008-04-09 23:49:11 +0000645class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000646public:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000647 // Type definitions.
648
Ted Kremenek0d721572008-03-11 17:48:22 +0000649 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremeneka7338b42008-03-11 06:39:11 +0000650 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000651
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000652 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
653 ReleasesNotOwnedTy;
654
655 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
656
657 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000658 LeaksTy;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000659
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000660 class BindingsPrinter : public ValueState::CheckerStatePrinter {
661 public:
662 virtual void PrintCheckerState(std::ostream& Out, void* State,
663 const char* nl, const char* sep);
664 };
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000665
666private:
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000667 // Instance variables.
668
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000669 RetainSummaryManager Summaries;
670 const bool EmitStandardWarnings;
671 const LangOptions& LOpts;
672 RefBFactoryTy RefBFactory;
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000673
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000674 UseAfterReleasesTy UseAfterReleases;
675 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000676 LeaksTy Leaks;
Ted Kremenek1daa16c2008-03-11 18:14:09 +0000677
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000678 BindingsPrinter Printer;
679
Ted Kremenek1feab292008-04-16 04:28:53 +0000680 Selector RetainSelector;
681 Selector ReleaseSelector;
Ted Kremenek3281a1f2008-05-01 02:18:37 +0000682 Selector AutoreleaseSelector;
Ted Kremenek1feab292008-04-16 04:28:53 +0000683
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000684public:
685
Ted Kremeneka7338b42008-03-11 06:39:11 +0000686 static RefBindings GetRefBindings(ValueState& StImpl) {
687 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
688 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000689
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000690private:
691
Ted Kremeneka7338b42008-03-11 06:39:11 +0000692 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
693 StImpl.CheckerState = B.getRoot();
694 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000695
Ted Kremeneka7338b42008-03-11 06:39:11 +0000696 RefBindings Remove(RefBindings B, SymbolID sym) {
697 return RefBFactory.Remove(B, sym);
698 }
699
Ted Kremenek0d721572008-03-11 17:48:22 +0000700 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +0000701 RefVal::Kind& hasErr);
702
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000703 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
704 GRStmtNodeBuilder<ValueState>& Builder,
705 Expr* NodeExpr, Expr* ErrorExpr,
706 ExplodedNode<ValueState>* Pred,
707 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000708 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000709
710 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
711 SymbolID sid, RefVal V, bool& hasLeak);
712
713 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
714 SymbolID sid);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000715
716public:
Ted Kremenek7aef4842008-04-16 20:40:59 +0000717
Ted Kremenek2f62f352008-05-02 18:01:49 +0000718 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
719 const LangOptions& lopts)
Ted Kremenek9b0c09c2008-04-29 05:33:51 +0000720 : Summaries(Ctx, gcenabled),
Ted Kremenek2f62f352008-05-02 18:01:49 +0000721 EmitStandardWarnings(StandardWarnings),
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000722 LOpts(lopts),
Ted Kremenek1bd6ddb2008-05-01 18:31:44 +0000723 RetainSelector(GetNullarySelector("retain", Ctx)),
724 ReleaseSelector(GetNullarySelector("release", Ctx)),
725 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek1feab292008-04-16 04:28:53 +0000726
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000727 virtual ~CFRefCount() {
728 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
729 delete I->second;
730 }
Ted Kremenek7d421f32008-04-09 23:49:11 +0000731
732 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000733
734 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
735 return &Printer;
736 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000737
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000738 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000739 const LangOptions& getLangOptions() const { return LOpts; }
740
Ted Kremeneka7338b42008-03-11 06:39:11 +0000741 // Calls.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000742
743 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
744 GRExprEngine& Eng,
745 GRStmtNodeBuilder<ValueState>& Builder,
746 Expr* Ex,
747 Expr* Receiver,
748 RetainSummary* Summ,
749 Expr** arg_beg, Expr** arg_end,
750 ExplodedNode<ValueState>* Pred);
751
Ted Kremeneka7338b42008-03-11 06:39:11 +0000752 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce0767f2008-03-12 21:06:49 +0000753 GRExprEngine& Eng,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000754 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek0a6a80b2008-04-23 20:12:28 +0000755 CallExpr* CE, RVal L,
Ted Kremeneka7338b42008-03-11 06:39:11 +0000756 ExplodedNode<ValueState>* Pred);
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000757
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000758
Ted Kremenek4b4738b2008-04-15 23:44:31 +0000759 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
760 GRExprEngine& Engine,
761 GRStmtNodeBuilder<ValueState>& Builder,
762 ObjCMessageExpr* ME,
763 ExplodedNode<ValueState>* Pred);
764
765 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
766 GRExprEngine& Engine,
767 GRStmtNodeBuilder<ValueState>& Builder,
768 ObjCMessageExpr* ME,
769 ExplodedNode<ValueState>* Pred);
770
Ted Kremenek7aef4842008-04-16 20:40:59 +0000771 // Stores.
772
773 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
774 GRExprEngine& Engine,
775 GRStmtNodeBuilder<ValueState>& Builder,
776 Expr* E, ExplodedNode<ValueState>* Pred,
777 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremenekffefc352008-04-11 22:25:11 +0000778 // End-of-path.
779
780 virtual void EvalEndPath(GRExprEngine& Engine,
781 GREndPathNodeBuilder<ValueState>& Builder);
782
Ted Kremenek541db372008-04-24 23:57:27 +0000783 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
784 GRExprEngine& Engine,
785 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +0000786 ExplodedNode<ValueState>* Pred,
787 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +0000788 ValueState* St,
789 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenekd9ccf682008-04-17 18:12:53 +0000790 // Return statements.
791
792 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
793 GRExprEngine& Engine,
794 GRStmtNodeBuilder<ValueState>& Builder,
795 ReturnStmt* S,
796 ExplodedNode<ValueState>* Pred);
Ted Kremenekeef8f1e2008-04-18 19:23:43 +0000797
798 // Assumptions.
799
800 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
801 RVal Cond, bool Assumption, bool& isFeasible);
802
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000803 // Error iterators.
804
805 typedef UseAfterReleasesTy::iterator use_after_iterator;
806 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000807 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000808
Ted Kremenek7d421f32008-04-09 23:49:11 +0000809 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
810 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenek10fe66d2008-04-09 01:10:13 +0000811
Ted Kremenek7d421f32008-04-09 23:49:11 +0000812 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
813 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +0000814
815 leaks_iterator leaks_begin() { return Leaks.begin(); }
816 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000817};
818
819} // end anonymous namespace
820
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000821
Ted Kremenek7d421f32008-04-09 23:49:11 +0000822
823
Ted Kremenek3b11f7a2008-03-11 19:44:10 +0000824void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
825 void* State, const char* nl,
826 const char* sep) {
827 RefBindings B((RefBindings::TreeTy*) State);
828
829 if (State)
830 Out << sep << nl;
831
832 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
833 Out << (*I).first << " : ";
834 (*I).second.print(Out);
835 Out << nl;
836 }
837}
838
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000839static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000840 return Summ ? Summ->getArg(idx) : DoNothing;
841}
842
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000843static inline RetEffect GetRetE(RetainSummary* Summ) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000844 return Summ ? Summ->getRet() : RetEffect::MakeNoRet();
845}
846
Ted Kremenek3f3c9c82008-04-16 22:32:20 +0000847void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
848 GRStmtNodeBuilder<ValueState>& Builder,
849 Expr* NodeExpr, Expr* ErrorExpr,
850 ExplodedNode<ValueState>* Pred,
851 ValueState* St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000852 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000853 Builder.BuildSinks = true;
854 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
855
856 if (!N) return;
857
858 switch (hasErr) {
859 default: assert(false);
860 case RefVal::ErrorUseAfterRelease:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000861 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000862 break;
863
864 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000865 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +0000866 break;
867 }
868}
869
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000870void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
871 GRExprEngine& Eng,
872 GRStmtNodeBuilder<ValueState>& Builder,
873 Expr* Ex,
874 Expr* Receiver,
875 RetainSummary* Summ,
876 Expr** arg_beg, Expr** arg_end,
877 ExplodedNode<ValueState>* Pred) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000878
Ted Kremenek827f93b2008-03-06 00:08:09 +0000879
Ted Kremeneka7338b42008-03-11 06:39:11 +0000880 // Get the state.
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000881 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremeneka7338b42008-03-11 06:39:11 +0000882 ValueState* St = Builder.GetState(Pred);
883
884 // Evaluate the effects of the call.
885
886 ValueState StVals = *St;
Ted Kremenek1feab292008-04-16 04:28:53 +0000887 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000888
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000889 // This function has a summary. Evaluate the effect of the arguments.
890
891 unsigned idx = 0;
892
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000893 Expr* ErrorExpr = NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000894 SymbolID ErrorSym = 0;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000895
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000896 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremeneka7338b42008-03-11 06:39:11 +0000897
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000898 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremeneka7338b42008-03-11 06:39:11 +0000899
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000900 if (isa<lval::SymbolVal>(V)) {
901 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenek455dd862008-04-11 20:23:24 +0000902 RefBindings B = GetRefBindings(StVals);
903
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000904 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek1feab292008-04-16 04:28:53 +0000905 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000906 SetRefBindings(StVals, B);
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000907
Ted Kremenek1feab292008-04-16 04:28:53 +0000908 if (hasErr) {
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000909 ErrorExpr = *I;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000910 ErrorSym = T->getValue().first;
Ted Kremenek99b0ecb2008-04-11 18:40:51 +0000911 break;
912 }
Ted Kremeneka7338b42008-03-11 06:39:11 +0000913 }
Ted Kremeneke4924202008-04-11 20:51:02 +0000914 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000915 else if (isa<LVal>(V)) {
916 // Nuke all arguments passed by reference.
Ted Kremenek455dd862008-04-11 20:23:24 +0000917 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremeneke4924202008-04-11 20:51:02 +0000918 }
Ted Kremenekbe621292008-04-22 21:39:21 +0000919 else if (isa<nonlval::LValAsInteger>(V))
920 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000921 }
Ted Kremenek1feab292008-04-16 04:28:53 +0000922
923 St = StateMgr.getPersistentState(StVals);
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000924
Ted Kremenek1feab292008-04-16 04:28:53 +0000925 if (hasErr) {
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000926 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000927 hasErr, ErrorSym);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000928 return;
Ted Kremenek0d721572008-03-11 17:48:22 +0000929 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000930
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000931 // Finally, consult the summary for the return value.
932
Ted Kremenek455dd862008-04-11 20:23:24 +0000933 RetEffect RE = GetRetE(Summ);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000934
935 switch (RE.getKind()) {
936 default:
937 assert (false && "Unhandled RetEffect."); break;
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000938
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000939 case RetEffect::NoRet:
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000940
Ted Kremenek455dd862008-04-11 20:23:24 +0000941 // Make up a symbol for the return value (not reference counted).
Ted Kremeneke4924202008-04-11 20:51:02 +0000942 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
943 // should compose behavior, not copy it.
Ted Kremenek455dd862008-04-11 20:23:24 +0000944
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000945 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenek455dd862008-04-11 20:23:24 +0000946 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000947 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek455dd862008-04-11 20:23:24 +0000948
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000949 RVal X = Ex->getType()->isPointerType()
950 ? cast<RVal>(lval::SymbolVal(Sym))
951 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenek455dd862008-04-11 20:23:24 +0000952
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000953 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek455dd862008-04-11 20:23:24 +0000954 }
955
Ted Kremenekab2fa2a2008-04-10 23:44:06 +0000956 break;
957
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000958 case RetEffect::Alias: {
959 unsigned idx = RE.getValue();
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000960 assert ((arg_end - arg_beg) >= 0);
961 assert (idx < (unsigned) (arg_end - arg_beg));
962 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
963 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000964 break;
965 }
966
967 case RetEffect::OwnedSymbol: {
968 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000969 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
970
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000971 ValueState StImpl = *St;
972 RefBindings B = GetRefBindings(StImpl);
Ted Kremenekc4f81022008-04-10 23:09:18 +0000973 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000974
975 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000976 Ex, lval::SymbolVal(Sym),
977 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000978
979 break;
980 }
981
982 case RetEffect::NotOwnedSymbol: {
983 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000984 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000985
986 ValueState StImpl = *St;
987 RefBindings B = GetRefBindings(StImpl);
988 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
989
990 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000991 Ex, lval::SymbolVal(Sym),
992 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000993
994 break;
995 }
996 }
Ted Kremeneka8c3c432008-05-05 22:11:16 +0000997
998 Builder.MakeNode(Dst, Ex, Pred, St);
999}
1000
1001
1002void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1003 GRExprEngine& Eng,
1004 GRStmtNodeBuilder<ValueState>& Builder,
1005 CallExpr* CE, RVal L,
1006 ExplodedNode<ValueState>* Pred) {
1007
1008
1009 RetainSummary* Summ = NULL;
1010
1011 // Get the summary.
1012
1013 if (isa<lval::FuncVal>(L)) {
1014 lval::FuncVal FV = cast<lval::FuncVal>(L);
1015 FunctionDecl* FD = FV.getDecl();
1016 Summ = Summaries.getSummary(FD, Eng.getContext());
1017 }
1018
1019 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1020 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek827f93b2008-03-06 00:08:09 +00001021}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001022
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001023
1024void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1025 GRExprEngine& Eng,
1026 GRStmtNodeBuilder<ValueState>& Builder,
1027 ObjCMessageExpr* ME,
1028 ExplodedNode<ValueState>* Pred) {
1029
Ted Kremenek33661802008-05-01 21:31:50 +00001030 if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred))
1031 return;
1032
1033 // The basic transfer function logic for message expressions does nothing.
1034 // We just invalidate all arguments passed in by references.
1035
1036 ValueStateManager& StateMgr = Eng.getStateManager();
1037 ValueState* St = Builder.GetState(Pred);
1038 RefBindings B = GetRefBindings(*St);
1039
1040 for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
1041 I != E; ++I) {
1042
1043 RVal V = StateMgr.GetRVal(St, *I);
1044
1045 if (isa<LVal>(V)) {
1046
1047 LVal lv = cast<LVal>(V);
1048
1049 // Did the lval bind to a symbol?
1050 RVal X = StateMgr.GetRVal(St, lv);
1051
1052 if (isa<lval::SymbolVal>(X)) {
Ted Kremenek6a24ec02008-05-01 23:38:35 +00001053 SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
Ted Kremenek33661802008-05-01 21:31:50 +00001054 B = Remove(B, Sym);
1055
1056 // Create a new state with the updated bindings.
1057 ValueState StVals = *St;
1058 SetRefBindings(StVals, B);
1059 St = StateMgr.getPersistentState(StVals);
1060 }
1061
1062 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
1063 }
1064 }
1065
1066 Builder.MakeNode(Dst, ME, Pred, St);
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001067}
1068
1069bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1070 GRExprEngine& Eng,
1071 GRStmtNodeBuilder<ValueState>& Builder,
1072 ObjCMessageExpr* ME,
1073 ExplodedNode<ValueState>* Pred) {
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001074
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001075 if (isGCEnabled())
Ted Kremenek9b0c09c2008-04-29 05:33:51 +00001076 return true;
1077
Ted Kremenek1feab292008-04-16 04:28:53 +00001078 // Handle "toll-free bridging" of calls to "Release" and "Retain".
1079
1080 // FIXME: track the underlying object type associated so that we can
1081 // flag illegal uses of toll-free bridging (or at least handle it
1082 // at casts).
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001083
1084 Selector S = ME->getSelector();
1085
1086 if (!S.isUnarySelector())
1087 return true;
1088
Ted Kremenek1feab292008-04-16 04:28:53 +00001089 Expr* Receiver = ME->getReceiver();
1090
1091 if (!Receiver)
1092 return true;
1093
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001094 // Check if we are calling "autorelease".
1095
1096 enum { IsRelease, IsRetain, IsAutorelease, IsNone } mode = IsNone;
Ted Kremenek1feab292008-04-16 04:28:53 +00001097
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001098 if (S == AutoreleaseSelector)
1099 mode = IsAutorelease;
1100 else if (S == RetainSelector)
1101 mode = IsRetain;
1102 else if (S == ReleaseSelector)
1103 mode = IsRelease;
Ted Kremenek1feab292008-04-16 04:28:53 +00001104
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001105 if (mode == IsNone)
Ted Kremenek1feab292008-04-16 04:28:53 +00001106 return true;
1107
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001108 // We have "retain", "release", or "autorelease".
Ted Kremenek1feab292008-04-16 04:28:53 +00001109 ValueStateManager& StateMgr = Eng.getStateManager();
1110 ValueState* St = Builder.GetState(Pred);
1111 RVal V = StateMgr.GetRVal(St, Receiver);
1112
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001113 // Was the argument something we are not tracking?
Ted Kremenek1feab292008-04-16 04:28:53 +00001114 if (!isa<lval::SymbolVal>(V))
1115 return true;
1116
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001117 // Get the bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001118 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1119 RefBindings B = GetRefBindings(*St);
1120
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001121 // Find the tracked value.
Ted Kremenek1feab292008-04-16 04:28:53 +00001122 RefBindings::TreeTy* T = B.SlimFind(Sym);
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001123
Ted Kremenek1feab292008-04-16 04:28:53 +00001124 if (!T)
1125 return true;
Ted Kremenek1feab292008-04-16 04:28:53 +00001126
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001127 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek1feab292008-04-16 04:28:53 +00001128
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001129 // Update the bindings.
1130 switch (mode) {
1131 case IsNone:
1132 assert(false);
1133
1134 case IsRelease:
1135 B = Update(B, Sym, T->getValue().second, DecRef, hasErr);
1136 break;
1137
1138 case IsRetain:
1139 B = Update(B, Sym, T->getValue().second, IncRef, hasErr);
1140 break;
1141
1142 case IsAutorelease:
1143 // For now we just stop tracking a value if we see
1144 // it sent "autorelease." In the future we can potentially
1145 // track the associated pool.
1146 B = Remove(B, Sym);
1147 break;
1148 }
1149
1150 // Create a new state with the updated bindings.
Ted Kremenek1feab292008-04-16 04:28:53 +00001151 ValueState StVals = *St;
1152 SetRefBindings(StVals, B);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001153 St = Eng.SetRVal(StateMgr.getPersistentState(StVals), ME, V);
Ted Kremenek1feab292008-04-16 04:28:53 +00001154
Ted Kremenek3281a1f2008-05-01 02:18:37 +00001155 // Create an error node if it exists.
Ted Kremenek1feab292008-04-16 04:28:53 +00001156 if (hasErr)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001157 ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
Ted Kremenek1feab292008-04-16 04:28:53 +00001158 else
1159 Builder.MakeNode(Dst, ME, Pred, St);
1160
1161 return false;
Ted Kremenek4b4738b2008-04-15 23:44:31 +00001162}
1163
Ted Kremenek7aef4842008-04-16 20:40:59 +00001164// Stores.
1165
1166void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1167 GRExprEngine& Eng,
1168 GRStmtNodeBuilder<ValueState>& Builder,
1169 Expr* E, ExplodedNode<ValueState>* Pred,
1170 ValueState* St, RVal TargetLV, RVal Val) {
1171
1172 // Check if we have a binding for "Val" and if we are storing it to something
1173 // we don't understand or otherwise the value "escapes" the function.
1174
1175 if (!isa<lval::SymbolVal>(Val))
1176 return;
1177
1178 // Are we storing to something that causes the value to "escape"?
1179
1180 bool escapes = false;
1181
1182 if (!isa<lval::DeclVal>(TargetLV))
1183 escapes = true;
1184 else
1185 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1186
1187 if (!escapes)
1188 return;
1189
1190 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1191 RefBindings B = GetRefBindings(*St);
1192 RefBindings::TreeTy* T = B.SlimFind(Sym);
1193
1194 if (!T)
1195 return;
1196
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001197 // Nuke the binding.
1198 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek7aef4842008-04-16 20:40:59 +00001199
1200 // Hand of the remaining logic to the parent implementation.
1201 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1202}
1203
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001204
1205ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1206 SymbolID sid) {
1207 ValueState StImpl = *St;
1208 RefBindings B = GetRefBindings(StImpl);
1209 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1210 return VMgr.getPersistentState(StImpl);
1211}
1212
Ted Kremenekffefc352008-04-11 22:25:11 +00001213// End-of-path.
1214
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001215ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1216 ValueState* St, SymbolID sid,
1217 RefVal V, bool& hasLeak) {
1218
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001219 hasLeak = V.isOwned() ||
1220 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001221
1222 if (!hasLeak)
1223 return NukeBinding(VMgr, St, sid);
1224
1225 RefBindings B = GetRefBindings(*St);
1226 ValueState StImpl = *St;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001227
1228 StImpl.CheckerState =
1229 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1230
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001231 return VMgr.getPersistentState(StImpl);
1232}
1233
1234void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremenekffefc352008-04-11 22:25:11 +00001235 GREndPathNodeBuilder<ValueState>& Builder) {
1236
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001237 ValueState* St = Builder.getState();
1238 RefBindings B = GetRefBindings(*St);
Ted Kremenekffefc352008-04-11 22:25:11 +00001239
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001240 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremenekffefc352008-04-11 22:25:11 +00001241
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001242 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1243 bool hasLeak = false;
Ted Kremenekffefc352008-04-11 22:25:11 +00001244
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001245 St = HandleSymbolDeath(Eng.getStateManager(), St,
1246 (*I).first, (*I).second, hasLeak);
1247
1248 if (hasLeak) Leaked.push_back((*I).first);
1249 }
Ted Kremenek541db372008-04-24 23:57:27 +00001250
1251 if (Leaked.empty())
1252 return;
1253
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001254 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001255
Ted Kremenek541db372008-04-24 23:57:27 +00001256 if (!N)
Ted Kremenekcfc909d2008-04-18 16:30:14 +00001257 return;
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001258
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001259 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1260 assert (!LeaksAtNode);
1261 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenek3f3c9c82008-04-16 22:32:20 +00001262
1263 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1264 E = Leaked.end(); I != E; ++I)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001265 (*LeaksAtNode).push_back(*I);
Ted Kremenekffefc352008-04-11 22:25:11 +00001266}
1267
Ted Kremenek541db372008-04-24 23:57:27 +00001268// Dead symbols.
1269
1270void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1271 GRExprEngine& Eng,
1272 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenekac91ce92008-04-25 01:25:15 +00001273 ExplodedNode<ValueState>* Pred,
1274 Stmt* S,
Ted Kremenek541db372008-04-24 23:57:27 +00001275 ValueState* St,
1276 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenekac91ce92008-04-25 01:25:15 +00001277
Ted Kremenek541db372008-04-24 23:57:27 +00001278 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1279
1280 RefBindings B = GetRefBindings(*St);
1281 llvm::SmallVector<SymbolID, 10> Leaked;
1282
1283 for (ValueStateManager::DeadSymbolsTy::const_iterator
1284 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1285
1286 RefBindings::TreeTy* T = B.SlimFind(*I);
1287
1288 if (!T)
1289 continue;
1290
1291 bool hasLeak = false;
1292
1293 St = HandleSymbolDeath(Eng.getStateManager(), St,
1294 *I, T->getValue().second, hasLeak);
1295
1296 if (hasLeak) Leaked.push_back(*I);
1297 }
1298
1299 if (Leaked.empty())
1300 return;
1301
1302 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1303
1304 if (!N)
1305 return;
1306
1307 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1308 assert (!LeaksAtNode);
1309 LeaksAtNode = new std::vector<SymbolID>();
1310
1311 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1312 E = Leaked.end(); I != E; ++I)
1313 (*LeaksAtNode).push_back(*I);
1314}
1315
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001316 // Return statements.
1317
1318void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1319 GRExprEngine& Eng,
1320 GRStmtNodeBuilder<ValueState>& Builder,
1321 ReturnStmt* S,
1322 ExplodedNode<ValueState>* Pred) {
1323
1324 Expr* RetE = S->getRetValue();
1325 if (!RetE) return;
1326
1327 ValueStateManager& StateMgr = Eng.getStateManager();
1328 ValueState* St = Builder.GetState(Pred);
1329 RVal V = StateMgr.GetRVal(St, RetE);
1330
1331 if (!isa<lval::SymbolVal>(V))
1332 return;
1333
1334 // Get the reference count binding (if any).
1335 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1336 RefBindings B = GetRefBindings(*St);
1337 RefBindings::TreeTy* T = B.SlimFind(Sym);
1338
1339 if (!T)
1340 return;
1341
1342 // Change the reference count.
1343
1344 RefVal X = T->getValue().second;
1345
1346 switch (X.getKind()) {
1347
1348 case RefVal::Owned: {
1349 unsigned cnt = X.getCount();
1350 X = RefVal::makeReturnedOwned(cnt);
1351 break;
1352 }
1353
1354 case RefVal::NotOwned: {
1355 unsigned cnt = X.getCount();
1356 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1357 : RefVal::makeReturnedNotOwned();
1358 break;
1359 }
1360
1361 default:
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001362 return;
1363 }
1364
1365 // Update the binding.
1366
1367 ValueState StImpl = *St;
1368 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1369 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1370}
1371
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001372// Assumptions.
1373
1374ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1375 RVal Cond, bool Assumption,
1376 bool& isFeasible) {
1377
1378 // FIXME: We may add to the interface of EvalAssume the list of symbols
1379 // whose assumptions have changed. For now we just iterate through the
1380 // bindings and check if any of the tracked symbols are NULL. This isn't
1381 // too bad since the number of symbols we will track in practice are
1382 // probably small and EvalAssume is only called at branches and a few
1383 // other places.
1384
1385 RefBindings B = GetRefBindings(*St);
1386
1387 if (B.isEmpty())
1388 return St;
1389
1390 bool changed = false;
1391
1392 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1393
1394 // Check if the symbol is null (or equal to any constant).
1395 // If this is the case, stop tracking the symbol.
1396
1397 if (St->getSymVal(I.getKey())) {
1398 changed = true;
1399 B = RefBFactory.Remove(B, I.getKey());
1400 }
1401 }
1402
1403 if (!changed)
1404 return St;
1405
1406 ValueState StImpl = *St;
1407 StImpl.CheckerState = B.getRoot();
1408 return Eng.getStateManager().getPersistentState(StImpl);
1409}
Ted Kremeneka7338b42008-03-11 06:39:11 +00001410
1411CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek0d721572008-03-11 17:48:22 +00001412 RefVal V, ArgEffect E,
Ted Kremenek1feab292008-04-16 04:28:53 +00001413 RefVal::Kind& hasErr) {
Ted Kremeneka7338b42008-03-11 06:39:11 +00001414
Ted Kremenek0d721572008-03-11 17:48:22 +00001415 // FIXME: This dispatch can potentially be sped up by unifiying it into
1416 // a single switch statement. Opt for simplicity for now.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001417
Ted Kremenek0d721572008-03-11 17:48:22 +00001418 switch (E) {
1419 default:
1420 assert (false && "Unhandled CFRef transition.");
1421
1422 case DoNothing:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001423 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001424 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001425 hasErr = V.getKind();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +00001426 break;
1427 }
1428
Ted Kremenek0d721572008-03-11 17:48:22 +00001429 return B;
1430
1431 case IncRef:
1432 switch (V.getKind()) {
1433 default:
1434 assert(false);
1435
1436 case RefVal::Owned:
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001437 V = RefVal::makeOwned(V.getCount()+1);
1438 break;
Ted Kremenekc4f81022008-04-10 23:09:18 +00001439
Ted Kremenek0d721572008-03-11 17:48:22 +00001440 case RefVal::NotOwned:
Ted Kremenekc4f81022008-04-10 23:09:18 +00001441 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek0d721572008-03-11 17:48:22 +00001442 break;
1443
1444 case RefVal::Released:
Ted Kremeneka8c3c432008-05-05 22:11:16 +00001445 if (isGCEnabled())
Ted Kremeneke2dd9572008-04-29 05:44:10 +00001446 V = RefVal::makeOwned();
1447 else {
1448 V = RefVal::makeUseAfterRelease();
1449 hasErr = V.getKind();
1450 }
1451
Ted Kremenek0d721572008-03-11 17:48:22 +00001452 break;
1453 }
1454
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001455 break;
1456
Ted Kremenek0d721572008-03-11 17:48:22 +00001457 case DecRef:
1458 switch (V.getKind()) {
1459 default:
1460 assert (false);
1461
1462 case RefVal::Owned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001463 unsigned Count = V.getCount();
1464 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek0d721572008-03-11 17:48:22 +00001465 break;
1466 }
1467
Ted Kremenekc4f81022008-04-10 23:09:18 +00001468 case RefVal::NotOwned: {
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001469 unsigned Count = V.getCount();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001470
Ted Kremenekd9ccf682008-04-17 18:12:53 +00001471 if (Count > 0)
1472 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenekc4f81022008-04-10 23:09:18 +00001473 else {
1474 V = RefVal::makeReleaseNotOwned();
Ted Kremenek1feab292008-04-16 04:28:53 +00001475 hasErr = V.getKind();
Ted Kremenekc4f81022008-04-10 23:09:18 +00001476 }
1477
Ted Kremenek0d721572008-03-11 17:48:22 +00001478 break;
1479 }
Ted Kremenek0d721572008-03-11 17:48:22 +00001480
1481 case RefVal::Released:
Ted Kremenek0d721572008-03-11 17:48:22 +00001482 V = RefVal::makeUseAfterRelease();
Ted Kremenek1feab292008-04-16 04:28:53 +00001483 hasErr = V.getKind();
Ted Kremenek0d721572008-03-11 17:48:22 +00001484 break;
1485 }
Ted Kremenekab2fa2a2008-04-10 23:44:06 +00001486
1487 break;
Ted Kremenek0d721572008-03-11 17:48:22 +00001488 }
1489
1490 return RefBFactory.Add(B, sym, V);
Ted Kremeneka7338b42008-03-11 06:39:11 +00001491}
1492
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001493
1494//===----------------------------------------------------------------------===//
Ted Kremenek7d421f32008-04-09 23:49:11 +00001495// Error reporting.
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001496//===----------------------------------------------------------------------===//
1497
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001498namespace {
1499
1500 //===-------------===//
1501 // Bug Descriptions. //
1502 //===-------------===//
1503
Ted Kremeneke3769852008-04-18 20:54:29 +00001504 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001505 protected:
1506 CFRefCount& TF;
1507
1508 public:
1509 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001510
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001511 CFRefCount& getTF() { return TF; }
1512
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001513 virtual bool isLeak() const { return false; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001514 };
1515
1516 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1517 public:
1518 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1519
1520 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001521 return "Core Foundation: Use-After-Release";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001522 }
1523 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001524 return "Reference-counted object is used"
1525 " after it is released.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001526 }
1527
1528 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001529 };
1530
1531 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1532 public:
1533 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1534
1535 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001536 return "Core Foundation: Release of non-owned object";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001537 }
1538 virtual const char* getDescription() const {
1539 return "Incorrect decrement of the reference count of a "
Ted Kremeneka8503952008-04-18 04:55:01 +00001540 "CoreFoundation object: "
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001541 "The object is not owned at this point by the caller.";
1542 }
1543
1544 virtual void EmitWarnings(BugReporter& BR);
1545 };
1546
1547 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1548 public:
1549 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1550
1551 virtual const char* getName() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001552 return "Core Foundation: Memory Leak";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001553 }
1554
1555 virtual const char* getDescription() const {
Ted Kremeneka8503952008-04-18 04:55:01 +00001556 return "Object leaked.";
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001557 }
1558
1559 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001560 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001561 virtual bool isLeak() const { return true; }
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001562 };
1563
1564 //===---------===//
1565 // Bug Reports. //
1566 //===---------===//
1567
1568 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1569 SymbolID Sym;
1570 public:
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001571 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001572 : RangedBugReport(D, n), Sym(sym) {}
1573
1574 virtual ~CFRefReport() {}
1575
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001576 CFRefBug& getBugType() {
1577 return (CFRefBug&) RangedBugReport::getBugType();
1578 }
1579 const CFRefBug& getBugType() const {
1580 return (const CFRefBug&) RangedBugReport::getBugType();
1581 }
1582
1583 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1584 const SourceRange*& end) {
1585
Ted Kremenek198cae02008-05-02 20:53:50 +00001586 if (!getBugType().isLeak())
Ted Kremenek5c3407a2008-05-01 22:50:36 +00001587 RangedBugReport::getRanges(BR, beg, end);
1588 else {
1589 beg = 0;
1590 end = 0;
1591 }
1592 }
1593
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001594 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1595 ExplodedNode<ValueState>* N);
1596
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001597 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001598
1599 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1600 ExplodedNode<ValueState>* PrevN,
1601 ExplodedGraph<ValueState>& G,
1602 BugReporter& BR);
1603 };
1604
1605
1606} // end anonymous namespace
1607
1608void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001609 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001610 Eng.Register(new UseAfterRelease(*this));
1611 Eng.Register(new BadRelease(*this));
1612 Eng.Register(new Leak(*this));
1613}
1614
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001615
1616static const char* Msgs[] = {
1617 "Code is compiled in garbage collection only mode" // GC only
1618 " (the bug occurs with garbage collection enabled).",
1619
1620 "Code is compiled without garbage collection.", // No GC.
1621
1622 "Code is compiled for use with and without garbage collection (GC)."
1623 " The bug occurs with GC enabled.", // Hybrid, with GC.
1624
1625 "Code is compiled for use with and without garbage collection (GC)."
1626 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1627};
1628
1629std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1630 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1631
1632 switch (TF.getLangOptions().getGCMode()) {
1633 default:
1634 assert(false);
Ted Kremenekcb4709402008-05-01 04:02:04 +00001635
1636 case LangOptions::GCOnly:
1637 assert (TF.isGCEnabled());
1638 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001639
1640 case LangOptions::NonGC:
1641 assert (!TF.isGCEnabled());
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001642 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1643
1644 case LangOptions::HybridGC:
1645 if (TF.isGCEnabled())
1646 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1647 else
1648 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1649 }
1650}
1651
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001652PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1653 ExplodedNode<ValueState>* PrevN,
1654 ExplodedGraph<ValueState>& G,
1655 BugReporter& BR) {
1656
1657 // Check if the type state has changed.
1658
1659 ValueState* PrevSt = PrevN->getState();
1660 ValueState* CurrSt = N->getState();
1661
1662 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1663 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1664
Ted Kremeneka8503952008-04-18 04:55:01 +00001665 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1666 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001667
Ted Kremeneka8503952008-04-18 04:55:01 +00001668 if (!CurrT)
1669 return NULL;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001670
Ted Kremeneka8503952008-04-18 04:55:01 +00001671 const char* Msg = NULL;
1672 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenek9363fd92008-05-05 17:53:17 +00001673
Ted Kremeneka8503952008-04-18 04:55:01 +00001674 if (!PrevT) {
1675
Ted Kremenek9363fd92008-05-05 17:53:17 +00001676 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1677
1678 if (CurrV.isOwned()) {
1679
1680 if (isa<CallExpr>(S))
1681 Msg = "Function call returns an object with a +1 retain count"
1682 " (owning reference).";
1683 else {
1684 assert (isa<ObjCMessageExpr>(S));
1685 Msg = "Method returns an object with a +1 retain count"
1686 " (owning reference).";
1687 }
1688 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001689 else {
1690 assert (CurrV.isNotOwned());
Ted Kremenek9363fd92008-05-05 17:53:17 +00001691
1692 if (isa<CallExpr>(S))
1693 Msg = "Function call returns an object with a +0 retain count"
1694 " (non-owning reference).";
1695 else {
1696 assert (isa<ObjCMessageExpr>(S));
1697 Msg = "Method returns an object with a +0 retain count"
1698 " (non-owning reference).";
1699 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001700 }
Ted Kremenek9363fd92008-05-05 17:53:17 +00001701
Ted Kremeneka8503952008-04-18 04:55:01 +00001702 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1703 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1704
1705 if (Expr* Exp = dyn_cast<Expr>(S))
1706 P->addRange(Exp->getSourceRange());
1707
1708 return P;
1709 }
1710
1711 // Determine if the typestate has changed.
1712
1713 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1714
1715 if (PrevV == CurrV)
1716 return NULL;
1717
1718 // The typestate has changed.
1719
1720 std::ostringstream os;
1721
1722 switch (CurrV.getKind()) {
1723 case RefVal::Owned:
1724 case RefVal::NotOwned:
1725 assert (PrevV.getKind() == CurrV.getKind());
1726
1727 if (PrevV.getCount() > CurrV.getCount())
1728 os << "Reference count decremented.";
1729 else
1730 os << "Reference count incremented.";
1731
Ted Kremenek9363fd92008-05-05 17:53:17 +00001732 if (unsigned Count = GetCount(CurrV)) {
1733
1734 os << " Object has +" << Count;
Ted Kremenek752b5842008-04-18 05:32:44 +00001735
Ted Kremenek9363fd92008-05-05 17:53:17 +00001736 if (Count > 1)
1737 os << " retain counts.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001738 else
Ted Kremenek9363fd92008-05-05 17:53:17 +00001739 os << " retain count.";
Ted Kremenek752b5842008-04-18 05:32:44 +00001740 }
Ted Kremeneka8503952008-04-18 04:55:01 +00001741
1742 Msg = os.str().c_str();
1743
1744 break;
1745
1746 case RefVal::Released:
1747 Msg = "Object released.";
1748 break;
1749
1750 case RefVal::ReturnedOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001751 Msg = "Object returned to caller as owning reference (single retain count"
1752 " transferred to caller).";
Ted Kremeneka8503952008-04-18 04:55:01 +00001753 break;
1754
1755 case RefVal::ReturnedNotOwned:
Ted Kremenek9363fd92008-05-05 17:53:17 +00001756 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremeneka8503952008-04-18 04:55:01 +00001757 break;
1758
1759 default:
1760 return NULL;
1761 }
1762
1763 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1764 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1765 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1766
1767 // Add the range by scanning the children of the statement for any bindings
1768 // to Sym.
1769
1770 ValueStateManager& VSM = BR.getEngine().getStateManager();
1771
1772 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1773 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1774 RVal X = VSM.GetRVal(CurrSt, Exp);
1775
1776 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1777 if (SV->getSymbol() == Sym) {
1778 P->addRange(Exp->getSourceRange()); break;
1779 }
1780 }
1781
1782 return P;
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001783}
1784
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001785PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremenekea794e92008-05-05 18:50:19 +00001786 ExplodedNode<ValueState>* EndN) {
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001787
1788 if (!getBugType().isLeak())
Ted Kremenekea794e92008-05-05 18:50:19 +00001789 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001790
Ted Kremenek9363fd92008-05-05 17:53:17 +00001791 typedef CFRefCount::RefBindings RefBindings;
1792
1793 // Get the retain count.
1794 unsigned long RetCount = 0;
1795
1796 {
Ted Kremenekea794e92008-05-05 18:50:19 +00001797 ValueState* St = EndN->getState();
Ted Kremenek9363fd92008-05-05 17:53:17 +00001798 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1799 RefBindings::TreeTy* T = B.SlimFind(Sym);
1800 assert (T);
1801 RetCount = GetCount(T->getValue().second);
1802 }
1803
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001804 // We are a leak. Walk up the graph to get to the first node where the
1805 // symbol appeared.
1806
Ted Kremenekea794e92008-05-05 18:50:19 +00001807 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001808 ExplodedNode<ValueState>* Last = N;
Ted Kremenekea794e92008-05-05 18:50:19 +00001809
Ted Kremenek198cae02008-05-02 20:53:50 +00001810 // Find the first node that referred to the tracked symbol. We also
1811 // try and find the first VarDecl the value was stored to.
1812
1813 VarDecl* FirstDecl = 0;
Ted Kremenekea794e92008-05-05 18:50:19 +00001814
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001815 while (N) {
1816 ValueState* St = N->getState();
1817 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremenek198cae02008-05-02 20:53:50 +00001818 RefBindings::TreeTy* T = B.SlimFind(Sym);
1819
1820 if (!T)
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001821 break;
Ted Kremenek198cae02008-05-02 20:53:50 +00001822
1823 VarDecl* VD = 0;
1824
1825 // Determine if there is an LVal binding to the symbol.
1826 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1827 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1828 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1829 continue;
1830
1831 if (VD) { // Multiple decls map to this symbol.
1832 VD = 0;
1833 break;
1834 }
1835
1836 VD = I->first;
1837 }
1838
1839 if (VD) FirstDecl = VD;
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001840
1841 Last = N;
1842 N = N->pred_empty() ? NULL : *(N->pred_begin());
1843 }
1844
Ted Kremenekea794e92008-05-05 18:50:19 +00001845 // Get the allocate site.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001846
1847 assert (Last);
1848 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1849
Ted Kremenekea794e92008-05-05 18:50:19 +00001850 SourceManager& SMgr = BR.getContext().getSourceManager();
1851 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001852
Ted Kremenekea794e92008-05-05 18:50:19 +00001853 // Get the leak site. We may have multiple ExplodedNodes (one with the
1854 // leak) that occur on the same line number; if the node with the leak
1855 // has any immediate predecessor nodes with the same line number, find
1856 // any transitive-successors that have a different statement and use that
1857 // line number instead. This avoids emiting a diagnostic like:
1858 //
1859 // // 'y' is leaked.
1860 // int x = foo(y);
1861 //
1862 // instead we want:
1863 //
1864 // int x = foo(y);
1865 // // 'y' is leaked.
1866
1867 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
1868 assert (S);
1869 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
1870
1871 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
1872 // it occur on the same line?
1873
1874 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
1875 N = *(EndN->pred_begin());
1876
1877 do {
1878 ProgramPoint P = N->getLocation();
1879
1880 if (!isa<PostStmt>(P))
1881 break;
1882
1883 // Predecessor at same line?
1884
1885 Stmt* SPred = cast<PostStmt>(P).getStmt();
1886
1887 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine)
1888 break;
1889
1890 // The predecessor (where the object was not yet leaked) is a statement
1891 // on the same line. Get the first successor statement that appears
1892 // on a different line. For this operation, we can traverse the
1893 // non-trimmed graph.
1894
1895 N = getEndNode(); // This is the node where the leak occured in the
1896 // original graph.
1897
1898 while (!N->succ_empty()) {
1899
1900 N = *(N->succ_begin());
1901 ProgramPoint P = N->getLocation();
1902
1903 if (!isa<PostStmt>(P))
1904 continue;
1905
1906 Stmt* SSucc = cast<PostStmt>(P).getStmt();
1907
1908 if (SMgr.getLogicalLineNumber(SSucc->getLocStart()) != EndLine) {
1909 S = SSucc;
1910 break;
1911 }
1912 }
1913 }
1914 while (false);
1915
1916 // Construct the location.
1917
1918 FullSourceLoc L(S->getLocStart(), SMgr);
1919
1920 // Generate the diagnostic.
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001921 std::ostringstream os;
Ted Kremenek198cae02008-05-02 20:53:50 +00001922
Ted Kremenekea794e92008-05-05 18:50:19 +00001923 os << "Object allocated on line " << AllocLine;
Ted Kremenek198cae02008-05-02 20:53:50 +00001924
1925 if (FirstDecl)
1926 os << " and stored into '" << FirstDecl->getName() << '\'';
1927
Ted Kremenek9363fd92008-05-05 17:53:17 +00001928 os << " is no longer referenced after this point and has a retain count of +"
1929 << RetCount << " (object leaked).";
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001930
Ted Kremenekea794e92008-05-05 18:50:19 +00001931 return new PathDiagnosticPiece(L, os.str());
Ted Kremenekfe4d2312008-05-01 23:13:35 +00001932}
1933
Ted Kremenek7d421f32008-04-09 23:49:11 +00001934void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001935
Ted Kremenek7d421f32008-04-09 23:49:11 +00001936 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
1937 E = TF.use_after_end(); I != E; ++I) {
1938
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001939 CFRefReport report(*this, I->first, I->second.second);
1940 report.addRange(I->second.first->getSourceRange());
Ted Kremenek270ab7d2008-04-18 01:56:37 +00001941 BR.EmitWarning(report);
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001942 }
Ted Kremenek7d421f32008-04-09 23:49:11 +00001943}
1944
1945void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001946
Ted Kremenek7d421f32008-04-09 23:49:11 +00001947 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
1948 E = TF.bad_release_end(); I != E; ++I) {
1949
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001950 CFRefReport report(*this, I->first, I->second.second);
1951 report.addRange(I->second.first->getSourceRange());
1952 BR.EmitWarning(report);
Ted Kremenek7d421f32008-04-09 23:49:11 +00001953 }
1954}
Ted Kremenek10fe66d2008-04-09 01:10:13 +00001955
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001956void Leak::EmitWarnings(BugReporter& BR) {
1957
1958 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
1959 E = TF.leaks_end(); I != E; ++I) {
1960
Ted Kremenek2be7ddb2008-04-18 03:39:05 +00001961 std::vector<SymbolID>& SymV = *(I->second);
1962 unsigned n = SymV.size();
1963
1964 for (unsigned i = 0; i < n; ++i) {
1965 CFRefReport report(*this, I->first, SymV[i]);
1966 BR.EmitWarning(report);
1967 }
Ted Kremenek7f3f41a2008-04-17 23:43:50 +00001968 }
1969}
1970
Ted Kremenekeef8f1e2008-04-18 19:23:43 +00001971void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
1972 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
1973 I!=E; ++I)
1974 Nodes.push_back(I->first);
1975}
1976
Ted Kremeneka7338b42008-03-11 06:39:11 +00001977//===----------------------------------------------------------------------===//
Ted Kremenekb1983ba2008-04-10 22:16:52 +00001978// Transfer function creation for external clients.
Ted Kremeneka7338b42008-03-11 06:39:11 +00001979//===----------------------------------------------------------------------===//
1980
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001981GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek2f62f352008-05-02 18:01:49 +00001982 bool StandardWarnings,
Ted Kremenekfe30beb2008-04-30 23:47:44 +00001983 const LangOptions& lopts) {
Ted Kremenek2f62f352008-05-02 18:01:49 +00001984 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremeneka4c74292008-04-10 22:58:08 +00001985}