blob: 72c5e0ab603f0590193b4a1cb8b7cca2fbf78183 [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 Kremenek1bffd742008-05-06 15:44:25 +0000103 /// Args - an ordered vector of (index, ArgEffect) pairs, where index
104 /// specifies the argument (starting from 0). This can be sparsely
105 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000106 ArgEffects* Args;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000107
108 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
109 /// do not have an entry in Args.
110 ArgEffect DefaultArgEffect;
111
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000112 ArgEffect Receiver;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000113 RetEffect Ret;
114public:
115
Ted Kremenek1bffd742008-05-06 15:44:25 +0000116 RetainSummary(ArgEffects* A, RetEffect R, ArgEffect defaultEff,
117 ArgEffect ReceiverEff)
118 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000119
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000120 ArgEffect getArg(unsigned idx) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000121
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000122 if (!Args)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000123 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000124
125 // If Args is present, it is likely to contain only 1 element.
126 // Just do a linear search. Do it from the back because functions with
127 // large numbers of arguments will be tail heavy with respect to which
128 // argument they actually modify with respect to the reference count.
129
130 for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
131 I!=E; ++I) {
132
133 if (idx > I->first)
Ted Kremenek1bffd742008-05-06 15:44:25 +0000134 return DefaultArgEffect;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000135
136 if (idx == I->first)
137 return I->second;
138 }
139
Ted Kremenek1bffd742008-05-06 15:44:25 +0000140 return DefaultArgEffect;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000141 }
142
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000143 RetEffect getRetEffect() const {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000144 return Ret;
145 }
146
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000147 ArgEffect getReceiverEffect() const {
148 return Receiver;
149 }
150
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000151 typedef ArgEffects::const_iterator arg_iterator;
152
153 arg_iterator begin_args() const { return Args->begin(); }
154 arg_iterator end_args() const { return Args->end(); }
155
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000156 static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000157 RetEffect RetEff, ArgEffect DefaultEff,
158 ArgEffect ReceiverEff) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000159 ID.AddPointer(A);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000160 ID.Add(RetEff);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000161 ID.AddInteger((unsigned) DefaultEff);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000162 ID.AddInteger((unsigned) ReceiverEff);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000163 }
164
165 void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek1bffd742008-05-06 15:44:25 +0000166 Profile(ID, Args, Ret, DefaultArgEffect, Receiver);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000167 }
168};
169
170
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000171class RetainSummaryManager {
172
173 //==-----------------------------------------------------------------==//
174 // Typedefs.
175 //==-----------------------------------------------------------------==//
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000176
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000177 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
178 ArgEffectsSetTy;
179
180 typedef llvm::FoldingSet<RetainSummary>
181 SummarySetTy;
182
183 typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
184 FuncSummariesTy;
185
186 typedef llvm::DenseMap<Selector, RetainSummary*>
Ted Kremenek9c32d082008-05-06 00:30:21 +0000187 ObjCMethSummariesTy;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000188
189 //==-----------------------------------------------------------------==//
190 // Data.
191 //==-----------------------------------------------------------------==//
192
193 // Ctx - The ASTContext object for the analyzed ASTs.
Ted Kremenek377e2302008-04-29 05:33:51 +0000194 ASTContext& Ctx;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000195
196 // GCEnabled - Records whether or not the analyzed code runs in GC mode.
Ted Kremenek377e2302008-04-29 05:33:51 +0000197 const bool GCEnabled;
198
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000199 // SummarySet - A FoldingSet of uniqued summaries.
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +0000200 SummarySetTy SummarySet;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000201
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000202 // FuncSummaries - A map from FunctionDecls to summaries.
203 FuncSummariesTy FuncSummaries;
204
Ted Kremenek9c32d082008-05-06 00:30:21 +0000205 // ObjCInstMethSummaries - A map from selectors (for instance methods)
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000206 // to summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000207 ObjCMethSummariesTy ObjCInstMethSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000208
Ted Kremenek9c32d082008-05-06 00:30:21 +0000209 // ObjCMethSummaries - A map from selectors to summaries.
210 ObjCMethSummariesTy ObjCMethSummaries;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000211
212 // ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
213 ArgEffectsSetTy ArgEffectsSet;
214
215 // BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
216 // and all other data used by the checker.
217 llvm::BumpPtrAllocator BPAlloc;
218
219 // ScratchArgs - A holding buffer for construct ArgEffects.
220 ArgEffects ScratchArgs;
221
Ted Kremenek432af592008-05-06 18:11:36 +0000222 RetainSummary* StopSummary;
223
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000224 //==-----------------------------------------------------------------==//
225 // Methods.
226 //==-----------------------------------------------------------------==//
227
228 // getArgEffects - Returns a persistent ArgEffects object based on the
229 // data in ScratchArgs.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000230 ArgEffects* getArgEffects();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000231
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000232 enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000233 RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
Ted Kremenek377e2302008-04-29 05:33:51 +0000234
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000235 RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
236 RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000237
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000238 RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
239 RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000240
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000241 RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000242 ArgEffect ReceiverEff = DoNothing,
243 ArgEffect DefaultEff = DoNothing);
244
Ted Kremenek9c32d082008-05-06 00:30:21 +0000245
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000246 RetainSummary* getPersistentSummary(RetEffect RE,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000247 ArgEffect ReceiverEff = DoNothing,
248 ArgEffect DefaultEff = DoNothing) {
249 return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
Ted Kremenek9c32d082008-05-06 00:30:21 +0000250 }
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000251
Ted Kremenek432af592008-05-06 18:11:36 +0000252
253
Ted Kremenek1bffd742008-05-06 15:44:25 +0000254 RetainSummary* getPersistentStopSummary() {
Ted Kremenek432af592008-05-06 18:11:36 +0000255 if (StopSummary)
256 return StopSummary;
257
258 StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
259 StopTracking, StopTracking);
260
261 return StopSummary;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000262 }
Ted Kremenekb3095252008-05-06 04:20:12 +0000263
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000264 RetainSummary* getInitMethodSummary(Selector S);
265
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000266 void InitializeInstMethSummaries();
267 void InitializeMethSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000268
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000269public:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000270
271 RetainSummaryManager(ASTContext& ctx, bool gcenabled)
Ted Kremenek432af592008-05-06 18:11:36 +0000272 : Ctx(ctx), GCEnabled(gcenabled), StopSummary(0) {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000273
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000274 InitializeInstMethSummaries();
275 InitializeMethSummaries();
Ted Kremenek9c32d082008-05-06 00:30:21 +0000276 }
Ted Kremenek377e2302008-04-29 05:33:51 +0000277
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000278 ~RetainSummaryManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000279
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000280 RetainSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
281
Ted Kremenek1bffd742008-05-06 15:44:25 +0000282 RetainSummary* getMethodSummary(ObjCMessageExpr* ME);
Ted Kremenekb3095252008-05-06 04:20:12 +0000283 RetainSummary* getInstanceMethodSummary(IdentifierInfo* ClsName, Selector S);
284
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000285 bool isGCEnabled() const { return GCEnabled; }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000286};
287
288} // end anonymous namespace
289
290//===----------------------------------------------------------------------===//
291// Implementation of checker data structures.
292//===----------------------------------------------------------------------===//
293
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000294RetainSummaryManager::~RetainSummaryManager() {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000295
296 // FIXME: The ArgEffects could eventually be allocated from BPAlloc,
297 // mitigating the need to do explicit cleanup of the
298 // Argument-Effect summaries.
299
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000300 for (ArgEffectsSetTy::iterator I = ArgEffectsSet.begin(),
301 E = ArgEffectsSet.end(); I!=E; ++I)
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000302 I->getValue().~ArgEffects();
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000303}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000304
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000305ArgEffects* RetainSummaryManager::getArgEffects() {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000306
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000307 if (ScratchArgs.empty())
308 return NULL;
309
310 // Compute a profile for a non-empty ScratchArgs.
311
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000312 llvm::FoldingSetNodeID profile;
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000313
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000314 profile.Add(ScratchArgs);
315 void* InsertPos;
316
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000317 // Look up the uniqued copy, or create a new one.
318
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000319 llvm::FoldingSetNodeWrapper<ArgEffects>* E =
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000320 ArgEffectsSet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000321
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000322 if (E) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000323 ScratchArgs.clear();
324 return &E->getValue();
325 }
326
327 E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
328 BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
329
330 new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000331 ArgEffectsSet.InsertNode(E, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000332
333 ScratchArgs.clear();
334 return &E->getValue();
335}
336
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000337RetainSummary*
338RetainSummaryManager::getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
Ted Kremenek1bffd742008-05-06 15:44:25 +0000339 ArgEffect ReceiverEff,
340 ArgEffect DefaultEff) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000341
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000342 // Generate a profile for the summary.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000343 llvm::FoldingSetNodeID profile;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000344 RetainSummary::Profile(profile, AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000345
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000346 // Look up the uniqued summary, or create one if it doesn't exist.
347 void* InsertPos;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000348 RetainSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000349
350 if (Summ)
351 return Summ;
352
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000353 // Create the summary and return it.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000354 Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
Ted Kremenek1bffd742008-05-06 15:44:25 +0000355 new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000356 SummarySet.InsertNode(Summ, InsertPos);
357
358 return Summ;
359}
360
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000361//===----------------------------------------------------------------------===//
362// Summary creation for functions (largely uses of Core Foundation).
363//===----------------------------------------------------------------------===//
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000364
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000365RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000366 ASTContext& Ctx) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000367
368 SourceLocation Loc = FD->getLocation();
369
370 if (!Loc.isFileID())
371 return NULL;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000372
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000373 // Look up a summary in our cache of FunctionDecls -> Summaries.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000374 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000375
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000376 if (I != FuncSummaries.end())
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000377 return I->second;
378
379 // No summary. Generate one.
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000380 const char* FName = FD->getIdentifier()->getName();
381
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000382 RetainSummary *S = 0;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000383
384 if (FName[0] == 'C' && FName[1] == 'F')
385 S = getCFSummary(FD, FName);
386 else if (FName[0] == 'N' && FName[1] == 'S')
387 S = getNSSummary(FD, FName);
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000388
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000389 FuncSummaries[FD] = S;
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000390 return S;
Ted Kremenek2fff37e2008-03-06 00:08:09 +0000391}
392
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000393RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000394 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000395 FName += 2;
396
397 if (strcmp(FName, "MakeCollectable") == 0)
398 return getUnarySummary(FD, cfmakecollectable);
399
400 return 0;
401}
402
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000403RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000404 const char* FName) {
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000405
406 FName += 2;
407
408 if (strcmp(FName, "Retain") == 0)
409 return getUnarySummary(FD, cfretain);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000410
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000411 if (strcmp(FName, "Release") == 0)
412 return getUnarySummary(FD, cfrelease);
413
414 if (strcmp(FName, "MakeCollectable") == 0)
415 return getUnarySummary(FD, cfmakecollectable);
416
417 if (strstr(FName, "Create") || strstr(FName, "Copy"))
418 return getCFSummaryCreateRule(FD);
419
420 if (strstr(FName, "Get"))
421 return getCFSummaryGetRule(FD);
422
423 return 0;
424}
425
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000426RetainSummary*
427RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000428
429 FunctionTypeProto* FT =
430 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
431
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000432 if (FT) {
433
434 if (FT->getNumArgs() != 1)
435 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000436
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000437 TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
438
439 if (!ArgT)
440 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000441
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000442 if (!ArgT->isPointerType())
443 return NULL;
444 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000445
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000446 assert (ScratchArgs.empty());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000447
Ted Kremenek377e2302008-04-29 05:33:51 +0000448 switch (func) {
449 case cfretain: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000450 ScratchArgs.push_back(std::make_pair(0, IncRef));
Ted Kremenek9c32d082008-05-06 00:30:21 +0000451 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek377e2302008-04-29 05:33:51 +0000452 }
453
454 case cfrelease: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000455 ScratchArgs.push_back(std::make_pair(0, DecRef));
Ted Kremenek9c32d082008-05-06 00:30:21 +0000456 return getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek377e2302008-04-29 05:33:51 +0000457 }
458
459 case cfmakecollectable: {
Ted Kremenek377e2302008-04-29 05:33:51 +0000460 if (GCEnabled)
461 ScratchArgs.push_back(std::make_pair(0, DecRef));
462
Ted Kremenek9c32d082008-05-06 00:30:21 +0000463 return getPersistentSummary(RetEffect::MakeAlias(0));
Ted Kremenek377e2302008-04-29 05:33:51 +0000464 }
465
466 default:
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000467 assert (false && "Not a supported unary function.");
Ted Kremenek940b1d82008-04-10 23:44:06 +0000468 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000469}
470
471static bool isCFRefType(QualType T) {
472
473 if (!T->isPointerType())
474 return false;
475
476 // Check the typedef for the name "CF" and the substring "Ref".
477
478 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
479
480 if (!TD)
481 return false;
482
483 const char* TDName = TD->getDecl()->getIdentifier()->getName();
484 assert (TDName);
485
486 if (TDName[0] != 'C' || TDName[1] != 'F')
487 return false;
488
489 if (strstr(TDName, "Ref") == 0)
490 return false;
491
492 return true;
493}
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000494
Ted Kremenek1bffd742008-05-06 15:44:25 +0000495static bool isNSType(QualType T) {
496
497 if (!T->isPointerType())
498 return false;
499
500 // Check the typedef for the name "CF" and the substring "Ref".
501
502 TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
503
504 if (!TD)
505 return false;
506
507 const char* TDName = TD->getDecl()->getIdentifier()->getName();
508 assert (TDName);
509
510 if (TDName[0] != 'N' || TDName[1] != 'S')
511 return false;
512
513 return true;
514}
Ted Kremenek1bffd742008-05-06 15:44:25 +0000515
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000516RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000517
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000518 FunctionTypeProto* FT =
519 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
520
521 if (FT && !isCFRefType(FT->getResultType()))
522 return 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000523
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000524 // FIXME: Add special-cases for functions that retain/release. For now
525 // just handle the default case.
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000526
527 assert (ScratchArgs.empty());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000528 return getPersistentSummary(RetEffect::MakeOwned());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000529}
530
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000531RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000532
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000533 FunctionTypeProto* FT =
534 dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000535
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000536 if (FT) {
537 QualType RetTy = FT->getResultType();
Ted Kremeneka0df99f2008-04-11 20:11:19 +0000538
Ted Kremenek86ad3bc2008-05-05 16:51:50 +0000539 // FIXME: For now we assume that all pointer types returned are referenced
540 // counted. Since this is the "Get" rule, we assume non-ownership, which
541 // works fine for things that are not reference counted. We do this because
542 // some generic data structures return "void*". We need something better
543 // in the future.
544
545 if (!isCFRefType(RetTy) && !RetTy->isPointerType())
546 return 0;
547 }
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000548
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000549 // FIXME: Add special-cases for functions that retain/release. For now
550 // just handle the default case.
551
Ted Kremenek891d5cc2008-04-24 17:22:33 +0000552 assert (ScratchArgs.empty());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000553 return getPersistentSummary(RetEffect::MakeNotOwned());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000554}
555
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000556//===----------------------------------------------------------------------===//
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000557// Summary creation for Selectors.
558//===----------------------------------------------------------------------===//
559
Ted Kremenek1bffd742008-05-06 15:44:25 +0000560RetainSummary*
561RetainSummaryManager::getInitMethodSummary(Selector S) {
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000562 assert(ScratchArgs.empty());
563
564 RetainSummary* Summ =
Ted Kremenek9c32d082008-05-06 00:30:21 +0000565 getPersistentSummary(RetEffect::MakeReceiverAlias());
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000566
Ted Kremenek9c32d082008-05-06 00:30:21 +0000567 ObjCMethSummaries[S] = Summ;
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000568 return Summ;
569}
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000570
Ted Kremenek1bffd742008-05-06 15:44:25 +0000571RetainSummary*
572RetainSummaryManager::getMethodSummary(ObjCMessageExpr* ME) {
573
574 Selector S = ME->getSelector();
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000575
576 // Look up a summary in our cache of Selectors -> Summaries.
Ted Kremenek9c32d082008-05-06 00:30:21 +0000577 ObjCMethSummariesTy::iterator I = ObjCMethSummaries.find(S);
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000578
Ted Kremenek9c32d082008-05-06 00:30:21 +0000579 if (I != ObjCMethSummaries.end())
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000580 return I->second;
Ted Kremenekc8395602008-05-06 21:26:51 +0000581
582#if 0
Ted Kremenek1bffd742008-05-06 15:44:25 +0000583 // Only generate real summaries for methods involving
584 // NSxxxx objects.
Ted Kremenekc8395602008-05-06 21:26:51 +0000585
Ted Kremenek1bffd742008-05-06 15:44:25 +0000586 if (!isNSType(ME->getReceiver()->getType())) {
587 RetainSummary* Summ = getPersistentStopSummary();
588 ObjCMethSummaries[S] = Summ;
589 return Summ;
590 }
Ted Kremenekc8395602008-05-06 21:26:51 +0000591#endif
Ted Kremenek432af592008-05-06 18:11:36 +0000592
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000593 if (!ME->getType()->isPointerType())
594 return 0;
595
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000596 // "initXXX": pass-through for receiver.
597
598 const char* s = S.getIdentifierInfoForSlot(0)->getName();
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000599 assert (ScratchArgs.empty());
Ted Kremenekaee9e572008-05-06 06:09:09 +0000600
Ted Kremenek84548b82008-05-06 06:17:42 +0000601 if (strncmp(s, "init", 4) == 0)
Ted Kremenek432af592008-05-06 18:11:36 +0000602 return getInitMethodSummary(S);
Ted Kremenek1bffd742008-05-06 15:44:25 +0000603
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000604 // "copyXXX", "createXXX", "newXXX": allocators.
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000605
Ted Kremenek84060db2008-05-07 04:25:59 +0000606 if (!isNSType(ME->getReceiver()->getType()))
607 return 0;
608
Ted Kremeneka4b695a2008-05-07 03:45:05 +0000609 if (strcasestr(s, "create") == 0 || strcasestr(s, "copy") == 0 ||
610 strcasestr(s, "new") == 0) {
611
612 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet()
613 : RetEffect::MakeOwned();
614
615 RetainSummary* Summ = getPersistentSummary(E);
616 ObjCMethSummaries[S] = Summ;
Ted Kremenek1bffd742008-05-06 15:44:25 +0000617 return Summ;
618 }
Ted Kremenek1bffd742008-05-06 15:44:25 +0000619
Ted Kremenek46e49ee2008-05-05 23:55:01 +0000620 return 0;
621}
622
Ted Kremenekc8395602008-05-06 21:26:51 +0000623RetainSummary*
624RetainSummaryManager::getInstanceMethodSummary(IdentifierInfo* ClsName,
625 Selector S) {
626
627 // Look up a summary in our cache of Selectors -> Summaries.
628 ObjCMethSummariesTy::iterator I = ObjCInstMethSummaries.find(S);
629
630 if (I != ObjCInstMethSummaries.end())
631 return I->second;
632
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000633 return 0;
634
635#if 0
636 return 0;
637
Ted Kremenekc8395602008-05-06 21:26:51 +0000638 // Don't track anything if using GC.
639 if (isGCEnabled())
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000640 return 0;
641
Ted Kremenekc8395602008-05-06 21:26:51 +0000642 // Inspect the class name and selecrtor to determine if this method
643 // creates new objects.
644 const char* cls = ClsName->getName();
645
646 if (cls[0] == 'N' && cls[1] == 'S') // Ignore preceding "NS" (if present).
647 cls += 2;
648
649 // Heuristic: XXXwithYYY, where XXX is the class name with the "NS"
650 // stripped off is usually an allocation.
651
652 const char* s = S.getIdentifierInfoForSlot(0)->getName();
653
654 if (cls[0] == '\0' || s[0] == '\0' || tolower(cls[0]) != s[0])
655 return 0;
656
657 // Now look at the rest of the characters.
658 ++cls; ++s;
659 unsigned len = strlen(cls);
660
661 // If the prefix doesn't match, don't generate a special summary.
662 if (strncmp(cls, s, len) != 0)
663 return 0;
664
665 // Look at the text after the prefix.
666 s += len;
667
668 if (!(s[0] == '\0' || strncmp(s, "With", 4) == 0))
669 return 0;
670
671 // Generate and return the summary.
672 assert (ScratchArgs.empty());
673
674 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeOwned());
675 ObjCInstMethSummaries[S] = Summ;
676 return Summ;
Ted Kremeneka22cc2f2008-05-06 23:07:13 +0000677#endif
Ted Kremenekc8395602008-05-06 21:26:51 +0000678}
679
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000680void RetainSummaryManager::InitializeInstMethSummaries() {
Ted Kremenek9c32d082008-05-06 00:30:21 +0000681
682 assert (ScratchArgs.empty());
683
684 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
685 RetainSummary* Summ = getPersistentSummary(E);
686
687 // Create the "alloc" selector.
688 ObjCInstMethSummaries[ GetNullarySelector("alloc", Ctx) ] = Summ;
689
690 // Create the "new" selector.
691 ObjCInstMethSummaries[ GetNullarySelector("new", Ctx) ] = Summ;
692
693 // Create the "allocWithZone:" selector.
694 ObjCInstMethSummaries[ GetUnarySelector("allocWithZone", Ctx) ] = Summ;
695
696 // Create the "copyWithZone:" selector.
697 ObjCInstMethSummaries[ GetUnarySelector("copyWithZone", Ctx) ] = Summ;
698
699 // Create the "mutableCopyWithZone:" selector.
700 ObjCInstMethSummaries[ GetUnarySelector("mutableCopyWithZone", Ctx) ] = Summ;
Ted Kremenek432af592008-05-06 18:11:36 +0000701
Ted Kremenekc8395602008-05-06 21:26:51 +0000702 // ** Special cases! **
703 //
704 // FIXME: It would be great if this one day was in a file, rather than
705 // hardcoded into the source code.
706 //
707
708 // NSProcessInfo::processInfo - This instance method does not return
709 // an owning reference.
Ted Kremenek432af592008-05-06 18:11:36 +0000710 ObjCInstMethSummaries[ GetNullarySelector("processInfo", Ctx) ] =
711 getPersistentSummary(RetEffect::MakeNoRet());
Ted Kremenek9c32d082008-05-06 00:30:21 +0000712}
713
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000714void RetainSummaryManager::InitializeMethSummaries() {
715
716 assert (ScratchArgs.empty());
717
Ted Kremenekc8395602008-05-06 21:26:51 +0000718 // Create the "init" selector. It just acts as a pass-through for the
719 // receiver.
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000720 RetainSummary* Summ = getPersistentSummary(RetEffect::MakeReceiverAlias());
721 ObjCMethSummaries[ GetNullarySelector("init", Ctx) ] = Summ;
Ted Kremenekc8395602008-05-06 21:26:51 +0000722
723 // The next methods are allocators.
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000724 RetEffect E = isGCEnabled() ? RetEffect::MakeNoRet() : RetEffect::MakeOwned();
Ted Kremenekc8395602008-05-06 21:26:51 +0000725 Summ = getPersistentSummary(E);
726
727 // Create the "copy" selector.
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000728 ObjCMethSummaries[ GetNullarySelector("copy", Ctx) ] = Summ;
729
730 // Create the "mutableCopy" selector.
731 ObjCMethSummaries[ GetNullarySelector("mutableCopy", Ctx) ] = Summ;
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000732
733 // Create the "retain" selector.
734 E = RetEffect::MakeReceiverAlias();
735 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
736 ObjCMethSummaries[ GetNullarySelector("retain", Ctx) ] = Summ;
737
738 // Create the "release" selector.
739 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
740 ObjCMethSummaries[ GetNullarySelector("release", Ctx) ] = Summ;
741
742 // Create the "autorelease" selector.
Ted Kremenek14993892008-05-06 02:41:27 +0000743 Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : StopTracking);
Ted Kremenek3c0cea32008-05-06 02:26:56 +0000744 ObjCMethSummaries[ GetNullarySelector("autorelease", Ctx) ] = Summ;
Ted Kremenekb3c3c282008-05-06 00:38:54 +0000745}
746
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000747//===----------------------------------------------------------------------===//
Ted Kremenek13922612008-04-16 20:40:59 +0000748// Reference-counting logic (typestate + counts).
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000749//===----------------------------------------------------------------------===//
750
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000751namespace {
752
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000753class VISIBILITY_HIDDEN RefVal {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000754public:
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000755
Ted Kremenek4fd88972008-04-17 18:12:53 +0000756 enum Kind {
757 Owned = 0, // Owning reference.
758 NotOwned, // Reference is not owned by still valid (not freed).
759 Released, // Object has been released.
760 ReturnedOwned, // Returned object passes ownership to caller.
761 ReturnedNotOwned, // Return object does not pass ownership to caller.
762 ErrorUseAfterRelease, // Object used after released.
763 ErrorReleaseNotOwned, // Release of an object that was not owned.
764 ErrorLeak // A memory leak due to excessive reference counts.
765 };
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000766
Ted Kremenek4fd88972008-04-17 18:12:53 +0000767private:
768
769 Kind kind;
770 unsigned Cnt;
771
772 RefVal(Kind k, unsigned cnt) : kind(k), Cnt(cnt) {}
773
774 RefVal(Kind k) : kind(k), Cnt(0) {}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000775
776public:
Ted Kremenekdb863712008-04-16 22:32:20 +0000777
Ted Kremenek4fd88972008-04-17 18:12:53 +0000778 Kind getKind() const { return kind; }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000779
Ted Kremenek4fd88972008-04-17 18:12:53 +0000780 unsigned getCount() const { return Cnt; }
781
782 // Useful predicates.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000783
Ted Kremenek73c750b2008-03-11 18:14:09 +0000784 static bool isError(Kind k) { return k >= ErrorUseAfterRelease; }
785
Ted Kremenekdb863712008-04-16 22:32:20 +0000786 static bool isLeak(Kind k) { return k == ErrorLeak; }
787
Ted Kremeneke7bd9c22008-04-11 22:25:11 +0000788 bool isOwned() const {
789 return getKind() == Owned;
790 }
791
Ted Kremenekdb863712008-04-16 22:32:20 +0000792 bool isNotOwned() const {
793 return getKind() == NotOwned;
794 }
795
Ted Kremenek4fd88972008-04-17 18:12:53 +0000796 bool isReturnedOwned() const {
797 return getKind() == ReturnedOwned;
798 }
799
800 bool isReturnedNotOwned() const {
801 return getKind() == ReturnedNotOwned;
802 }
803
804 bool isNonLeakError() const {
805 Kind k = getKind();
806 return isError(k) && !isLeak(k);
807 }
808
809 // State creation: normal state.
810
Ted Kremenek61b9f872008-04-10 23:09:18 +0000811 static RefVal makeOwned(unsigned Count = 0) {
812 return RefVal(Owned, Count);
813 }
814
815 static RefVal makeNotOwned(unsigned Count = 0) {
816 return RefVal(NotOwned, Count);
817 }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000818
819 static RefVal makeReturnedOwned(unsigned Count) {
820 return RefVal(ReturnedOwned, Count);
821 }
822
823 static RefVal makeReturnedNotOwned() {
824 return RefVal(ReturnedNotOwned);
825 }
826
827 // State creation: errors.
Ted Kremenek61b9f872008-04-10 23:09:18 +0000828
Ted Kremenekce48e002008-05-05 17:53:17 +0000829 static RefVal makeLeak(unsigned Count) { return RefVal(ErrorLeak, Count); }
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000830 static RefVal makeReleased() { return RefVal(Released); }
831 static RefVal makeUseAfterRelease() { return RefVal(ErrorUseAfterRelease); }
832 static RefVal makeReleaseNotOwned() { return RefVal(ErrorReleaseNotOwned); }
Ted Kremenek4fd88972008-04-17 18:12:53 +0000833
834 // Comparison, profiling, and pretty-printing.
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000835
Ted Kremenek4fd88972008-04-17 18:12:53 +0000836 bool operator==(const RefVal& X) const {
837 return kind == X.kind && Cnt == X.Cnt;
838 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000839
Ted Kremenek4fd88972008-04-17 18:12:53 +0000840 void Profile(llvm::FoldingSetNodeID& ID) const {
841 ID.AddInteger((unsigned) kind);
842 ID.AddInteger(Cnt);
843 }
844
Ted Kremenekf3948042008-03-11 19:44:10 +0000845 void print(std::ostream& Out) const;
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000846};
Ted Kremenekf3948042008-03-11 19:44:10 +0000847
848void RefVal::print(std::ostream& Out) const {
849 switch (getKind()) {
850 default: assert(false);
Ted Kremenek61b9f872008-04-10 23:09:18 +0000851 case Owned: {
852 Out << "Owned";
853 unsigned cnt = getCount();
854 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000855 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000856 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000857
Ted Kremenek61b9f872008-04-10 23:09:18 +0000858 case NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +0000859 Out << "NotOwned";
Ted Kremenek61b9f872008-04-10 23:09:18 +0000860 unsigned cnt = getCount();
861 if (cnt) Out << " (+ " << cnt << ")";
Ted Kremenekf3948042008-03-11 19:44:10 +0000862 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +0000863 }
Ted Kremenekf3948042008-03-11 19:44:10 +0000864
Ted Kremenek4fd88972008-04-17 18:12:53 +0000865 case ReturnedOwned: {
866 Out << "ReturnedOwned";
867 unsigned cnt = getCount();
868 if (cnt) Out << " (+ " << cnt << ")";
869 break;
870 }
871
872 case ReturnedNotOwned: {
873 Out << "ReturnedNotOwned";
874 unsigned cnt = getCount();
875 if (cnt) Out << " (+ " << cnt << ")";
876 break;
877 }
878
Ted Kremenekf3948042008-03-11 19:44:10 +0000879 case Released:
880 Out << "Released";
881 break;
882
Ted Kremenekdb863712008-04-16 22:32:20 +0000883 case ErrorLeak:
884 Out << "Leaked";
885 break;
886
Ted Kremenekf3948042008-03-11 19:44:10 +0000887 case ErrorUseAfterRelease:
888 Out << "Use-After-Release [ERROR]";
889 break;
890
891 case ErrorReleaseNotOwned:
892 Out << "Release of Not-Owned [ERROR]";
893 break;
894 }
895}
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000896
Ted Kremenekce48e002008-05-05 17:53:17 +0000897static inline unsigned GetCount(RefVal V) {
898 switch (V.getKind()) {
899 default:
900 return V.getCount();
901
902 case RefVal::Owned:
903 return V.getCount()+1;
904 }
905}
906
Ted Kremenek13922612008-04-16 20:40:59 +0000907//===----------------------------------------------------------------------===//
908// Transfer functions.
909//===----------------------------------------------------------------------===//
910
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000911class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Ted Kremenek8dd56462008-04-18 03:39:05 +0000912public:
Ted Kremenekf3948042008-03-11 19:44:10 +0000913 // Type definitions.
914
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000915 typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000916 typedef RefBindings::Factory RefBFactoryTy;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000917
Ted Kremenek8dd56462008-04-18 03:39:05 +0000918 typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
919 ReleasesNotOwnedTy;
920
921 typedef ReleasesNotOwnedTy UseAfterReleasesTy;
922
923 typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
Ted Kremenekdb863712008-04-16 22:32:20 +0000924 LeaksTy;
Ted Kremenek8dd56462008-04-18 03:39:05 +0000925
Ted Kremenekf3948042008-03-11 19:44:10 +0000926 class BindingsPrinter : public ValueState::CheckerStatePrinter {
927 public:
928 virtual void PrintCheckerState(std::ostream& Out, void* State,
929 const char* nl, const char* sep);
930 };
Ted Kremenek8dd56462008-04-18 03:39:05 +0000931
932private:
Ted Kremenekf3948042008-03-11 19:44:10 +0000933 // Instance variables.
934
Ted Kremenekd3dbcf42008-05-05 22:11:16 +0000935 RetainSummaryManager Summaries;
936 const bool EmitStandardWarnings;
937 const LangOptions& LOpts;
938 RefBFactoryTy RefBFactory;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000939
Ted Kremenek73c750b2008-03-11 18:14:09 +0000940 UseAfterReleasesTy UseAfterReleases;
941 ReleasesNotOwnedTy ReleasesNotOwned;
Ted Kremenekdb863712008-04-16 22:32:20 +0000942 LeaksTy Leaks;
Ted Kremenek73c750b2008-03-11 18:14:09 +0000943
Ted Kremenekf3948042008-03-11 19:44:10 +0000944 BindingsPrinter Printer;
945
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000946 Selector RetainSelector;
947 Selector ReleaseSelector;
Ted Kremenek5934cee2008-05-01 02:18:37 +0000948 Selector AutoreleaseSelector;
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000949
Ted Kremenek8dd56462008-04-18 03:39:05 +0000950public:
951
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000952 static RefBindings GetRefBindings(ValueState& StImpl) {
953 return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
954 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000955
Ted Kremenek8dd56462008-04-18 03:39:05 +0000956private:
957
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000958 static void SetRefBindings(ValueState& StImpl, RefBindings B) {
959 StImpl.CheckerState = B.getRoot();
960 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000961
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000962 RefBindings Remove(RefBindings B, SymbolID sym) {
963 return RefBFactory.Remove(B, sym);
964 }
965
Ted Kremenek1ac08d62008-03-11 17:48:22 +0000966 RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000967 RefVal::Kind& hasErr);
968
Ted Kremenekdb863712008-04-16 22:32:20 +0000969 void ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
970 GRStmtNodeBuilder<ValueState>& Builder,
971 Expr* NodeExpr, Expr* ErrorExpr,
972 ExplodedNode<ValueState>* Pred,
973 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +0000974 RefVal::Kind hasErr, SymbolID Sym);
Ted Kremenekdb863712008-04-16 22:32:20 +0000975
976 ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
977 SymbolID sid, RefVal V, bool& hasLeak);
978
979 ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St,
980 SymbolID sid);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +0000981
982public:
Ted Kremenek13922612008-04-16 20:40:59 +0000983
Ted Kremenek9f741612008-05-02 18:01:49 +0000984 CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
985 const LangOptions& lopts)
Ted Kremenek377e2302008-04-29 05:33:51 +0000986 : Summaries(Ctx, gcenabled),
Ted Kremenek9f741612008-05-02 18:01:49 +0000987 EmitStandardWarnings(StandardWarnings),
Ted Kremenek072192b2008-04-30 23:47:44 +0000988 LOpts(lopts),
Ted Kremenekb83e02e2008-05-01 18:31:44 +0000989 RetainSelector(GetNullarySelector("retain", Ctx)),
990 ReleaseSelector(GetNullarySelector("release", Ctx)),
991 AutoreleaseSelector(GetNullarySelector("autorelease", Ctx)) {}
Ted Kremenek9ed18e62008-04-16 04:28:53 +0000992
Ted Kremenek8dd56462008-04-18 03:39:05 +0000993 virtual ~CFRefCount() {
994 for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
995 delete I->second;
996 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +0000997
998 virtual void RegisterChecks(GRExprEngine& Eng);
Ted Kremenekf3948042008-03-11 19:44:10 +0000999
1000 virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
1001 return &Printer;
1002 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001003
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001004 bool isGCEnabled() const { return Summaries.isGCEnabled(); }
Ted Kremenek072192b2008-04-30 23:47:44 +00001005 const LangOptions& getLangOptions() const { return LOpts; }
1006
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001007 // Calls.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001008
1009 void EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1010 GRExprEngine& Eng,
1011 GRStmtNodeBuilder<ValueState>& Builder,
1012 Expr* Ex,
1013 Expr* Receiver,
1014 RetainSummary* Summ,
1015 Expr** arg_beg, Expr** arg_end,
1016 ExplodedNode<ValueState>* Pred);
1017
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001018 virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek199e1a02008-03-12 21:06:49 +00001019 GRExprEngine& Eng,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001020 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek186350f2008-04-23 20:12:28 +00001021 CallExpr* CE, RVal L,
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001022 ExplodedNode<ValueState>* Pred);
Ted Kremenekfa34b332008-04-09 01:10:13 +00001023
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001024
Ted Kremenek85348202008-04-15 23:44:31 +00001025 virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1026 GRExprEngine& Engine,
1027 GRStmtNodeBuilder<ValueState>& Builder,
1028 ObjCMessageExpr* ME,
1029 ExplodedNode<ValueState>* Pred);
1030
1031 bool EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst,
1032 GRExprEngine& Engine,
1033 GRStmtNodeBuilder<ValueState>& Builder,
1034 ObjCMessageExpr* ME,
1035 ExplodedNode<ValueState>* Pred);
1036
Ted Kremenek13922612008-04-16 20:40:59 +00001037 // Stores.
1038
1039 virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
1040 GRExprEngine& Engine,
1041 GRStmtNodeBuilder<ValueState>& Builder,
1042 Expr* E, ExplodedNode<ValueState>* Pred,
1043 ValueState* St, RVal TargetLV, RVal Val);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001044 // End-of-path.
1045
1046 virtual void EvalEndPath(GRExprEngine& Engine,
1047 GREndPathNodeBuilder<ValueState>& Builder);
1048
Ted Kremenek652adc62008-04-24 23:57:27 +00001049 virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1050 GRExprEngine& Engine,
1051 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001052 ExplodedNode<ValueState>* Pred,
1053 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001054 ValueState* St,
1055 const ValueStateManager::DeadSymbolsTy& Dead);
Ted Kremenek4fd88972008-04-17 18:12:53 +00001056 // Return statements.
1057
1058 virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1059 GRExprEngine& Engine,
1060 GRStmtNodeBuilder<ValueState>& Builder,
1061 ReturnStmt* S,
1062 ExplodedNode<ValueState>* Pred);
Ted Kremenekcb612922008-04-18 19:23:43 +00001063
1064 // Assumptions.
1065
1066 virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
1067 RVal Cond, bool Assumption, bool& isFeasible);
1068
Ted Kremenekfa34b332008-04-09 01:10:13 +00001069 // Error iterators.
1070
1071 typedef UseAfterReleasesTy::iterator use_after_iterator;
1072 typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
Ted Kremenek989d5192008-04-17 23:43:50 +00001073 typedef LeaksTy::iterator leaks_iterator;
Ted Kremenekfa34b332008-04-09 01:10:13 +00001074
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001075 use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
1076 use_after_iterator use_after_end() { return UseAfterReleases.end(); }
Ted Kremenekfa34b332008-04-09 01:10:13 +00001077
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001078 bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
1079 bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
Ted Kremenek989d5192008-04-17 23:43:50 +00001080
1081 leaks_iterator leaks_begin() { return Leaks.begin(); }
1082 leaks_iterator leaks_end() { return Leaks.end(); }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001083};
1084
1085} // end anonymous namespace
1086
Ted Kremenek8dd56462008-04-18 03:39:05 +00001087
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001088
1089
Ted Kremenekf3948042008-03-11 19:44:10 +00001090void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
1091 void* State, const char* nl,
1092 const char* sep) {
1093 RefBindings B((RefBindings::TreeTy*) State);
1094
1095 if (State)
1096 Out << sep << nl;
1097
1098 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1099 Out << (*I).first << " : ";
1100 (*I).second.print(Out);
1101 Out << nl;
1102 }
1103}
1104
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001105static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001106 return Summ ? Summ->getArg(idx) : DoNothing;
1107}
1108
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001109static inline RetEffect GetRetEffect(RetainSummary* Summ) {
1110 return Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001111}
1112
Ted Kremenek14993892008-05-06 02:41:27 +00001113static inline ArgEffect GetReceiverE(RetainSummary* Summ) {
1114 return Summ ? Summ->getReceiverEffect() : DoNothing;
1115}
1116
Ted Kremenekdb863712008-04-16 22:32:20 +00001117void CFRefCount::ProcessNonLeakError(ExplodedNodeSet<ValueState>& Dst,
1118 GRStmtNodeBuilder<ValueState>& Builder,
1119 Expr* NodeExpr, Expr* ErrorExpr,
1120 ExplodedNode<ValueState>* Pred,
1121 ValueState* St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001122 RefVal::Kind hasErr, SymbolID Sym) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001123 Builder.BuildSinks = true;
1124 GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
1125
1126 if (!N) return;
1127
1128 switch (hasErr) {
1129 default: assert(false);
1130 case RefVal::ErrorUseAfterRelease:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001131 UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001132 break;
1133
1134 case RefVal::ErrorReleaseNotOwned:
Ted Kremenek8dd56462008-04-18 03:39:05 +00001135 ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001136 break;
1137 }
1138}
1139
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001140void CFRefCount::EvalSummary(ExplodedNodeSet<ValueState>& Dst,
1141 GRExprEngine& Eng,
1142 GRStmtNodeBuilder<ValueState>& Builder,
1143 Expr* Ex,
1144 Expr* Receiver,
1145 RetainSummary* Summ,
1146 Expr** arg_beg, Expr** arg_end,
1147 ExplodedNode<ValueState>* Pred) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001148
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001149
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001150 // Get the state.
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001151 ValueStateManager& StateMgr = Eng.getStateManager();
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001152 ValueState* St = Builder.GetState(Pred);
1153
Ted Kremenek14993892008-05-06 02:41:27 +00001154
1155 // Evaluate the effect of the arguments.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001156
1157 ValueState StVals = *St;
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001158 RefVal::Kind hasErr = (RefVal::Kind) 0;
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001159 unsigned idx = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001160 Expr* ErrorExpr = NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001161 SymbolID ErrorSym = 0;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001162
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001163 for (Expr **I = arg_beg, **E = arg_end; I != E; ++I, ++idx) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001164
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001165 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001166
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001167 if (isa<lval::SymbolVal>(V)) {
1168 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
Ted Kremenekf9561e52008-04-11 20:23:24 +00001169 RefBindings B = GetRefBindings(StVals);
1170
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001171 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001172 B = Update(B, Sym, T->getValue().second, GetArgE(Summ, idx), hasErr);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001173 SetRefBindings(StVals, B);
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001174
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001175 if (hasErr) {
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001176 ErrorExpr = *I;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001177 ErrorSym = T->getValue().first;
Ted Kremenekbcf50ad2008-04-11 18:40:51 +00001178 break;
1179 }
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001180 }
Ted Kremenekb8873552008-04-11 20:51:02 +00001181 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001182 else if (isa<LVal>(V)) {
1183 // Nuke all arguments passed by reference.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001184 StateMgr.Unbind(StVals, cast<LVal>(V));
Ted Kremenekb8873552008-04-11 20:51:02 +00001185 }
Ted Kremeneka5488462008-04-22 21:39:21 +00001186 else if (isa<nonlval::LValAsInteger>(V))
1187 StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001188 }
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001189
Ted Kremenek14993892008-05-06 02:41:27 +00001190 // Evaluate the effect on the message receiver.
1191
1192 if (!ErrorExpr && Receiver) {
1193 RVal V = StateMgr.GetRVal(St, Receiver);
1194
1195 if (isa<lval::SymbolVal>(V)) {
1196 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1197 RefBindings B = GetRefBindings(StVals);
1198
1199 if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
1200 B = Update(B, Sym, T->getValue().second, GetReceiverE(Summ), hasErr);
1201 SetRefBindings(StVals, B);
1202
1203 if (hasErr) {
1204 ErrorExpr = Receiver;
1205 ErrorSym = T->getValue().first;
1206 }
1207 }
1208 }
1209 }
1210
1211 // Get the persistent state.
1212
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001213 St = StateMgr.getPersistentState(StVals);
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001214
Ted Kremenek14993892008-05-06 02:41:27 +00001215 // Process any errors.
1216
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001217 if (hasErr) {
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001218 ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
Ted Kremenek8dd56462008-04-18 03:39:05 +00001219 hasErr, ErrorSym);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001220 return;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001221 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001222
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001223 // Finally, consult the summary for the return value.
1224
Ted Kremenek3c0cea32008-05-06 02:26:56 +00001225 RetEffect RE = GetRetEffect(Summ);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001226
1227 switch (RE.getKind()) {
1228 default:
1229 assert (false && "Unhandled RetEffect."); break;
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001230
Ted Kremenek940b1d82008-04-10 23:44:06 +00001231 case RetEffect::NoRet:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001232
Ted Kremenekf9561e52008-04-11 20:23:24 +00001233 // Make up a symbol for the return value (not reference counted).
Ted Kremenekb8873552008-04-11 20:51:02 +00001234 // FIXME: This is basically copy-and-paste from GRSimpleVals. We
1235 // should compose behavior, not copy it.
Ted Kremenekf9561e52008-04-11 20:23:24 +00001236
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001237 if (Ex->getType() != Eng.getContext().VoidTy) {
Ted Kremenekf9561e52008-04-11 20:23:24 +00001238 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001239 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001240
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001241 RVal X = Ex->getType()->isPointerType()
1242 ? cast<RVal>(lval::SymbolVal(Sym))
1243 : cast<RVal>(nonlval::SymbolVal(Sym));
Ted Kremenekf9561e52008-04-11 20:23:24 +00001244
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001245 St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenekf9561e52008-04-11 20:23:24 +00001246 }
1247
Ted Kremenek940b1d82008-04-10 23:44:06 +00001248 break;
1249
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001250 case RetEffect::Alias: {
1251 unsigned idx = RE.getValue();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001252 assert ((arg_end - arg_beg) >= 0);
1253 assert (idx < (unsigned) (arg_end - arg_beg));
1254 RVal V = StateMgr.GetRVal(St, arg_beg[idx]);
1255 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001256 break;
1257 }
1258
Ted Kremenek14993892008-05-06 02:41:27 +00001259 case RetEffect::ReceiverAlias: {
1260 assert (Receiver);
1261 RVal V = StateMgr.GetRVal(St, Receiver);
1262 St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
1263 break;
1264 }
1265
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001266 case RetEffect::OwnedSymbol: {
1267 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001268 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
1269
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001270 ValueState StImpl = *St;
1271 RefBindings B = GetRefBindings(StImpl);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001272 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned()));
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001273
1274 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001275 Ex, lval::SymbolVal(Sym),
1276 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001277
1278 break;
1279 }
1280
1281 case RetEffect::NotOwnedSymbol: {
1282 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001283 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001284
1285 ValueState StImpl = *St;
1286 RefBindings B = GetRefBindings(StImpl);
1287 SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
1288
1289 St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001290 Ex, lval::SymbolVal(Sym),
1291 Eng.getCFG().isBlkExpr(Ex), false);
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001292
1293 break;
1294 }
1295 }
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001296
1297 Builder.MakeNode(Dst, Ex, Pred, St);
1298}
1299
1300
1301void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
1302 GRExprEngine& Eng,
1303 GRStmtNodeBuilder<ValueState>& Builder,
1304 CallExpr* CE, RVal L,
1305 ExplodedNode<ValueState>* Pred) {
1306
1307
1308 RetainSummary* Summ = NULL;
1309
1310 // Get the summary.
1311
1312 if (isa<lval::FuncVal>(L)) {
1313 lval::FuncVal FV = cast<lval::FuncVal>(L);
1314 FunctionDecl* FD = FV.getDecl();
1315 Summ = Summaries.getSummary(FD, Eng.getContext());
1316 }
1317
1318 EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
1319 CE->arg_begin(), CE->arg_end(), Pred);
Ted Kremenek2fff37e2008-03-06 00:08:09 +00001320}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001321
Ted Kremenek85348202008-04-15 23:44:31 +00001322
1323void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
1324 GRExprEngine& Eng,
1325 GRStmtNodeBuilder<ValueState>& Builder,
1326 ObjCMessageExpr* ME,
1327 ExplodedNode<ValueState>* Pred) {
1328
Ted Kremenekb3095252008-05-06 04:20:12 +00001329 RetainSummary* Summ;
Ted Kremenek9040c652008-05-01 21:31:50 +00001330
Ted Kremenekb3095252008-05-06 04:20:12 +00001331 if (ME->getReceiver())
Ted Kremenek1bffd742008-05-06 15:44:25 +00001332 Summ = Summaries.getMethodSummary(ME);
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001333 else
Ted Kremenekb3095252008-05-06 04:20:12 +00001334 Summ = Summaries.getInstanceMethodSummary(ME->getClassName(),
1335 ME->getSelector());
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001336
Ted Kremenekb3095252008-05-06 04:20:12 +00001337 EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
1338 ME->arg_begin(), ME->arg_end(), Pred);
Ted Kremenek85348202008-04-15 23:44:31 +00001339}
Ted Kremenekb3095252008-05-06 04:20:12 +00001340
Ted Kremenek13922612008-04-16 20:40:59 +00001341// Stores.
1342
1343void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
1344 GRExprEngine& Eng,
1345 GRStmtNodeBuilder<ValueState>& Builder,
1346 Expr* E, ExplodedNode<ValueState>* Pred,
1347 ValueState* St, RVal TargetLV, RVal Val) {
1348
1349 // Check if we have a binding for "Val" and if we are storing it to something
1350 // we don't understand or otherwise the value "escapes" the function.
1351
1352 if (!isa<lval::SymbolVal>(Val))
1353 return;
1354
1355 // Are we storing to something that causes the value to "escape"?
1356
1357 bool escapes = false;
1358
1359 if (!isa<lval::DeclVal>(TargetLV))
1360 escapes = true;
1361 else
1362 escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
1363
1364 if (!escapes)
1365 return;
1366
1367 SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
1368 RefBindings B = GetRefBindings(*St);
1369 RefBindings::TreeTy* T = B.SlimFind(Sym);
1370
1371 if (!T)
1372 return;
1373
Ted Kremenekdb863712008-04-16 22:32:20 +00001374 // Nuke the binding.
1375 St = NukeBinding(Eng.getStateManager(), St, Sym);
Ted Kremenek13922612008-04-16 20:40:59 +00001376
1377 // Hand of the remaining logic to the parent implementation.
1378 GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
1379}
1380
Ted Kremenekdb863712008-04-16 22:32:20 +00001381
1382ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
1383 SymbolID sid) {
1384 ValueState StImpl = *St;
1385 RefBindings B = GetRefBindings(StImpl);
1386 StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
1387 return VMgr.getPersistentState(StImpl);
1388}
1389
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001390// End-of-path.
1391
Ted Kremenekdb863712008-04-16 22:32:20 +00001392ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
1393 ValueState* St, SymbolID sid,
1394 RefVal V, bool& hasLeak) {
1395
Ted Kremenek4fd88972008-04-17 18:12:53 +00001396 hasLeak = V.isOwned() ||
1397 ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
Ted Kremenekdb863712008-04-16 22:32:20 +00001398
1399 if (!hasLeak)
1400 return NukeBinding(VMgr, St, sid);
1401
1402 RefBindings B = GetRefBindings(*St);
1403 ValueState StImpl = *St;
Ted Kremenekce48e002008-05-05 17:53:17 +00001404
1405 StImpl.CheckerState =
1406 RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
1407
Ted Kremenekdb863712008-04-16 22:32:20 +00001408 return VMgr.getPersistentState(StImpl);
1409}
1410
1411void CFRefCount::EvalEndPath(GRExprEngine& Eng,
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001412 GREndPathNodeBuilder<ValueState>& Builder) {
1413
Ted Kremenekdb863712008-04-16 22:32:20 +00001414 ValueState* St = Builder.getState();
1415 RefBindings B = GetRefBindings(*St);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001416
Ted Kremenekdb863712008-04-16 22:32:20 +00001417 llvm::SmallVector<SymbolID, 10> Leaked;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001418
Ted Kremenekdb863712008-04-16 22:32:20 +00001419 for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1420 bool hasLeak = false;
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001421
Ted Kremenekdb863712008-04-16 22:32:20 +00001422 St = HandleSymbolDeath(Eng.getStateManager(), St,
1423 (*I).first, (*I).second, hasLeak);
1424
1425 if (hasLeak) Leaked.push_back((*I).first);
1426 }
Ted Kremenek652adc62008-04-24 23:57:27 +00001427
1428 if (Leaked.empty())
1429 return;
1430
Ted Kremenek8dd56462008-04-18 03:39:05 +00001431 ExplodedNode<ValueState>* N = Builder.MakeNode(St);
Ted Kremenek4f285152008-04-18 16:30:14 +00001432
Ted Kremenek652adc62008-04-24 23:57:27 +00001433 if (!N)
Ted Kremenek4f285152008-04-18 16:30:14 +00001434 return;
Ted Kremenekcb612922008-04-18 19:23:43 +00001435
Ted Kremenek8dd56462008-04-18 03:39:05 +00001436 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1437 assert (!LeaksAtNode);
1438 LeaksAtNode = new std::vector<SymbolID>();
Ted Kremenekdb863712008-04-16 22:32:20 +00001439
1440 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1441 E = Leaked.end(); I != E; ++I)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001442 (*LeaksAtNode).push_back(*I);
Ted Kremeneke7bd9c22008-04-11 22:25:11 +00001443}
1444
Ted Kremenek652adc62008-04-24 23:57:27 +00001445// Dead symbols.
1446
1447void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
1448 GRExprEngine& Eng,
1449 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek910e9992008-04-25 01:25:15 +00001450 ExplodedNode<ValueState>* Pred,
1451 Stmt* S,
Ted Kremenek652adc62008-04-24 23:57:27 +00001452 ValueState* St,
1453 const ValueStateManager::DeadSymbolsTy& Dead) {
Ted Kremenek910e9992008-04-25 01:25:15 +00001454
Ted Kremenek652adc62008-04-24 23:57:27 +00001455 // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1456
1457 RefBindings B = GetRefBindings(*St);
1458 llvm::SmallVector<SymbolID, 10> Leaked;
1459
1460 for (ValueStateManager::DeadSymbolsTy::const_iterator
1461 I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
1462
1463 RefBindings::TreeTy* T = B.SlimFind(*I);
1464
1465 if (!T)
1466 continue;
1467
1468 bool hasLeak = false;
1469
1470 St = HandleSymbolDeath(Eng.getStateManager(), St,
1471 *I, T->getValue().second, hasLeak);
1472
1473 if (hasLeak) Leaked.push_back(*I);
1474 }
1475
1476 if (Leaked.empty())
1477 return;
1478
1479 ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);
1480
1481 if (!N)
1482 return;
1483
1484 std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1485 assert (!LeaksAtNode);
1486 LeaksAtNode = new std::vector<SymbolID>();
1487
1488 for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
1489 E = Leaked.end(); I != E; ++I)
1490 (*LeaksAtNode).push_back(*I);
1491}
1492
Ted Kremenek4fd88972008-04-17 18:12:53 +00001493 // Return statements.
1494
1495void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
1496 GRExprEngine& Eng,
1497 GRStmtNodeBuilder<ValueState>& Builder,
1498 ReturnStmt* S,
1499 ExplodedNode<ValueState>* Pred) {
1500
1501 Expr* RetE = S->getRetValue();
1502 if (!RetE) return;
1503
1504 ValueStateManager& StateMgr = Eng.getStateManager();
1505 ValueState* St = Builder.GetState(Pred);
1506 RVal V = StateMgr.GetRVal(St, RetE);
1507
1508 if (!isa<lval::SymbolVal>(V))
1509 return;
1510
1511 // Get the reference count binding (if any).
1512 SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
1513 RefBindings B = GetRefBindings(*St);
1514 RefBindings::TreeTy* T = B.SlimFind(Sym);
1515
1516 if (!T)
1517 return;
1518
1519 // Change the reference count.
1520
1521 RefVal X = T->getValue().second;
1522
1523 switch (X.getKind()) {
1524
1525 case RefVal::Owned: {
1526 unsigned cnt = X.getCount();
1527 X = RefVal::makeReturnedOwned(cnt);
1528 break;
1529 }
1530
1531 case RefVal::NotOwned: {
1532 unsigned cnt = X.getCount();
1533 X = cnt ? RefVal::makeReturnedOwned(cnt - 1)
1534 : RefVal::makeReturnedNotOwned();
1535 break;
1536 }
1537
1538 default:
Ted Kremenek4fd88972008-04-17 18:12:53 +00001539 return;
1540 }
1541
1542 // Update the binding.
1543
1544 ValueState StImpl = *St;
1545 StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
1546 Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
1547}
1548
Ted Kremenekcb612922008-04-18 19:23:43 +00001549// Assumptions.
1550
1551ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
1552 RVal Cond, bool Assumption,
1553 bool& isFeasible) {
1554
1555 // FIXME: We may add to the interface of EvalAssume the list of symbols
1556 // whose assumptions have changed. For now we just iterate through the
1557 // bindings and check if any of the tracked symbols are NULL. This isn't
1558 // too bad since the number of symbols we will track in practice are
1559 // probably small and EvalAssume is only called at branches and a few
1560 // other places.
1561
1562 RefBindings B = GetRefBindings(*St);
1563
1564 if (B.isEmpty())
1565 return St;
1566
1567 bool changed = false;
1568
1569 for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
1570
1571 // Check if the symbol is null (or equal to any constant).
1572 // If this is the case, stop tracking the symbol.
1573
1574 if (St->getSymVal(I.getKey())) {
1575 changed = true;
1576 B = RefBFactory.Remove(B, I.getKey());
1577 }
1578 }
1579
1580 if (!changed)
1581 return St;
1582
1583 ValueState StImpl = *St;
1584 StImpl.CheckerState = B.getRoot();
1585 return Eng.getStateManager().getPersistentState(StImpl);
1586}
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001587
1588CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001589 RefVal V, ArgEffect E,
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001590 RefVal::Kind& hasErr) {
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001591
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001592 // FIXME: This dispatch can potentially be sped up by unifiying it into
1593 // a single switch statement. Opt for simplicity for now.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001594
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001595 switch (E) {
1596 default:
1597 assert (false && "Unhandled CFRef transition.");
1598
1599 case DoNothing:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001600 if (!isGCEnabled() && V.getKind() == RefVal::Released) {
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001601 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001602 hasErr = V.getKind();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +00001603 break;
1604 }
1605
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001606 return B;
1607
Ted Kremenek14993892008-05-06 02:41:27 +00001608 case StopTracking:
1609 return RefBFactory.Remove(B, sym);
1610
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001611 case IncRef:
1612 switch (V.getKind()) {
1613 default:
1614 assert(false);
1615
1616 case RefVal::Owned:
Ted Kremenek940b1d82008-04-10 23:44:06 +00001617 V = RefVal::makeOwned(V.getCount()+1);
1618 break;
Ted Kremenek61b9f872008-04-10 23:09:18 +00001619
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001620 case RefVal::NotOwned:
Ted Kremenek61b9f872008-04-10 23:09:18 +00001621 V = RefVal::makeNotOwned(V.getCount()+1);
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001622 break;
1623
1624 case RefVal::Released:
Ted Kremenekd3dbcf42008-05-05 22:11:16 +00001625 if (isGCEnabled())
Ted Kremenek65c91652008-04-29 05:44:10 +00001626 V = RefVal::makeOwned();
1627 else {
1628 V = RefVal::makeUseAfterRelease();
1629 hasErr = V.getKind();
1630 }
1631
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001632 break;
1633 }
1634
Ted Kremenek940b1d82008-04-10 23:44:06 +00001635 break;
1636
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001637 case DecRef:
1638 switch (V.getKind()) {
1639 default:
1640 assert (false);
1641
1642 case RefVal::Owned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001643 unsigned Count = V.getCount();
1644 V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001645 break;
1646 }
1647
Ted Kremenek61b9f872008-04-10 23:09:18 +00001648 case RefVal::NotOwned: {
Ted Kremenek4fd88972008-04-17 18:12:53 +00001649 unsigned Count = V.getCount();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001650
Ted Kremenek4fd88972008-04-17 18:12:53 +00001651 if (Count > 0)
1652 V = RefVal::makeNotOwned(Count - 1);
Ted Kremenek61b9f872008-04-10 23:09:18 +00001653 else {
1654 V = RefVal::makeReleaseNotOwned();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001655 hasErr = V.getKind();
Ted Kremenek61b9f872008-04-10 23:09:18 +00001656 }
1657
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001658 break;
1659 }
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001660
1661 case RefVal::Released:
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001662 V = RefVal::makeUseAfterRelease();
Ted Kremenek9ed18e62008-04-16 04:28:53 +00001663 hasErr = V.getKind();
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001664 break;
1665 }
Ted Kremenek940b1d82008-04-10 23:44:06 +00001666
1667 break;
Ted Kremenek1ac08d62008-03-11 17:48:22 +00001668 }
1669
1670 return RefBFactory.Add(B, sym, V);
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00001671}
1672
Ted Kremenekfa34b332008-04-09 01:10:13 +00001673
1674//===----------------------------------------------------------------------===//
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00001675// Error reporting.
Ted Kremenekfa34b332008-04-09 01:10:13 +00001676//===----------------------------------------------------------------------===//
1677
Ted Kremenek8dd56462008-04-18 03:39:05 +00001678namespace {
1679
1680 //===-------------===//
1681 // Bug Descriptions. //
1682 //===-------------===//
1683
Ted Kremenek95cc1ba2008-04-18 20:54:29 +00001684 class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
Ted Kremenek8dd56462008-04-18 03:39:05 +00001685 protected:
1686 CFRefCount& TF;
1687
1688 public:
1689 CFRefBug(CFRefCount& tf) : TF(tf) {}
Ted Kremenek072192b2008-04-30 23:47:44 +00001690
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001691 CFRefCount& getTF() { return TF; }
Ted Kremenek789deac2008-05-05 23:16:31 +00001692 const CFRefCount& getTF() const { return TF; }
1693
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001694 virtual bool isLeak() const { return false; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001695 };
1696
1697 class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
1698 public:
1699 UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
1700
1701 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001702 return "Use-After-Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001703 }
1704 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001705 return "Reference-counted object is used"
1706 " after it is released.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001707 }
1708
1709 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001710 };
1711
1712 class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
1713 public:
1714 BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
1715
1716 virtual const char* getName() const {
Ted Kremenek789deac2008-05-05 23:16:31 +00001717 return "Bad Release";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001718 }
1719 virtual const char* getDescription() const {
1720 return "Incorrect decrement of the reference count of a "
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001721 "CoreFoundation object: "
Ted Kremenek8dd56462008-04-18 03:39:05 +00001722 "The object is not owned at this point by the caller.";
1723 }
1724
1725 virtual void EmitWarnings(BugReporter& BR);
1726 };
1727
1728 class VISIBILITY_HIDDEN Leak : public CFRefBug {
1729 public:
1730 Leak(CFRefCount& tf) : CFRefBug(tf) {}
1731
1732 virtual const char* getName() const {
Ted Kremenek432af592008-05-06 18:11:36 +00001733
1734 if (getTF().isGCEnabled())
1735 return "Memory Leak (GC)";
1736
1737 if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
1738 return "Memory Leak (Hybrid MM, non-GC)";
1739
1740 assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
1741 return "Memory Leak";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001742 }
1743
1744 virtual const char* getDescription() const {
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001745 return "Object leaked.";
Ted Kremenek8dd56462008-04-18 03:39:05 +00001746 }
1747
1748 virtual void EmitWarnings(BugReporter& BR);
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001749 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001750 virtual bool isLeak() const { return true; }
Ted Kremenek8dd56462008-04-18 03:39:05 +00001751 };
1752
1753 //===---------===//
1754 // Bug Reports. //
1755 //===---------===//
1756
1757 class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
1758 SymbolID Sym;
1759 public:
Ted Kremenek072192b2008-04-30 23:47:44 +00001760 CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym)
Ted Kremenek8dd56462008-04-18 03:39:05 +00001761 : RangedBugReport(D, n), Sym(sym) {}
1762
1763 virtual ~CFRefReport() {}
1764
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001765 CFRefBug& getBugType() {
1766 return (CFRefBug&) RangedBugReport::getBugType();
1767 }
1768 const CFRefBug& getBugType() const {
1769 return (const CFRefBug&) RangedBugReport::getBugType();
1770 }
1771
1772 virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
1773 const SourceRange*& end) {
1774
Ted Kremeneke92c1b22008-05-02 20:53:50 +00001775 if (!getBugType().isLeak())
Ted Kremenekbb77e9b2008-05-01 22:50:36 +00001776 RangedBugReport::getRanges(BR, beg, end);
1777 else {
1778 beg = 0;
1779 end = 0;
1780 }
1781 }
1782
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001783 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
1784 ExplodedNode<ValueState>* N);
1785
Ted Kremenek072192b2008-04-30 23:47:44 +00001786 virtual std::pair<const char**,const char**> getExtraDescriptiveText();
Ted Kremenek8dd56462008-04-18 03:39:05 +00001787
1788 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
1789 ExplodedNode<ValueState>* PrevN,
1790 ExplodedGraph<ValueState>& G,
1791 BugReporter& BR);
1792 };
1793
1794
1795} // end anonymous namespace
1796
1797void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
Ted Kremenek9f741612008-05-02 18:01:49 +00001798 if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001799 Eng.Register(new UseAfterRelease(*this));
1800 Eng.Register(new BadRelease(*this));
1801 Eng.Register(new Leak(*this));
1802}
1803
Ted Kremenek072192b2008-04-30 23:47:44 +00001804
1805static const char* Msgs[] = {
1806 "Code is compiled in garbage collection only mode" // GC only
1807 " (the bug occurs with garbage collection enabled).",
1808
1809 "Code is compiled without garbage collection.", // No GC.
1810
1811 "Code is compiled for use with and without garbage collection (GC)."
1812 " The bug occurs with GC enabled.", // Hybrid, with GC.
1813
1814 "Code is compiled for use with and without garbage collection (GC)."
1815 " The bug occurs in non-GC mode." // Hyrbird, without GC/
1816};
1817
1818std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
1819 CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
1820
1821 switch (TF.getLangOptions().getGCMode()) {
1822 default:
1823 assert(false);
Ted Kremenek31593ac2008-05-01 04:02:04 +00001824
1825 case LangOptions::GCOnly:
1826 assert (TF.isGCEnabled());
1827 return std::make_pair(&Msgs[0], &Msgs[0]+1);
Ted Kremenek072192b2008-04-30 23:47:44 +00001828
1829 case LangOptions::NonGC:
1830 assert (!TF.isGCEnabled());
Ted Kremenek072192b2008-04-30 23:47:44 +00001831 return std::make_pair(&Msgs[1], &Msgs[1]+1);
1832
1833 case LangOptions::HybridGC:
1834 if (TF.isGCEnabled())
1835 return std::make_pair(&Msgs[2], &Msgs[2]+1);
1836 else
1837 return std::make_pair(&Msgs[3], &Msgs[3]+1);
1838 }
1839}
1840
Ted Kremenek8dd56462008-04-18 03:39:05 +00001841PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
1842 ExplodedNode<ValueState>* PrevN,
1843 ExplodedGraph<ValueState>& G,
1844 BugReporter& BR) {
1845
1846 // Check if the type state has changed.
1847
1848 ValueState* PrevSt = PrevN->getState();
1849 ValueState* CurrSt = N->getState();
1850
1851 CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
1852 CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
1853
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001854 CFRefCount::RefBindings::TreeTy* PrevT = PrevB.SlimFind(Sym);
1855 CFRefCount::RefBindings::TreeTy* CurrT = CurrB.SlimFind(Sym);
Ted Kremenek8dd56462008-04-18 03:39:05 +00001856
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001857 if (!CurrT)
1858 return NULL;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001859
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001860 const char* Msg = NULL;
1861 RefVal CurrV = CurrB.SlimFind(Sym)->getValue().second;
Ted Kremenekce48e002008-05-05 17:53:17 +00001862
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001863 if (!PrevT) {
1864
Ted Kremenekce48e002008-05-05 17:53:17 +00001865 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1866
1867 if (CurrV.isOwned()) {
1868
1869 if (isa<CallExpr>(S))
1870 Msg = "Function call returns an object with a +1 retain count"
1871 " (owning reference).";
1872 else {
1873 assert (isa<ObjCMessageExpr>(S));
1874 Msg = "Method returns an object with a +1 retain count"
1875 " (owning reference).";
1876 }
1877 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001878 else {
1879 assert (CurrV.isNotOwned());
Ted Kremenekce48e002008-05-05 17:53:17 +00001880
1881 if (isa<CallExpr>(S))
1882 Msg = "Function call returns an object with a +0 retain count"
1883 " (non-owning reference).";
1884 else {
1885 assert (isa<ObjCMessageExpr>(S));
1886 Msg = "Method returns an object with a +0 retain count"
1887 " (non-owning reference).";
1888 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001889 }
Ted Kremenekce48e002008-05-05 17:53:17 +00001890
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001891 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1892 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1893
1894 if (Expr* Exp = dyn_cast<Expr>(S))
1895 P->addRange(Exp->getSourceRange());
1896
1897 return P;
1898 }
1899
1900 // Determine if the typestate has changed.
1901
1902 RefVal PrevV = PrevB.SlimFind(Sym)->getValue().second;
1903
1904 if (PrevV == CurrV)
1905 return NULL;
1906
1907 // The typestate has changed.
1908
1909 std::ostringstream os;
1910
1911 switch (CurrV.getKind()) {
1912 case RefVal::Owned:
1913 case RefVal::NotOwned:
1914 assert (PrevV.getKind() == CurrV.getKind());
1915
1916 if (PrevV.getCount() > CurrV.getCount())
1917 os << "Reference count decremented.";
1918 else
1919 os << "Reference count incremented.";
1920
Ted Kremenekce48e002008-05-05 17:53:17 +00001921 if (unsigned Count = GetCount(CurrV)) {
1922
1923 os << " Object has +" << Count;
Ted Kremenek79c140b2008-04-18 05:32:44 +00001924
Ted Kremenekce48e002008-05-05 17:53:17 +00001925 if (Count > 1)
1926 os << " retain counts.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00001927 else
Ted Kremenekce48e002008-05-05 17:53:17 +00001928 os << " retain count.";
Ted Kremenek79c140b2008-04-18 05:32:44 +00001929 }
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001930
1931 Msg = os.str().c_str();
1932
1933 break;
1934
1935 case RefVal::Released:
1936 Msg = "Object released.";
1937 break;
1938
1939 case RefVal::ReturnedOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00001940 Msg = "Object returned to caller as owning reference (single retain count"
1941 " transferred to caller).";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001942 break;
1943
1944 case RefVal::ReturnedNotOwned:
Ted Kremenekce48e002008-05-05 17:53:17 +00001945 Msg = "Object returned to caller with a +0 (non-owning) retain count.";
Ted Kremenek2cf943a2008-04-18 04:55:01 +00001946 break;
1947
1948 default:
1949 return NULL;
1950 }
1951
1952 Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
1953 FullSourceLoc Pos(S->getLocStart(), BR.getContext().getSourceManager());
1954 PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, Msg);
1955
1956 // Add the range by scanning the children of the statement for any bindings
1957 // to Sym.
1958
1959 ValueStateManager& VSM = BR.getEngine().getStateManager();
1960
1961 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1962 if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) {
1963 RVal X = VSM.GetRVal(CurrSt, Exp);
1964
1965 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&X))
1966 if (SV->getSymbol() == Sym) {
1967 P->addRange(Exp->getSourceRange()); break;
1968 }
1969 }
1970
1971 return P;
Ted Kremenek8dd56462008-04-18 03:39:05 +00001972}
1973
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00001974
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001975PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
Ted Kremeneke28565b2008-05-05 18:50:19 +00001976 ExplodedNode<ValueState>* EndN) {
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001977
1978 if (!getBugType().isLeak())
Ted Kremeneke28565b2008-05-05 18:50:19 +00001979 return RangedBugReport::getEndPath(BR, EndN);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001980
Ted Kremenekce48e002008-05-05 17:53:17 +00001981 typedef CFRefCount::RefBindings RefBindings;
1982
1983 // Get the retain count.
1984 unsigned long RetCount = 0;
1985
1986 {
Ted Kremeneke28565b2008-05-05 18:50:19 +00001987 ValueState* St = EndN->getState();
Ted Kremenekce48e002008-05-05 17:53:17 +00001988 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
1989 RefBindings::TreeTy* T = B.SlimFind(Sym);
1990 assert (T);
1991 RetCount = GetCount(T->getValue().second);
1992 }
1993
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001994 // We are a leak. Walk up the graph to get to the first node where the
1995 // symbol appeared.
1996
Ted Kremeneke28565b2008-05-05 18:50:19 +00001997 ExplodedNode<ValueState>* N = EndN;
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00001998 ExplodedNode<ValueState>* Last = N;
Ted Kremeneke28565b2008-05-05 18:50:19 +00001999
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002000 // Find the first node that referred to the tracked symbol. We also
2001 // try and find the first VarDecl the value was stored to.
2002
2003 VarDecl* FirstDecl = 0;
Ted Kremeneke28565b2008-05-05 18:50:19 +00002004
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002005 while (N) {
2006 ValueState* St = N->getState();
2007 RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002008 RefBindings::TreeTy* T = B.SlimFind(Sym);
2009
2010 if (!T)
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002011 break;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002012
2013 VarDecl* VD = 0;
2014
2015 // Determine if there is an LVal binding to the symbol.
2016 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
2017 if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
2018 || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
2019 continue;
2020
2021 if (VD) { // Multiple decls map to this symbol.
2022 VD = 0;
2023 break;
2024 }
2025
2026 VD = I->first;
2027 }
2028
2029 if (VD) FirstDecl = VD;
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002030
2031 Last = N;
2032 N = N->pred_empty() ? NULL : *(N->pred_begin());
2033 }
2034
Ted Kremeneke28565b2008-05-05 18:50:19 +00002035 // Get the allocate site.
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002036
2037 assert (Last);
2038 Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
2039
Ted Kremeneke28565b2008-05-05 18:50:19 +00002040 SourceManager& SMgr = BR.getContext().getSourceManager();
2041 unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart());
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002042
Ted Kremeneke28565b2008-05-05 18:50:19 +00002043 // Get the leak site. We may have multiple ExplodedNodes (one with the
2044 // leak) that occur on the same line number; if the node with the leak
2045 // has any immediate predecessor nodes with the same line number, find
2046 // any transitive-successors that have a different statement and use that
2047 // line number instead. This avoids emiting a diagnostic like:
2048 //
2049 // // 'y' is leaked.
2050 // int x = foo(y);
2051 //
2052 // instead we want:
2053 //
2054 // int x = foo(y);
2055 // // 'y' is leaked.
2056
2057 Stmt* S = getStmt(BR); // This is the statement where the leak occured.
2058 assert (S);
2059 unsigned EndLine = SMgr.getLogicalLineNumber(S->getLocStart());
2060
2061 // Look in the *trimmed* graph at the immediate predecessor of EndN. Does
2062 // it occur on the same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002063
2064 PathDiagnosticPiece::DisplayHint Hint = PathDiagnosticPiece::Above;
Ted Kremeneke28565b2008-05-05 18:50:19 +00002065
2066 assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002067 ExplodedNode<ValueState> *Pred = *(EndN->pred_begin());
2068 ProgramPoint PredPos = Pred->getLocation();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002069
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002070 if (PostStmt* PredPS = dyn_cast<PostStmt>(&PredPos)) {
Ted Kremeneke28565b2008-05-05 18:50:19 +00002071
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002072 Stmt* SPred = PredPS->getStmt();
Ted Kremeneke28565b2008-05-05 18:50:19 +00002073
2074 // Predecessor at same line?
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002075 if (SMgr.getLogicalLineNumber(SPred->getLocStart()) != EndLine) {
2076 Hint = PathDiagnosticPiece::Below;
2077 S = SPred;
2078 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002079 }
Ted Kremeneke28565b2008-05-05 18:50:19 +00002080
2081 // Generate the diagnostic.
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002082 FullSourceLoc L( S->getLocStart(), SMgr);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002083 std::ostringstream os;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002084
Ted Kremeneke28565b2008-05-05 18:50:19 +00002085 os << "Object allocated on line " << AllocLine;
Ted Kremeneke92c1b22008-05-02 20:53:50 +00002086
2087 if (FirstDecl)
2088 os << " and stored into '" << FirstDecl->getName() << '\'';
2089
Ted Kremenekce48e002008-05-05 17:53:17 +00002090 os << " is no longer referenced after this point and has a retain count of +"
2091 << RetCount << " (object leaked).";
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002092
Ted Kremeneka22cc2f2008-05-06 23:07:13 +00002093 return new PathDiagnosticPiece(L, os.str(), Hint);
Ted Kremenekc9fa2f72008-05-01 23:13:35 +00002094}
2095
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002096void UseAfterRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002097
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002098 for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
2099 E = TF.use_after_end(); I != E; ++I) {
2100
Ted Kremenek8dd56462008-04-18 03:39:05 +00002101 CFRefReport report(*this, I->first, I->second.second);
2102 report.addRange(I->second.first->getSourceRange());
Ted Kremenek75840e12008-04-18 01:56:37 +00002103 BR.EmitWarning(report);
Ted Kremenekfa34b332008-04-09 01:10:13 +00002104 }
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002105}
2106
2107void BadRelease::EmitWarnings(BugReporter& BR) {
Ted Kremenekfa34b332008-04-09 01:10:13 +00002108
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002109 for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
2110 E = TF.bad_release_end(); I != E; ++I) {
2111
Ted Kremenek8dd56462008-04-18 03:39:05 +00002112 CFRefReport report(*this, I->first, I->second.second);
2113 report.addRange(I->second.first->getSourceRange());
2114 BR.EmitWarning(report);
Ted Kremenek05cbe1a2008-04-09 23:49:11 +00002115 }
2116}
Ted Kremenekfa34b332008-04-09 01:10:13 +00002117
Ted Kremenek989d5192008-04-17 23:43:50 +00002118void Leak::EmitWarnings(BugReporter& BR) {
2119
2120 for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
2121 E = TF.leaks_end(); I != E; ++I) {
2122
Ted Kremenek8dd56462008-04-18 03:39:05 +00002123 std::vector<SymbolID>& SymV = *(I->second);
2124 unsigned n = SymV.size();
2125
2126 for (unsigned i = 0; i < n; ++i) {
2127 CFRefReport report(*this, I->first, SymV[i]);
2128 BR.EmitWarning(report);
2129 }
Ted Kremenek989d5192008-04-17 23:43:50 +00002130 }
2131}
2132
Ted Kremenekcb612922008-04-18 19:23:43 +00002133void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
2134 for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
2135 I!=E; ++I)
2136 Nodes.push_back(I->first);
2137}
2138
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002139//===----------------------------------------------------------------------===//
Ted Kremenekd71ed262008-04-10 22:16:52 +00002140// Transfer function creation for external clients.
Ted Kremenek6b3a0f72008-03-11 06:39:11 +00002141//===----------------------------------------------------------------------===//
2142
Ted Kremenek072192b2008-04-30 23:47:44 +00002143GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Ted Kremenek9f741612008-05-02 18:01:49 +00002144 bool StandardWarnings,
Ted Kremenek072192b2008-04-30 23:47:44 +00002145 const LangOptions& lopts) {
Ted Kremenek9f741612008-05-02 18:01:49 +00002146 return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
Ted Kremenek3ea0b6a2008-04-10 22:58:08 +00002147}