blob: 25d1ed0299f5b9e0cd7e3f9baeba6cec54b6a2d9 [file] [log] [blame]
Chris Lattnerbda0b622008-03-15 23:59:48 +00001// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek2fff37e2008-03-06 00:08:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines the methods for CFRefCount, which implements
Ted Kremenek2fff37e2008-03-06 00:08:09 +000011// a reference count checker for Core Foundation (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000015#include "GRSimpleVals.h"
Ted Kremenek072192b2008-04-30 23:47:44 +000016#include "clang/Basic/LangOptions.h"
Ted Kremenekc9fa2f72008-05-01 23:13:35 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek2fff37e2008-03-06 00:08:09 +000020#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000021#include "clang/Analysis/PathDiagnostic.h"
22#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/ADT/ImmutableMap.h"
Ted Kremenekfa34b332008-04-09 01:10:13 +000026#include "llvm/Support/Compiler.h"
Ted Kremenekf3948042008-03-11 19:44:10 +000027#include <ostream>
Ted Kremenek2cf943a2008-04-18 04:55:01 +000028#include <sstream>
Ted Kremenek2fff37e2008-03-06 00:08:09 +000029
30using namespace clang;
31
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000032//===----------------------------------------------------------------------===//
Ted Kremenek4fd88972008-04-17 18:12:53 +000033// Utility functions.
34//===----------------------------------------------------------------------===//
35
Ted Kremenekb83e02e2008-05-01 18:31:44 +000036static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
Ted Kremenek4fd88972008-04-17 18:12:53 +000037 IdentifierInfo* II = &Ctx.Idents.get(name);
38 return Ctx.Selectors.getSelector(0, &II);
39}
40
Ted Kremenek9c32d082008-05-06 00:30:21 +000041static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
42 IdentifierInfo* II = &Ctx.Idents.get(name);
43 return Ctx.Selectors.getSelector(1, &II);
44}
45
Ted Kremenek4fd88972008-04-17 18:12:53 +000046//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +000047// Symbolic Evaluation of Reference Counting Logic
48//===----------------------------------------------------------------------===//
49
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000050namespace {
Ted Kremenek14993892008-05-06 02:41:27 +000051 enum ArgEffect { IncRef, DecRef, DoNothing, StopTracking };
Ted Kremenek891d5cc2008-04-24 17:22:33 +000052 typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000053}
Ted Kremenek2fff37e2008-03-06 00:08:09 +000054
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000055namespace llvm {
56 template <> struct FoldingSetTrait<ArgEffects> {
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000057 static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
Ted Kremenek891d5cc2008-04-24 17:22:33 +000058 for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
59 ID.AddInteger(I->first);
60 ID.AddInteger((unsigned) I->second);
61 }
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +000062 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000063 };
64} // end llvm namespace
65
66namespace {
Ted Kremenek2fff37e2008-03-06 00:08:09 +000067
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000068class RetEffect {
69public:
Ted Kremenek940b1d82008-04-10 23:44:06 +000070 enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
Ted Kremenekd3dbcf42008-05-05 22:11:16 +000071 NotOwnedSymbol = 0x3, ReceiverAlias=0x4 };
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000072
73private:
74 unsigned Data;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +000075 RetEffect(Kind k, unsigned D) { Data = (D << 3) | (unsigned) k; }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000076
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000077public:
78
Ted Kremenekd3dbcf42008-05-05 22:11:16 +000079 Kind getKind() const { return (Kind) (Data & 0x7); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000080
81 unsigned getValue() const {
82 assert(getKind() == Alias);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +000083 return Data >> 3;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000084 }
Ted Kremeneke7bd9c22008-04-11 22:25:11 +000085
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000086 static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000087
Ted Kremenekd3dbcf42008-05-05 22:11:16 +000088 static RetEffect MakeReceiverAlias() { return RetEffect(ReceiverAlias, 0); }
89
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000090 static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
Ted Kremenek2fff37e2008-03-06 00:08:09 +000091
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000092 static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
93
Ted Kremenek940b1d82008-04-10 23:44:06 +000094 static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
95
Ted Kremenek6b3a0f72008-03-11 06:39:11 +000096 operator Kind() const { return getKind(); }
97
98 void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
99};
100
101
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000102class RetainSummary : public llvm::FoldingSetNode {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000103 ArgEffects* Args;
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000104 ArgEffect Receiver;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000105 RetEffect Ret;
106public:
107
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000108 RetainSummary(ArgEffects* A, RetEffect R, ArgEffect ReceiverEff = DoNothing)
109 : Args(A), Receiver(ReceiverEff), Ret(R) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000110
111 unsigned getNumArgs() const { return Args->size(); }
112
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000113 ArgEffect getArg(unsigned idx) const {
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000114 if (!Args)
115 return DoNothing;
116
117 // If Args is present, it is likely to contain only 1 element.
118 // Just do a linear search. Do it from the back because functions with
119 // large numbers of arguments will be tail heavy with respect to which
120 // argument they actually modify with respect to the reference count.
121
122 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
123 I!=E; ++I) {
124
125 if (idx > I->first)
126 return DoNothing;
127
128 if (idx == I->first)
129 return I->second;
130 }
131
132 return DoNothing;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000133 }
134
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000135 RetEffect getRetEffect() const {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000136 return Ret;
137 }
138
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000139 ArgEffect getReceiverEffect() const {
140 return Receiver;
141 }
142
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000143 typedef ArgEffects::const_iterator arg_iterator;
144
145 arg_iterator begin_args() const { return Args->begin(); }
146 arg_iterator end_args() const { return Args->end(); }
147
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000148 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A,
149 RetEffect RetEff, ArgEffect ReceiverEff) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000150 ID.AddPointer(A);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000151 ID.Add(RetEff);
152 ID.AddInteger((unsigned) ReceiverEff);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000153 }
154
155 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000156 Profile(ID, Args, Ret, Receiver);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000157 }
158};
159
160
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000161class RetainSummaryManager {
162
163 //==-----------------------------------------------------------------==//
164 // Typedefs.
165 //==-----------------------------------------------------------------==//
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000166
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000167 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
168 ArgEffectsSetTy;
169
170 typedef llvm::FoldingSet<RetainSummary>
171 SummarySetTy;
172
173 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
174 FuncSummariesTy;
175
176 typedef llvm::DenseMap<Selector, RetainSummary*>
Ted Kremenek9c32d082008-05-06 00:30:21 +0000177 ObjCMethSummariesTy;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000178
179 //==-----------------------------------------------------------------==//
180 // Data.
181 //==-----------------------------------------------------------------==//
182
183 // Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek377e2302008-04-29 05:33:51 +0000184 ASTContext& Ctx;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000185
186 // GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek377e2302008-04-29 05:33:51 +0000187 const bool GCEnabled;
188
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000189 // SummarySet - A FoldingSet of uniqued summaries.
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000190 SummarySetTy SummarySet;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000191
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000192 // FuncSummaries - A map from FunctionDecls to summaries.
193 FuncSummariesTy FuncSummaries;
194
Ted Kremenek9c32d082008-05-06 00:30:21 +0000195 // ObjCInstMethSummaries - A map from selectors (for instance methods)
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000196 // to summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000197 ObjCMethSummariesTy ObjCInstMethSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000198
Ted Kremenek9c32d082008-05-06 00:30:21 +0000199 // ObjCMethSummaries - A map from selectors to summaries.
200 ObjCMethSummariesTy ObjCMethSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000201
202 // ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
203 ArgEffectsSetTy ArgEffectsSet;
204
205 // BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
206 // and all other data used by the checker.
207 llvm::BumpPtrAllocator BPAlloc;
208
209 // ScratchArgs - A holding buffer for construct ArgEffects.
210 ArgEffects ScratchArgs;
211
212 //==-----------------------------------------------------------------==//
213 // Methods.
214 //==-----------------------------------------------------------------==//
215
216 // getArgEffects - Returns a persistent ArgEffects object based on the
217 // data in ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000218 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000219
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000220 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000221 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek377e2302008-04-29 05:33:51 +0000222
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000223 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
224 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000225
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000226 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
227 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000228
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000229 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
230 ArgEffect ReceiverEff = DoNothing);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000231
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000232 RetainSummary* getPersistentSummary(RetEffect RE,
233 ArgEffect ReceiverEff = DoNothing) {
234 return getPersistentSummary(getArgEffects(), RE, ReceiverEff);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000235 }
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000236
Ted Kremenekb3095252008-05-06 04:20:12 +0000237
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000238 RetainSummary* getInitMethodSummary(Selector S);
239
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000240 void InitializeInstMethSummaries();
241 void InitializeMethSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000242
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000243public:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000244
245 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek9c32d082008-05-06 00:30:21 +0000246 : Ctx(ctx), GCEnabled(gcenabled) {
247
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000248 InitializeInstMethSummaries();
249 InitializeMethSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000250 }
Ted Kremenek377e2302008-04-29 05:33:51 +0000251
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000252 ~RetainSummaryManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000253
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000254 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
255
Ted Kremenekb3095252008-05-06 04:20:12 +0000256 RetainSummary* getMethodSummary(Selector S);
257 RetainSummary* getInstanceMethodSummary(IdentifierInfo* ClsName, Selector S);
258
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000259 bool isGCEnabled() const { return GCEnabled; }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000260};
261
262} // end anonymous namespace
263
264//===----------------------------------------------------------------------===//
265// Implementation of checker data structures.
266//===----------------------------------------------------------------------===//
267
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000268RetainSummaryManager::~RetainSummaryManager() {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000269
270 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
271 // mitigating the need to do explicit cleanup of the
272 // Argument-Effect summaries.
273
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000274 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
275 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000276 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000277}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000278
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000279ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000280
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000281 if (ScratchArgs.empty())
282 return NULL;
283
284 // Compute a profile for a non-empty ScratchArgs.
285
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000286 llvm::FoldingSetNodeID profile;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000287
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000288 profile.Add(ScratchArgs);
289 void* InsertPos;
290
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000291 // Look up the uniqued copy, or create a new one.
292
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000293 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000294 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000295
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000296 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000297 ScratchArgs.clear();
298 return &E->getValue();
299 }
300
301 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
302 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
303
304 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000305 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000306
307 ScratchArgs.clear();
308 return &E->getValue();
309}
310
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000311RetainSummary*
312RetainSummaryManager::getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
313 ArgEffect ReceiverEff) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000314
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000315 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000316 llvm::FoldingSetNodeID profile;
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000317 RetainSummary::Profile(profile, AE, RetEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000318
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000319 // Look up the uniqued summary, or create one if it doesn't exist.
320 void* InsertPos;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000321 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000322
323 if (Summ)
324 return Summ;
325
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000326 // Create the summary and return it.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000327 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000328 new (Summ) RetainSummary(AE, RetEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000329 SummarySet.InsertNode(Summ, InsertPos);
330
331 return Summ;
332}
333
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000334//===----------------------------------------------------------------------===//
335// Summary creation for functions (largely uses of Core Foundation).
336//===----------------------------------------------------------------------===//
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000337
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000338RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000339 ASTContext& Ctx) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000340
341 SourceLocation Loc = FD->getLocation();
342
343 if (!Loc.isFileID())
344 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000345
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000346 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000347 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000348
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000349 if (I != FuncSummaries.end())
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000350 return I->second;
351
352 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000353 const char* FName = FD->getIdentifier()->getName();
354
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000355 RetainSummary *S = 0;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000356
357 if (FName[0] == 'C' && FName[1] == 'F')
358 S = getCFSummary(FD, FName);
359 else if (FName[0] == 'N' && FName[1] == 'S')
360 S = getNSSummary(FD, FName);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000361
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000362 FuncSummaries[FD] = S;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000363 return S;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000364}
365
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000366RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000367 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000368 FName += 2;
369
370 if (strcmp(FName, "MakeCollectable") == 0)
371 return getUnarySummary(FD, cfmakecollectable);
372
373 return 0;
374}
375
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000376RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000377 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000378
379 FName += 2;
380
381 if (strcmp(FName, "Retain") == 0)
382 return getUnarySummary(FD, cfretain);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000383
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000384 if (strcmp(FName, "Release") == 0)
385 return getUnarySummary(FD, cfrelease);
386
387 if (strcmp(FName, "MakeCollectable") == 0)
388 return getUnarySummary(FD, cfmakecollectable);
389
390 if (strstr(FName, "Create") || strstr(FName, "Copy"))
391 return getCFSummaryCreateRule(FD);
392
393 if (strstr(FName, "Get"))
394 return getCFSummaryGetRule(FD);
395
396 return 0;
397}
398
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000399RetainSummary*
400RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000401
402 FunctionTypeProto* FT =
403 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
404
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000405 if (FT) {
406
407 if (FT->getNumArgs() != 1)
408 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000409
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000410 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
411
412 if (!ArgT)
413 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000414
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000415 if (!ArgT->isPointerType())
416 return NULL;
417 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000418
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000419 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000420
Ted Kremenek377e2302008-04-29 05:33:51 +0000421 switch (func) {
422 case cfretain: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000423 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek9c32d082008-05-06 00:30:21 +0000424 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek377e2302008-04-29 05:33:51 +0000425 }
426
427 case cfrelease: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000428 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek9c32d082008-05-06 00:30:21 +0000429 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek377e2302008-04-29 05:33:51 +0000430 }
431
432 case cfmakecollectable: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000433 if (GCEnabled)
434 ScratchArgs.push_back(std::make_pair(0, DecRef));
435
Ted Kremenek9c32d082008-05-06 00:30:21 +0000436 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek377e2302008-04-29 05:33:51 +0000437 }
438
439 default:
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000440 assert (false && "Not a supported unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000441 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000442}
443
444static bool isCFRefType(QualType T) {
445
446 if (!T->isPointerType())
447 return false;
448
449 // Check the typedef for the name "CF" and the substring "Ref".
450
451 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
452
453 if (!TD)
454 return false;
455
456 const char* TDName = TD->getDecl()->getIdentifier()->getName();
457 assert (TDName);
458
459 if (TDName[0] != 'C' || TDName[1] != 'F')
460 return false;
461
462 if (strstr(TDName, "Ref") == 0)
463 return false;
464
465 return true;
466}
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000467
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000468RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000469
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000470 FunctionTypeProto* FT =
471 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
472
473 if (FT && !isCFRefType(FT->getResultType()))
474 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000475
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000476 // FIXME: Add special-cases for functions that retain/release. For now
477 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000478
479 assert (ScratchArgs.empty());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000480 return getPersistentSummary(RetEffect::MakeOwned());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000481}
482
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000483RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000484
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000485 FunctionTypeProto* FT =
486 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000487
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000488 if (FT) {
489 QualType RetTy = FT->getResultType();
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000490
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000491 // FIXME: For now we assume that all pointer types returned are referenced
492 // counted. Since this is the "Get" rule, we assume non-ownership, which
493 // works fine for things that are not reference counted. We do this because
494 // some generic data structures return "void*". We need something better
495 // in the future.
496
497 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
498 return 0;
499 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000500
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000501 // FIXME: Add special-cases for functions that retain/release. For now
502 // just handle the default case.
503
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000504 assert (ScratchArgs.empty());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000505 return getPersistentSummary(RetEffect::MakeNotOwned());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000506}
507
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000508//===----------------------------------------------------------------------===//
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000509// Summary creation for Selectors.
510//===----------------------------------------------------------------------===//
511
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000512RetainSummary* RetainSummaryManager::getInitMethodSummary(Selector S) {
513 assert(ScratchArgs.empty());
514
515 RetainSummary* Summ =
Ted Kremenek9c32d082008-05-06 00:30:21 +0000516 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000517
Ted Kremenek9c32d082008-05-06 00:30:21 +0000518 ObjCMethSummaries[S] = Summ;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000519 return Summ;
520}
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000521
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000522RetainSummary* RetainSummaryManager::getMethodSummary(Selector S) {
523
524 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000525 ObjCMethSummariesTy::iterator I = ObjCMethSummaries.find(S);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000526
Ted Kremenek9c32d082008-05-06 00:30:21 +0000527 if (I != ObjCMethSummaries.end())
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000528 return I->second;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000529
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000530 // "initXXX": pass-through for receiver.
531
532 const char* s = S.getIdentifierInfoForSlot(0)->getName();
533
534 if (s[0] == 'i' && s[10] == 'n' && s[2] == 'i' && s[3] == 't')
535 return getInitMethodSummary(S);
536
537 return 0;
538}
539
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000540void RetainSummaryManager::InitializeInstMethSummaries() {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000541
542 assert (ScratchArgs.empty());
543
544 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
545 RetainSummary* Summ = getPersistentSummary(E);
546
547 // Create the "alloc" selector.
548 ObjCInstMethSummaries[ GetNullarySelector("alloc", Ctx) ] = Summ;
549
550 // Create the "new" selector.
551 ObjCInstMethSummaries[ GetNullarySelector("new", Ctx) ] = Summ;
552
553 // Create the "allocWithZone:" selector.
554 ObjCInstMethSummaries[ GetUnarySelector("allocWithZone", Ctx) ] = Summ;
555
556 // Create the "copyWithZone:" selector.
557 ObjCInstMethSummaries[ GetUnarySelector("copyWithZone", Ctx) ] = Summ;
558
559 // Create the "mutableCopyWithZone:" selector.
560 ObjCInstMethSummaries[ GetUnarySelector("mutableCopyWithZone", Ctx) ] = Summ;
561}
562
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000563void RetainSummaryManager::InitializeMethSummaries() {
564
565 assert (ScratchArgs.empty());
566
567 // Create the "init" selector.
568 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeReceiverAlias());
569 ObjCMethSummaries[ GetNullarySelector("init", Ctx) ] = Summ;
570
571 // Create the "copy" selector.
572 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
573 Summ = getPersistentSummary(E);
574 ObjCMethSummaries[ GetNullarySelector("copy", Ctx) ] = Summ;
575
576 // Create the "mutableCopy" selector.
577 ObjCMethSummaries[ GetNullarySelector("mutableCopy", Ctx) ] = Summ;
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000578
579 // Create the "retain" selector.
580 E = RetEffect::MakeReceiverAlias();
581 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
582 ObjCMethSummaries[ GetNullarySelector("retain", Ctx) ] = Summ;
583
584 // Create the "release" selector.
585 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
586 ObjCMethSummaries[ GetNullarySelector("release", Ctx) ] = Summ;
587
588 // Create the "autorelease" selector.
Ted Kremenek14993892008-05-06 02:41:27 +0000589 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : StopTracking);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000590 ObjCMethSummaries[ GetNullarySelector("autorelease", Ctx) ] = Summ;
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000591}
592
Ted Kremenek9c32d082008-05-06 00:30:21 +0000593
Ted Kremenekb3095252008-05-06 04:20:12 +0000594RetainSummary*
595RetainSummaryManager::getInstanceMethodSummary(IdentifierInfo* ClsName,
596 Selector S) {
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000597
598 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000599 ObjCMethSummariesTy::iterator I = ObjCInstMethSummaries.find(S);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000600
Ted Kremenek9c32d082008-05-06 00:30:21 +0000601 if (I != ObjCInstMethSummaries.end())
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000602 return I->second;
Ted Kremenekb3095252008-05-06 04:20:12 +0000603
604 // Don't track anything if using GC.
605 if (isGCEnabled())
606 return 0;
607
608 // Heuristic: XXXXwithYYYY, where XXX is the class name with the "NS"
609 // stripped off is usually an allocation.
610
611 const char* cls = ClsName->getName();
612 const char* s = S.getIdentifierInfoForSlot(0)->getName();
613
614 if (cls[0] == 'N' && cls[1] == 'S')
615 cls += 2;
616
617 if (cls[0] == '\0' || s[0] == '\0' || tolower(cls[0]) != s[0])
618 return 0;
619
620 ++cls;
621 ++s;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000622
Ted Kremenekb3095252008-05-06 04:20:12 +0000623 // Now look at the rest of the characters.
624 unsigned len = strlen(cls);
625 assert (len);
626
627 // Prefix matches?
628 if (strncmp(cls, s, len))
629 return 0;
630
631 s += len;
632
633 // If 's' is the same as clsName, or 's' has "With" after the class name,
634 // treat it as an allocator.
635 do {
636
637 if (s[0] == '\0')
638 break;
639
640 if (s[0]=='\0' || s[0]!='W' || s[1]!='i' || s[2]!='t' || s[3]!='h')
641 break;
642
643 return 0;
644
645 } while(0);
646
647 // Generate the summary.
648
649 assert (ScratchArgs.empty());
650 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeOwned());
651 ObjCInstMethSummaries[S] = Summ;
652 return Summ;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000653}
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000654
655//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000656// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000657//===----------------------------------------------------------------------===//
658
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000659namespace {
660
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000661class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000662public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000663
Ted Kremenek4fd88972008-04-17 18:12:53 +0000664 enum Kind {
665 Owned = 0, // Owning reference.
666 NotOwned, // Reference is not owned by still valid (not freed).
667 Released, // Object has been released.
668 ReturnedOwned, // Returned object passes ownership to caller.
669 ReturnedNotOwned, // Return object does not pass ownership to caller.
670 ErrorUseAfterRelease, // Object used after released.
671 ErrorReleaseNotOwned, // Release of an object that was not owned.
672 ErrorLeak // A memory leak due to excessive reference counts.
673 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000674
Ted Kremenek4fd88972008-04-17 18:12:53 +0000675private:
676
677 Kind kind;
678 unsigned Cnt;
679
680 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
681
682 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000683
684public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000685
Ted Kremenek4fd88972008-04-17 18:12:53 +0000686 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000687
Ted Kremenek4fd88972008-04-17 18:12:53 +0000688 unsigned getCount() const { return Cnt; }
689
690 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000691
Ted Kremenek73c750b2008-03-11 18:14:09 +0000692 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
693
Ted Kremenekdb863712008-04-16 22:32:20 +0000694 static bool isLeak(Kind k) { return k == ErrorLeak; }
695
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000696 bool isOwned() const {
697 return getKind() == Owned;
698 }
699
Ted Kremenekdb863712008-04-16 22:32:20 +0000700 bool isNotOwned() const {
701 return getKind() == NotOwned;
702 }
703
Ted Kremenek4fd88972008-04-17 18:12:53 +0000704 bool isReturnedOwned() const {
705 return getKind() == ReturnedOwned;
706 }
707
708 bool isReturnedNotOwned() const {
709 return getKind() == ReturnedNotOwned;
710 }
711
712 bool isNonLeakError() const {
713 Kind k = getKind();
714 return isError(k) && !isLeak(k);
715 }
716
717 // State creation: normal state.
718
Ted Kremenek61b9f872008-04-10 23:09:18 +0000719 static RefVal makeOwned(unsigned Count = 0) {
720 return RefVal(Owned, Count);
721 }
722
723 static RefVal makeNotOwned(unsigned Count = 0) {
724 return RefVal(NotOwned, Count);
725 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000726
727 static RefVal makeReturnedOwned(unsigned Count) {
728 return RefVal(ReturnedOwned, Count);
729 }
730
731 static RefVal makeReturnedNotOwned() {
732 return RefVal(ReturnedNotOwned);
733 }
734
735 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000736
Ted Kremenekce48e002008-05-05 17:53:17 +0000737 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000738 static RefVal makeReleased() { return RefVal(Released); }
739 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
740 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000741
742 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000743
Ted Kremenek4fd88972008-04-17 18:12:53 +0000744 bool operator==(const RefVal& X) const {
745 return kind == X.kind && Cnt == X.Cnt;
746 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000747
Ted Kremenek4fd88972008-04-17 18:12:53 +0000748 void Profile(llvm::FoldingSetNodeID& ID) const {
749 ID.AddInteger((unsigned) kind);
750 ID.AddInteger(Cnt);
751 }
752
Ted Kremenekf3948042008-03-11 19:44:10 +0000753 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000754};
Ted Kremenekf3948042008-03-11 19:44:10 +0000755
756void RefVal::print(std::ostream& Out) const {
757 switch (getKind()) {
758 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000759 case Owned: {
760 Out << "Owned";
761 unsigned cnt = getCount();
762 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000763 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000764 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000765
Ted Kremenek61b9f872008-04-10 23:09:18 +0000766 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000767 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000768 unsigned cnt = getCount();
769 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000770 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000771 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000772
Ted Kremenek4fd88972008-04-17 18:12:53 +0000773 case ReturnedOwned: {
774 Out << "ReturnedOwned";
775 unsigned cnt = getCount();
776 if (cnt) Out << " (+ " << cnt << ")";
777 break;
778 }
779
780 case ReturnedNotOwned: {
781 Out << "ReturnedNotOwned";
782 unsigned cnt = getCount();
783 if (cnt) Out << " (+ " << cnt << ")";
784 break;
785 }
786
Ted Kremenekf3948042008-03-11 19:44:10 +0000787 case Released:
788 Out << "Released";
789 break;
790
Ted Kremenekdb863712008-04-16 22:32:20 +0000791 case ErrorLeak:
792 Out << "Leaked";
793 break;
794
Ted Kremenekf3948042008-03-11 19:44:10 +0000795 case ErrorUseAfterRelease:
796 Out << "Use-After-Release [ERROR]";
797 break;
798
799 case ErrorReleaseNotOwned:
800 Out << "Release of Not-Owned [ERROR]";
801 break;
802 }
803}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000804
Ted Kremenekce48e002008-05-05 17:53:17 +0000805static inline unsigned GetCount(RefVal V) {
806 switch (V.getKind()) {
807 default:
808 return V.getCount();
809
810 case RefVal::Owned:
811 return V.getCount()+1;
812 }
813}
814
Ted Kremenek13922612008-04-16 20:40:59 +0000815//===----------------------------------------------------------------------===//
816// Transfer functions.
817//===----------------------------------------------------------------------===//
818
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000819class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000820public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000821 // Type definitions.
822
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000823 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000824 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000825
Ted Kremenek8dd56462008-04-18 03:39:05 +0000826 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
827 ReleasesNotOwnedTy;
828
829 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
830
831 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000832 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000833
Ted Kremenekf3948042008-03-11 19:44:10 +0000834 class BindingsPrinter : public ValueState::CheckerStatePrinter {
835 public:
836 virtual void PrintCheckerState(std::ostream& Out, void* State,
837 const char* nl, const char* sep);
838 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000839
840private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000841 // Instance variables.
842
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000843 RetainSummaryManager Summaries;
844 const bool EmitStandardWarnings;
845 const LangOptions& LOpts;
846 RefBFactoryTy RefBFactory;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000847
Ted Kremenek73c750b2008-03-11 18:14:09 +0000848 UseAfterReleasesTy UseAfterReleases;
849 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000850 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000851
Ted Kremenekf3948042008-03-11 19:44:10 +0000852 BindingsPrinter Printer;
853
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000854 Selector RetainSelector;
855 Selector ReleaseSelector;
Ted Kremenek5934cee2008-05-01 02:18:37 +0000856 Selector AutoreleaseSelector;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000857
Ted Kremenek8dd56462008-04-18 03:39:05 +0000858public:
859
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000860 static RefBindings GetRefBindings(ValueState& StImpl) {
861 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
862 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000863
Ted Kremenek8dd56462008-04-18 03:39:05 +0000864private:
865
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000866 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
867 StImpl.CheckerState = B.getRoot();
868 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000869
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000870 RefBindings Remove(RefBindings B, SymbolID sym) {
871 return RefBFactory.Remove(B, sym);
872 }
873
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000874 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000875 RefVal::Kind& hasErr);
876
Ted Kremenekdb863712008-04-16 22:32:20 +0000877 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
878 GRStmtNodeBuilder<ValueState>& Builder,
879 Expr* NodeExpr, Expr* ErrorExpr,
880 ExplodedNode<ValueState>* Pred,
881 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000882 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000883
884 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
885 SymbolID sid, RefVal V, bool& hasLeak);
886
887 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
888 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000889
890public:
Ted Kremenek13922612008-04-16 20:40:59 +0000891
Ted Kremenek9f741612008-05-02 18:01:49 +0000892 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
893 const LangOptions& lopts)
Ted Kremenek377e2302008-04-29 05:33:51 +0000894 : Summaries(Ctx, gcenabled),
Ted Kremenek9f741612008-05-02 18:01:49 +0000895 EmitStandardWarnings(StandardWarnings),
Ted Kremenek072192b2008-04-30 23:47:44 +0000896 LOpts(lopts),
Ted Kremenekb83e02e2008-05-01 18:31:44 +0000897 RetainSelector(GetNullarySelector("retain", Ctx)),
898 ReleaseSelector(GetNullarySelector("release", Ctx)),
899 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000900
Ted Kremenek8dd56462008-04-18 03:39:05 +0000901 virtual ~CFRefCount() {
902 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
903 delete I->second;
904 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000905
906 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000907
908 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
909 return &Printer;
910 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000911
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000912 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenek072192b2008-04-30 23:47:44 +0000913 const LangOptions& getLangOptions() const { return LOpts; }
914
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000915 // Calls.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000916
917 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
918 GRExprEngine& Eng,
919 GRStmtNodeBuilder<ValueState>& Builder,
920 Expr* Ex,
921 Expr* Receiver,
922 RetainSummary* Summ,
923 Expr** arg_beg, Expr** arg_end,
924 ExplodedNode<ValueState>* Pred);
925
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000926 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +0000927 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000928 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +0000929 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000930 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +0000931
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000932
Ted Kremenek85348202008-04-15 23:44:31 +0000933 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
934 GRExprEngine& Engine,
935 GRStmtNodeBuilder<ValueState>& Builder,
936 ObjCMessageExpr* ME,
937 ExplodedNode<ValueState>* Pred);
938
939 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
940 GRExprEngine& Engine,
941 GRStmtNodeBuilder<ValueState>& Builder,
942 ObjCMessageExpr* ME,
943 ExplodedNode<ValueState>* Pred);
944
Ted Kremenek13922612008-04-16 20:40:59 +0000945 // Stores.
946
947 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
948 GRExprEngine& Engine,
949 GRStmtNodeBuilder<ValueState>& Builder,
950 Expr* E, ExplodedNode<ValueState>* Pred,
951 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000952 // End-of-path.
953
954 virtual void EvalEndPath(GRExprEngine& Engine,
955 GREndPathNodeBuilder<ValueState>& Builder);
956
Ted Kremenek652adc62008-04-24 23:57:27 +0000957 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
958 GRExprEngine& Engine,
959 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +0000960 ExplodedNode<ValueState>* Pred,
961 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +0000962 ValueState* St,
963 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +0000964 // Return statements.
965
966 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
967 GRExprEngine& Engine,
968 GRStmtNodeBuilder<ValueState>& Builder,
969 ReturnStmt* S,
970 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +0000971
972 // Assumptions.
973
974 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
975 RVal Cond, bool Assumption, bool& isFeasible);
976
Ted Kremenekfa34b332008-04-09 01:10:13 +0000977 // Error iterators.
978
979 typedef UseAfterReleasesTy::iterator use_after_iterator;
980 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +0000981 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +0000982
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000983 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
984 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +0000985
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000986 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
987 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +0000988
989 leaks_iterator leaks_begin() { return Leaks.begin(); }
990 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000991};
992
993} // end anonymous namespace
994
Ted Kremenek8dd56462008-04-18 03:39:05 +0000995
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000996
997
Ted Kremenekf3948042008-03-11 19:44:10 +0000998void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
999 void* State, const char* nl,
1000 const char* sep) {
1001 RefBindings B((RefBindings::TreeTy*) State);
1002
1003 if (State)
1004 Out << sep << nl;
1005
1006 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1007 Out << (*I).first << " : ";
1008 (*I).second.print(Out);
1009 Out << nl;
1010 }
1011}
1012
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001013static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001014 return Summ ? Summ->getArg(idx) : DoNothing;
1015}
1016
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001017static inline RetEffect GetRetEffect(RetainSummary* Summ) {
1018 return Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001019}
1020
Ted Kremenek14993892008-05-06 02:41:27 +00001021static inline ArgEffect GetReceiverE(RetainSummary* Summ) {
1022 return Summ ? Summ->getReceiverEffect() : DoNothing;
1023}
1024
Ted Kremenekdb863712008-04-16 22:32:20 +00001025void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
1026 GRStmtNodeBuilder<ValueState>& Builder,
1027 Expr* NodeExpr, Expr* ErrorExpr,
1028 ExplodedNode<ValueState>* Pred,
1029 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001030 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001031 Builder.BuildSinks = true;
1032 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
1033
1034 if (!N) return;
1035
1036 switch (hasErr) {
1037 default: assert(false);
1038 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001039 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001040 break;
1041
1042 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001043 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001044 break;
1045 }
1046}
1047
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001048void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1049 GRExprEngine& Eng,
1050 GRStmtNodeBuilder<ValueState>& Builder,
1051 Expr* Ex,
1052 Expr* Receiver,
1053 RetainSummary* Summ,
1054 Expr** arg_beg, Expr** arg_end,
1055 ExplodedNode<ValueState>* Pred) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001056
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001057
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001058 // Get the state.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001059 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001060 ValueState* St = Builder.GetState(Pred);
1061
Ted Kremenek14993892008-05-06 02:41:27 +00001062
1063 // Evaluate the effect of the arguments.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001064
1065 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001066 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001067 unsigned idx = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001068 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001069 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001070
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001071 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001072
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001073 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001074
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001075 if (isa<lval::SymbolVal>(V)) {
1076 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001077 RefBindings B = GetRefBindings(StVals);
1078
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001079 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001080 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001081 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001082
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001083 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001084 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001085 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001086 break;
1087 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001088 }
Ted Kremenekb8873552008-04-11 20:51:02 +00001089 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001090 else if (isa<LVal>(V)) {
1091 // Nuke all arguments passed by reference.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001092 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +00001093 }
Ted Kremeneka5488462008-04-22 21:39:21 +00001094 else if (isa<nonlval::LValAsInteger>(V))
1095 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001096 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001097
Ted Kremenek14993892008-05-06 02:41:27 +00001098 // Evaluate the effect on the message receiver.
1099
1100 if (!ErrorExpr && Receiver) {
1101 RVal V = StateMgr.GetRVal(St, Receiver);
1102
1103 if (isa<lval::SymbolVal>(V)) {
1104 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1105 RefBindings B = GetRefBindings(StVals);
1106
1107 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
1108 B = Update(B, Sym, T->getValue().second, GetReceiverE(Summ), hasErr);
1109 SetRefBindings(StVals, B);
1110
1111 if (hasErr) {
1112 ErrorExpr = Receiver;
1113 ErrorSym = T->getValue().first;
1114 }
1115 }
1116 }
1117 }
1118
1119 // Get the persistent state.
1120
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001121 St = StateMgr.getPersistentState(StVals);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001122
Ted Kremenek14993892008-05-06 02:41:27 +00001123 // Process any errors.
1124
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001125 if (hasErr) {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001126 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001127 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001128 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001129 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001130
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001131 // Finally, consult the summary for the return value.
1132
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001133 RetEffect RE = GetRetEffect(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001134
1135 switch (RE.getKind()) {
1136 default:
1137 assert (false && "Unhandled RetEffect."); break;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001138
Ted Kremenek940b1d82008-04-10 23:44:06 +00001139 case RetEffect::NoRet:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001140
Ted Kremenekf9561e52008-04-11 20:23:24 +00001141 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +00001142 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1143 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001144
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001145 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001146 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001147 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001148
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001149 RVal X = Ex->getType()->isPointerType()
1150 ? cast<RVal>(lval::SymbolVal(Sym))
1151 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenekf9561e52008-04-11 20:23:24 +00001152
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001153 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001154 }
1155
Ted Kremenek940b1d82008-04-10 23:44:06 +00001156 break;
1157
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001158 case RetEffect::Alias: {
1159 unsigned idx = RE.getValue();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001160 assert ((arg_end - arg_beg) >= 0);
1161 assert (idx < (unsigned) (arg_end - arg_beg));
1162 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1163 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001164 break;
1165 }
1166
Ted Kremenek14993892008-05-06 02:41:27 +00001167 case RetEffect::ReceiverAlias: {
1168 assert (Receiver);
1169 RVal V = StateMgr.GetRVal(St, Receiver);
1170 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
1171 break;
1172 }
1173
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001174 case RetEffect::OwnedSymbol: {
1175 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001176 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1177
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001178 ValueState StImpl = *St;
1179 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001180 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001181
1182 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001183 Ex, lval::SymbolVal(Sym),
1184 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001185
1186 break;
1187 }
1188
1189 case RetEffect::NotOwnedSymbol: {
1190 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001191 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001192
1193 ValueState StImpl = *St;
1194 RefBindings B = GetRefBindings(StImpl);
1195 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1196
1197 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001198 Ex, lval::SymbolVal(Sym),
1199 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001200
1201 break;
1202 }
1203 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001204
1205 Builder.MakeNode(Dst, Ex, Pred, St);
1206}
1207
1208
1209void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1210 GRExprEngine& Eng,
1211 GRStmtNodeBuilder<ValueState>& Builder,
1212 CallExpr* CE, RVal L,
1213 ExplodedNode<ValueState>* Pred) {
1214
1215
1216 RetainSummary* Summ = NULL;
1217
1218 // Get the summary.
1219
1220 if (isa<lval::FuncVal>(L)) {
1221 lval::FuncVal FV = cast<lval::FuncVal>(L);
1222 FunctionDecl* FD = FV.getDecl();
1223 Summ = Summaries.getSummary(FD, Eng.getContext());
1224 }
1225
1226 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1227 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001228}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001229
Ted Kremenek85348202008-04-15 23:44:31 +00001230
1231void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1232 GRExprEngine& Eng,
1233 GRStmtNodeBuilder<ValueState>& Builder,
1234 ObjCMessageExpr* ME,
1235 ExplodedNode<ValueState>* Pred) {
1236
Ted Kremenekb3095252008-05-06 04:20:12 +00001237 RetainSummary* Summ;
Ted Kremenek9040c652008-05-01 21:31:50 +00001238
Ted Kremenekb3095252008-05-06 04:20:12 +00001239 if (ME->getReceiver())
1240 Summ = Summaries.getMethodSummary(ME->getSelector());
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001241 else
Ted Kremenekb3095252008-05-06 04:20:12 +00001242 Summ = Summaries.getInstanceMethodSummary(ME->getClassName(),
1243 ME->getSelector());
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001244
Ted Kremenekb3095252008-05-06 04:20:12 +00001245 EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
1246 ME->arg_begin(), ME->arg_end(), Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001247}
Ted Kremenekb3095252008-05-06 04:20:12 +00001248
Ted Kremenek13922612008-04-16 20:40:59 +00001249// Stores.
1250
1251void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1252 GRExprEngine& Eng,
1253 GRStmtNodeBuilder<ValueState>& Builder,
1254 Expr* E, ExplodedNode<ValueState>* Pred,
1255 ValueState* St, RVal TargetLV, RVal Val) {
1256
1257 // Check if we have a binding for "Val" and if we are storing it to something
1258 // we don't understand or otherwise the value "escapes" the function.
1259
1260 if (!isa<lval::SymbolVal>(Val))
1261 return;
1262
1263 // Are we storing to something that causes the value to "escape"?
1264
1265 bool escapes = false;
1266
1267 if (!isa<lval::DeclVal>(TargetLV))
1268 escapes = true;
1269 else
1270 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1271
1272 if (!escapes)
1273 return;
1274
1275 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1276 RefBindings B = GetRefBindings(*St);
1277 RefBindings::TreeTy* T = B.SlimFind(Sym);
1278
1279 if (!T)
1280 return;
1281
Ted Kremenekdb863712008-04-16 22:32:20 +00001282 // Nuke the binding.
1283 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001284
1285 // Hand of the remaining logic to the parent implementation.
1286 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1287}
1288
Ted Kremenekdb863712008-04-16 22:32:20 +00001289
1290ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1291 SymbolID sid) {
1292 ValueState StImpl = *St;
1293 RefBindings B = GetRefBindings(StImpl);
1294 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1295 return VMgr.getPersistentState(StImpl);
1296}
1297
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001298// End-of-path.
1299
Ted Kremenekdb863712008-04-16 22:32:20 +00001300ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1301 ValueState* St, SymbolID sid,
1302 RefVal V, bool& hasLeak) {
1303
Ted Kremenek4fd88972008-04-17 18:12:53 +00001304 hasLeak = V.isOwned() ||
1305 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001306
1307 if (!hasLeak)
1308 return NukeBinding(VMgr, St, sid);
1309
1310 RefBindings B = GetRefBindings(*St);
1311 ValueState StImpl = *St;
Ted Kremenekce48e002008-05-05 17:53:17 +00001312
1313 StImpl.CheckerState =
1314 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1315
Ted Kremenekdb863712008-04-16 22:32:20 +00001316 return VMgr.getPersistentState(StImpl);
1317}
1318
1319void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001320 GREndPathNodeBuilder<ValueState>& Builder) {
1321
Ted Kremenekdb863712008-04-16 22:32:20 +00001322 ValueState* St = Builder.getState();
1323 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001324
Ted Kremenekdb863712008-04-16 22:32:20 +00001325 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001326
Ted Kremenekdb863712008-04-16 22:32:20 +00001327 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1328 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001329
Ted Kremenekdb863712008-04-16 22:32:20 +00001330 St = HandleSymbolDeath(Eng.getStateManager(), St,
1331 (*I).first, (*I).second, hasLeak);
1332
1333 if (hasLeak) Leaked.push_back((*I).first);
1334 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001335
1336 if (Leaked.empty())
1337 return;
1338
Ted Kremenek8dd56462008-04-18 03:39:05 +00001339 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001340
Ted Kremenek652adc62008-04-24 23:57:27 +00001341 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001342 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001343
Ted Kremenek8dd56462008-04-18 03:39:05 +00001344 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1345 assert (!LeaksAtNode);
1346 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001347
1348 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1349 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001350 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001351}
1352
Ted Kremenek652adc62008-04-24 23:57:27 +00001353// Dead symbols.
1354
1355void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1356 GRExprEngine& Eng,
1357 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001358 ExplodedNode<ValueState>* Pred,
1359 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001360 ValueState* St,
1361 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001362
Ted Kremenek652adc62008-04-24 23:57:27 +00001363 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1364
1365 RefBindings B = GetRefBindings(*St);
1366 llvm::SmallVector<SymbolID, 10> Leaked;
1367
1368 for (ValueStateManager::DeadSymbolsTy::const_iterator
1369 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1370
1371 RefBindings::TreeTy* T = B.SlimFind(*I);
1372
1373 if (!T)
1374 continue;
1375
1376 bool hasLeak = false;
1377
1378 St = HandleSymbolDeath(Eng.getStateManager(), St,
1379 *I, T->getValue().second, hasLeak);
1380
1381 if (hasLeak) Leaked.push_back(*I);
1382 }
1383
1384 if (Leaked.empty())
1385 return;
1386
1387 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1388
1389 if (!N)
1390 return;
1391
1392 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1393 assert (!LeaksAtNode);
1394 LeaksAtNode = new std::vector<SymbolID>();
1395
1396 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1397 E = Leaked.end(); I != E; ++I)
1398 (*LeaksAtNode).push_back(*I);
1399}
1400
Ted Kremenek4fd88972008-04-17 18:12:53 +00001401 // Return statements.
1402
1403void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1404 GRExprEngine& Eng,
1405 GRStmtNodeBuilder<ValueState>& Builder,
1406 ReturnStmt* S,
1407 ExplodedNode<ValueState>* Pred) {
1408
1409 Expr* RetE = S->getRetValue();
1410 if (!RetE) return;
1411
1412 ValueStateManager& StateMgr = Eng.getStateManager();
1413 ValueState* St = Builder.GetState(Pred);
1414 RVal V = StateMgr.GetRVal(St, RetE);
1415
1416 if (!isa<lval::SymbolVal>(V))
1417 return;
1418
1419 // Get the reference count binding (if any).
1420 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1421 RefBindings B = GetRefBindings(*St);
1422 RefBindings::TreeTy* T = B.SlimFind(Sym);
1423
1424 if (!T)
1425 return;
1426
1427 // Change the reference count.
1428
1429 RefVal X = T->getValue().second;
1430
1431 switch (X.getKind()) {
1432
1433 case RefVal::Owned: {
1434 unsigned cnt = X.getCount();
1435 X = RefVal::makeReturnedOwned(cnt);
1436 break;
1437 }
1438
1439 case RefVal::NotOwned: {
1440 unsigned cnt = X.getCount();
1441 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1442 : RefVal::makeReturnedNotOwned();
1443 break;
1444 }
1445
1446 default:
Ted Kremenek4fd88972008-04-17 18:12:53 +00001447 return;
1448 }
1449
1450 // Update the binding.
1451
1452 ValueState StImpl = *St;
1453 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1454 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1455}
1456
Ted Kremenekcb612922008-04-18 19:23:43 +00001457// Assumptions.
1458
1459ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1460 RVal Cond, bool Assumption,
1461 bool& isFeasible) {
1462
1463 // FIXME: We may add to the interface of EvalAssume the list of symbols
1464 // whose assumptions have changed. For now we just iterate through the
1465 // bindings and check if any of the tracked symbols are NULL. This isn't
1466 // too bad since the number of symbols we will track in practice are
1467 // probably small and EvalAssume is only called at branches and a few
1468 // other places.
1469
1470 RefBindings B = GetRefBindings(*St);
1471
1472 if (B.isEmpty())
1473 return St;
1474
1475 bool changed = false;
1476
1477 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1478
1479 // Check if the symbol is null (or equal to any constant).
1480 // If this is the case, stop tracking the symbol.
1481
1482 if (St->getSymVal(I.getKey())) {
1483 changed = true;
1484 B = RefBFactory.Remove(B, I.getKey());
1485 }
1486 }
1487
1488 if (!changed)
1489 return St;
1490
1491 ValueState StImpl = *St;
1492 StImpl.CheckerState = B.getRoot();
1493 return Eng.getStateManager().getPersistentState(StImpl);
1494}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001495
1496CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001497 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001498 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001499
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001500 // FIXME: This dispatch can potentially be sped up by unifiying it into
1501 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001502
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001503 switch (E) {
1504 default:
1505 assert (false && "Unhandled CFRef transition.");
1506
1507 case DoNothing:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001508 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001509 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001510 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001511 break;
1512 }
1513
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001514 return B;
1515
Ted Kremenek14993892008-05-06 02:41:27 +00001516 case StopTracking:
1517 return RefBFactory.Remove(B, sym);
1518
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001519 case IncRef:
1520 switch (V.getKind()) {
1521 default:
1522 assert(false);
1523
1524 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001525 V = RefVal::makeOwned(V.getCount()+1);
1526 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001527
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001528 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001529 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001530 break;
1531
1532 case RefVal::Released:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001533 if (isGCEnabled())
Ted Kremenek65c91652008-04-29 05:44:10 +00001534 V = RefVal::makeOwned();
1535 else {
1536 V = RefVal::makeUseAfterRelease();
1537 hasErr = V.getKind();
1538 }
1539
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001540 break;
1541 }
1542
Ted Kremenek940b1d82008-04-10 23:44:06 +00001543 break;
1544
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001545 case DecRef:
1546 switch (V.getKind()) {
1547 default:
1548 assert (false);
1549
1550 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001551 unsigned Count = V.getCount();
1552 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001553 break;
1554 }
1555
Ted Kremenek61b9f872008-04-10 23:09:18 +00001556 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001557 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001558
Ted Kremenek4fd88972008-04-17 18:12:53 +00001559 if (Count > 0)
1560 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001561 else {
1562 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001563 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001564 }
1565
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001566 break;
1567 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001568
1569 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001570 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001571 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001572 break;
1573 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001574
1575 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001576 }
1577
1578 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001579}
1580
Ted Kremenekfa34b332008-04-09 01:10:13 +00001581
1582//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001583// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001584//===----------------------------------------------------------------------===//
1585
Ted Kremenek8dd56462008-04-18 03:39:05 +00001586namespace {
1587
1588 //===-------------===//
1589 // Bug Descriptions. //
1590 //===-------------===//
1591
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001592 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001593 protected:
1594 CFRefCount& TF;
1595
1596 public:
1597 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenek072192b2008-04-30 23:47:44 +00001598
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001599 CFRefCount& getTF() { return TF; }
Ted Kremenek789deac2008-05-05 23:16:31 +00001600 const CFRefCount& getTF() const { return TF; }
1601
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001602 virtual bool isLeak() const { return false; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001603 };
1604
1605 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1606 public:
1607 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1608
1609 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001610 return "Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001611 }
1612 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001613 return "Reference-counted object is used"
1614 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001615 }
1616
1617 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001618 };
1619
1620 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1621 public:
1622 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1623
1624 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001625 return "Bad Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001626 }
1627 virtual const char* getDescription() const {
1628 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001629 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001630 "The object is not owned at this point by the caller.";
1631 }
1632
1633 virtual void EmitWarnings(BugReporter& BR);
1634 };
1635
1636 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1637 public:
1638 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1639
1640 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001641 return getTF().isGCEnabled() ? "Memory Leak (GC)" : "Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001642 }
1643
1644 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001645 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001646 }
1647
1648 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001649 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001650 virtual bool isLeak() const { return true; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001651 };
1652
1653 //===---------===//
1654 // Bug Reports. //
1655 //===---------===//
1656
1657 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1658 SymbolID Sym;
1659 public:
Ted Kremenek072192b2008-04-30 23:47:44 +00001660 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001661 : RangedBugReport(D, n), Sym(sym) {}
1662
1663 virtual ~CFRefReport() {}
1664
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001665 CFRefBug& getBugType() {
1666 return (CFRefBug&) RangedBugReport::getBugType();
1667 }
1668 const CFRefBug& getBugType() const {
1669 return (const CFRefBug&) RangedBugReport::getBugType();
1670 }
1671
1672 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1673 const SourceRange*& end) {
1674
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001675 if (!getBugType().isLeak())
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001676 RangedBugReport::getRanges(BR, beg, end);
1677 else {
1678 beg = 0;
1679 end = 0;
1680 }
1681 }
1682
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001683 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1684 ExplodedNode<ValueState>* N);
1685
Ted Kremenek072192b2008-04-30 23:47:44 +00001686 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek8dd56462008-04-18 03:39:05 +00001687
1688 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1689 ExplodedNode<ValueState>* PrevN,
1690 ExplodedGraph<ValueState>& G,
1691 BugReporter& BR);
1692 };
1693
1694
1695} // end anonymous namespace
1696
1697void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek9f741612008-05-02 18:01:49 +00001698 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001699 Eng.Register(new UseAfterRelease(*this));
1700 Eng.Register(new BadRelease(*this));
1701 Eng.Register(new Leak(*this));
1702}
1703
Ted Kremenek072192b2008-04-30 23:47:44 +00001704
1705static const char* Msgs[] = {
1706 "Code is compiled in garbage collection only mode" // GC only
1707 " (the bug occurs with garbage collection enabled).",
1708
1709 "Code is compiled without garbage collection.", // No GC.
1710
1711 "Code is compiled for use with and without garbage collection (GC)."
1712 " The bug occurs with GC enabled.", // Hybrid, with GC.
1713
1714 "Code is compiled for use with and without garbage collection (GC)."
1715 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1716};
1717
1718std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1719 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1720
1721 switch (TF.getLangOptions().getGCMode()) {
1722 default:
1723 assert(false);
Ted Kremenek31593ac2008-05-01 04:02:04 +00001724
1725 case LangOptions::GCOnly:
1726 assert (TF.isGCEnabled());
1727 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenek072192b2008-04-30 23:47:44 +00001728
1729 case LangOptions::NonGC:
1730 assert (!TF.isGCEnabled());
Ted Kremenek072192b2008-04-30 23:47:44 +00001731 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1732
1733 case LangOptions::HybridGC:
1734 if (TF.isGCEnabled())
1735 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1736 else
1737 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1738 }
1739}
1740
Ted Kremenek8dd56462008-04-18 03:39:05 +00001741PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1742 ExplodedNode<ValueState>* PrevN,
1743 ExplodedGraph<ValueState>& G,
1744 BugReporter& BR) {
1745
1746 // Check if the type state has changed.
1747
1748 ValueState* PrevSt = PrevN->getState();
1749 ValueState* CurrSt = N->getState();
1750
1751 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1752 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1753
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001754 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1755 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001756
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001757 if (!CurrT)
1758 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001759
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001760 const char* Msg = NULL;
1761 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenekce48e002008-05-05 17:53:17 +00001762
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001763 if (!PrevT) {
1764
Ted Kremenekce48e002008-05-05 17:53:17 +00001765 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1766
1767 if (CurrV.isOwned()) {
1768
1769 if (isa<CallExpr>(S))
1770 Msg = "Function call returns an object with a +1 retain count"
1771 " (owning reference).";
1772 else {
1773 assert (isa<ObjCMessageExpr>(S));
1774 Msg = "Method returns an object with a +1 retain count"
1775 " (owning reference).";
1776 }
1777 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001778 else {
1779 assert (CurrV.isNotOwned());
Ted Kremenekce48e002008-05-05 17:53:17 +00001780
1781 if (isa<CallExpr>(S))
1782 Msg = "Function call returns an object with a +0 retain count"
1783 " (non-owning reference).";
1784 else {
1785 assert (isa<ObjCMessageExpr>(S));
1786 Msg = "Method returns an object with a +0 retain count"
1787 " (non-owning reference).";
1788 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001789 }
Ted Kremenekce48e002008-05-05 17:53:17 +00001790
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001791 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1792 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1793
1794 if (Expr* Exp = dyn_cast<Expr>(S))
1795 P->addRange(Exp->getSourceRange());
1796
1797 return P;
1798 }
1799
1800 // Determine if the typestate has changed.
1801
1802 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1803
1804 if (PrevV == CurrV)
1805 return NULL;
1806
1807 // The typestate has changed.
1808
1809 std::ostringstream os;
1810
1811 switch (CurrV.getKind()) {
1812 case RefVal::Owned:
1813 case RefVal::NotOwned:
1814 assert (PrevV.getKind() == CurrV.getKind());
1815
1816 if (PrevV.getCount() > CurrV.getCount())
1817 os << "Reference count decremented.";
1818 else
1819 os << "Reference count incremented.";
1820
Ted Kremenekce48e002008-05-05 17:53:17 +00001821 if (unsigned Count = GetCount(CurrV)) {
1822
1823 os << " Object has +" << Count;
Ted Kremenek79c140b2008-04-18 05:32:44 +00001824
Ted Kremenekce48e002008-05-05 17:53:17 +00001825 if (Count > 1)
1826 os << " retain counts.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00001827 else
Ted Kremenekce48e002008-05-05 17:53:17 +00001828 os << " retain count.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00001829 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001830
1831 Msg = os.str().c_str();
1832
1833 break;
1834
1835 case RefVal::Released:
1836 Msg = "Object released.";
1837 break;
1838
1839 case RefVal::ReturnedOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00001840 Msg = "Object returned to caller as owning reference (single retain count"
1841 " transferred to caller).";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001842 break;
1843
1844 case RefVal::ReturnedNotOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00001845 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001846 break;
1847
1848 default:
1849 return NULL;
1850 }
1851
1852 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1853 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1854 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1855
1856 // Add the range by scanning the children of the statement for any bindings
1857 // to Sym.
1858
1859 ValueStateManager& VSM = BR.getEngine().getStateManager();
1860
1861 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1862 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1863 RVal X = VSM.GetRVal(CurrSt, Exp);
1864
1865 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1866 if (SV->getSymbol() == Sym) {
1867 P->addRange(Exp->getSourceRange()); break;
1868 }
1869 }
1870
1871 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001872}
1873
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001874PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremeneke28565b2008-05-05 18:50:19 +00001875 ExplodedNode<ValueState>* EndN) {
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001876
1877 if (!getBugType().isLeak())
Ted Kremeneke28565b2008-05-05 18:50:19 +00001878 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001879
Ted Kremenekce48e002008-05-05 17:53:17 +00001880 typedef CFRefCount::RefBindings RefBindings;
1881
1882 // Get the retain count.
1883 unsigned long RetCount = 0;
1884
1885 {
Ted Kremeneke28565b2008-05-05 18:50:19 +00001886 ValueState* St = EndN->getState();
Ted Kremenekce48e002008-05-05 17:53:17 +00001887 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1888 RefBindings::TreeTy* T = B.SlimFind(Sym);
1889 assert (T);
1890 RetCount = GetCount(T->getValue().second);
1891 }
1892
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001893 // We are a leak. Walk up the graph to get to the first node where the
1894 // symbol appeared.
1895
Ted Kremeneke28565b2008-05-05 18:50:19 +00001896 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001897 ExplodedNode<ValueState>* Last = N;
Ted Kremeneke28565b2008-05-05 18:50:19 +00001898
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001899 // Find the first node that referred to the tracked symbol. We also
1900 // try and find the first VarDecl the value was stored to.
1901
1902 VarDecl* FirstDecl = 0;
Ted Kremeneke28565b2008-05-05 18:50:19 +00001903
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001904 while (N) {
1905 ValueState* St = N->getState();
1906 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001907 RefBindings::TreeTy* T = B.SlimFind(Sym);
1908
1909 if (!T)
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001910 break;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001911
1912 VarDecl* VD = 0;
1913
1914 // Determine if there is an LVal binding to the symbol.
1915 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
1916 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
1917 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
1918 continue;
1919
1920 if (VD) { // Multiple decls map to this symbol.
1921 VD = 0;
1922 break;
1923 }
1924
1925 VD = I->first;
1926 }
1927
1928 if (VD) FirstDecl = VD;
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001929
1930 Last = N;
1931 N = N->pred_empty() ? NULL : *(N->pred_begin());
1932 }
1933
Ted Kremeneke28565b2008-05-05 18:50:19 +00001934 // Get the allocate site.
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001935
1936 assert (Last);
1937 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
1938
Ted Kremeneke28565b2008-05-05 18:50:19 +00001939 SourceManager& SMgr = BR.getContext().getSourceManager();
1940 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001941
Ted Kremeneke28565b2008-05-05 18:50:19 +00001942 // Get the leak site. We may have multiple ExplodedNodes (one with the
1943 // leak) that occur on the same line number; if the node with the leak
1944 // has any immediate predecessor nodes with the same line number, find
1945 // any transitive-successors that have a different statement and use that
1946 // line number instead. This avoids emiting a diagnostic like:
1947 //
1948 // // 'y' is leaked.
1949 // int x = foo(y);
1950 //
1951 // instead we want:
1952 //
1953 // int x = foo(y);
1954 // // 'y' is leaked.
1955
1956 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
1957 assert (S);
1958 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
1959
1960 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
1961 // it occur on the same line?
1962
1963 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
1964 N = *(EndN->pred_begin());
1965
1966 do {
1967 ProgramPoint P = N->getLocation();
1968
1969 if (!isa<PostStmt>(P))
1970 break;
1971
1972 // Predecessor at same line?
1973
1974 Stmt* SPred = cast<PostStmt>(P).getStmt();
1975
1976 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine)
1977 break;
1978
1979 // The predecessor (where the object was not yet leaked) is a statement
1980 // on the same line. Get the first successor statement that appears
1981 // on a different line. For this operation, we can traverse the
1982 // non-trimmed graph.
1983
1984 N = getEndNode(); // This is the node where the leak occured in the
1985 // original graph.
1986
1987 while (!N->succ_empty()) {
1988
1989 N = *(N->succ_begin());
1990 ProgramPoint P = N->getLocation();
1991
1992 if (!isa<PostStmt>(P))
1993 continue;
1994
1995 Stmt* SSucc = cast<PostStmt>(P).getStmt();
1996
1997 if (SMgr.getLogicalLineNumber(SSucc->getLocStart()) != EndLine) {
1998 S = SSucc;
1999 break;
2000 }
2001 }
2002 }
2003 while (false);
2004
2005 // Construct the location.
2006
2007 FullSourceLoc L(S->getLocStart(), SMgr);
2008
2009 // Generate the diagnostic.
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002010 std::ostringstream os;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002011
Ted Kremeneke28565b2008-05-05 18:50:19 +00002012 os << "Object allocated on line " << AllocLine;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002013
2014 if (FirstDecl)
2015 os << " and stored into '" << FirstDecl->getName() << '\'';
2016
Ted Kremenekce48e002008-05-05 17:53:17 +00002017 os << " is no longer referenced after this point and has a retain count of +"
2018 << RetCount << " (object leaked).";
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002019
Ted Kremeneke28565b2008-05-05 18:50:19 +00002020 return new PathDiagnosticPiece(L, os.str());
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002021}
2022
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002023void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002024
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002025 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2026 E = TF.use_after_end(); I != E; ++I) {
2027
Ted Kremenek8dd56462008-04-18 03:39:05 +00002028 CFRefReport report(*this, I->first, I->second.second);
2029 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00002030 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00002031 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002032}
2033
2034void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002035
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002036 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2037 E = TF.bad_release_end(); I != E; ++I) {
2038
Ted Kremenek8dd56462008-04-18 03:39:05 +00002039 CFRefReport report(*this, I->first, I->second.second);
2040 report.addRange(I->second.first->getSourceRange());
2041 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002042 }
2043}
Ted Kremenekfa34b332008-04-09 01:10:13 +00002044
Ted Kremenek989d5192008-04-17 23:43:50 +00002045void Leak::EmitWarnings(BugReporter& BR) {
2046
2047 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2048 E = TF.leaks_end(); I != E; ++I) {
2049
Ted Kremenek8dd56462008-04-18 03:39:05 +00002050 std::vector<SymbolID>& SymV = *(I->second);
2051 unsigned n = SymV.size();
2052
2053 for (unsigned i = 0; i < n; ++i) {
2054 CFRefReport report(*this, I->first, SymV[i]);
2055 BR.EmitWarning(report);
2056 }
Ted Kremenek989d5192008-04-17 23:43:50 +00002057 }
2058}
2059
Ted Kremenekcb612922008-04-18 19:23:43 +00002060void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2061 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2062 I!=E; ++I)
2063 Nodes.push_back(I->first);
2064}
2065
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002066//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00002067// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002068//===----------------------------------------------------------------------===//
2069
Ted Kremenek072192b2008-04-30 23:47:44 +00002070GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek9f741612008-05-02 18:01:49 +00002071 bool StandardWarnings,
Ted Kremenek072192b2008-04-30 23:47:44 +00002072 const LangOptions& lopts) {
Ted Kremenek9f741612008-05-02 18:01:49 +00002073 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00002074}