blob: 1e580a8cd3cb188a907c940bc924792d61bbeac9 [file] [log] [blame]
Ted Kremenek9e240492008-10-04 05:50:14 +00001//== MemRegion.cpp - Abstract memory regions for static analysis --*- C++ -*--//
2//
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//
10// This file defines MemRegion and its subclasses. MemRegion defines a
11// partially-typed abstraction of memory useful for path-sensitive dataflow
12// analyses.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Support/raw_ostream.h"
17#include "clang/Analysis/PathSensitive/MemRegion.h"
18
19using namespace clang;
20
21
22MemRegion::~MemRegion() {}
23
24void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
25 ID.AddInteger((unsigned)getKind());
26}
27
Zhongxing Xue9f4e542008-10-25 14:13:41 +000028void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
29 const StringLiteral* Str,
30 const MemRegion* superRegion) {
31 ID.AddInteger((unsigned) StringRegionKind);
32 ID.AddPointer(Str);
33 ID.AddPointer(superRegion);
34}
35
Ted Kremenek7090ae12008-11-02 00:34:33 +000036void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
37 const Expr* Ex, unsigned cnt) {
38 ID.AddInteger((unsigned) AllocaRegionKind);
39 ID.AddPointer(Ex);
40 ID.AddInteger(cnt);
41}
42
43void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
44 ProfileRegion(ID, Ex, Cnt);
45}
46
Zhongxing Xudc0a25d2008-11-16 04:07:26 +000047void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
48 const MemRegion* superRegion) {
49 ID.AddInteger((unsigned) AnonTypedRegionKind);
50 ID.Add(T);
51 ID.AddPointer(superRegion);
52}
53
Zhongxing Xu817c67d2008-11-03 04:12:24 +000054QualType AnonPointeeRegion::getType(ASTContext& C) const {
Zhongxing Xuc5458622008-12-11 09:08:46 +000055 return C.getCanonicalType(T);
Ted Kremenek9e240492008-10-04 05:50:14 +000056}
57
Zhongxing Xu17892752008-10-08 02:50:44 +000058void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
Zhongxing Xuc5458622008-12-11 09:08:46 +000059 SymbolRef Sym,
Zhongxing Xu17892752008-10-08 02:50:44 +000060 const MemRegion* superRegion) {
61 ID.AddInteger((unsigned) AnonPointeeRegionKind);
Zhongxing Xuc5458622008-12-11 09:08:46 +000062 Sym.Profile(ID);
Zhongxing Xu17892752008-10-08 02:50:44 +000063 ID.AddPointer(superRegion);
64}
65
Ted Kremenek329d6fd2008-10-27 20:57:58 +000066void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
67 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
68}
69
70void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
71 const CompoundLiteralExpr* CL,
72 const MemRegion* superRegion) {
73 ID.AddInteger((unsigned) CompoundLiteralRegionKind);
74 ID.AddPointer(CL);
75 ID.AddPointer(superRegion);
76}
77
Ted Kremenek9e240492008-10-04 05:50:14 +000078void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
79 const MemRegion* superRegion, Kind k) {
80 ID.AddInteger((unsigned) k);
81 ID.AddPointer(D);
82 ID.AddPointer(superRegion);
83}
84
85void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
86 DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
87}
88
Ted Kremenek2dabd432008-12-05 02:27:51 +000089void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym) {
Ted Kremenek993f1c72008-10-17 20:28:54 +000090 ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
Ted Kremenek6d0e2d22008-12-05 02:39:38 +000091 ID.Add(sym);
Ted Kremenek993f1c72008-10-17 20:28:54 +000092}
93
94void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
95 SymbolicRegion::ProfileRegion(ID, sym);
96}
97
Zhongxing Xu511191c2008-10-21 05:27:10 +000098void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SVal Idx,
99 const MemRegion* superRegion) {
100 ID.AddInteger(MemRegion::ElementRegionKind);
101 ID.AddPointer(superRegion);
102 Idx.Profile(ID);
103}
104
105void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
106 ElementRegion::ProfileRegion(ID, Index, superRegion);
107}
Zhongxing Xu27b57062008-10-27 13:17:02 +0000108
109QualType ElementRegion::getType(ASTContext& C) const {
110 QualType T = cast<TypedRegion>(superRegion)->getType(C);
Zhongxing Xu56af9772008-11-13 07:30:58 +0000111
112 if (isa<ArrayType>(T.getTypePtr())) {
113 ArrayType* AT = cast<ArrayType>(T.getTypePtr());
114 return AT->getElementType();
115 }
Ted Kremenek34265e72008-11-17 22:55:12 +0000116 else {
117 assert (isa<AnonTypedRegion>(superRegion));
Zhongxing Xu56af9772008-11-13 07:30:58 +0000118 PointerType* PtrT = cast<PointerType>(T.getTypePtr());
119 QualType PTy = PtrT->getPointeeType();
120 return C.getCanonicalType(PTy);
121 }
Zhongxing Xu27b57062008-10-27 13:17:02 +0000122}
123
Ted Kremenek9e240492008-10-04 05:50:14 +0000124//===----------------------------------------------------------------------===//
125// Region pretty-printing.
126//===----------------------------------------------------------------------===//
127
128std::string MemRegion::getString() const {
129 std::string s;
130 llvm::raw_string_ostream os(s);
131 print(os);
132 return os.str();
133}
134
135void MemRegion::print(llvm::raw_ostream& os) const {
136 os << "<Unknown Region>";
137}
138
Ted Kremenek7090ae12008-11-02 00:34:33 +0000139void AllocaRegion::print(llvm::raw_ostream& os) const {
140 os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
141}
142
Ted Kremenek9e240492008-10-04 05:50:14 +0000143void VarRegion::print(llvm::raw_ostream& os) const {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000144 os << cast<VarDecl>(D)->getNameAsString();
Ted Kremenek9e240492008-10-04 05:50:14 +0000145}
146
Ted Kremenek993f1c72008-10-17 20:28:54 +0000147void SymbolicRegion::print(llvm::raw_ostream& os) const {
Ted Kremenek562731e2008-12-05 02:45:20 +0000148 os << "SymRegion-";
149 sym.print(os);
Ted Kremenek993f1c72008-10-17 20:28:54 +0000150}
151
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000152void FieldRegion::print(llvm::raw_ostream& os) const {
153 superRegion->print(os);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000154 os << "->" << getDecl()->getNameAsString();
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000155}
156
Zhongxing Xub21ff772008-10-24 06:30:07 +0000157void ElementRegion::print(llvm::raw_ostream& os) const {
158 superRegion->print(os);
159 os << '['; Index.print(os); os << ']';
160}
161
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000162void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
163 // FIXME: More elaborate pretty-printing.
164 os << "{ " << (void*) CL << " }";
165}
166
Zhongxing Xucc128b32008-11-10 13:05:26 +0000167void StringRegion::print(llvm::raw_ostream& os) const {
Zhongxing Xud2f016f2008-11-11 01:36:32 +0000168 if (Str->isWide()) os << 'L';
169 os << '"';
170
171 // FIXME: this doesn't print wstrings right.
172 for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
173 switch (Str->getStrData()[i]) {
174 default: os << Str->getStrData()[i]; break;
175 // Handle some common ones to make dumps prettier.
176 case '\\': os << "\\\\"; break;
177 case '"': os << "\\\""; break;
178 case '\n': os << "\\n"; break;
179 case '\t': os << "\\t"; break;
180 case '\a': os << "\\a"; break;
181 case '\b': os << "\\b"; break;
182 }
183 }
184 os << '"';
Zhongxing Xucc128b32008-11-10 13:05:26 +0000185}
186
Ted Kremenek9e240492008-10-04 05:50:14 +0000187//===----------------------------------------------------------------------===//
188// MemRegionManager methods.
189//===----------------------------------------------------------------------===//
190
191MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
192
193 if (!region) {
194 region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
195 new (region) MemSpaceRegion();
196 }
197
198 return region;
199}
200
201MemSpaceRegion* MemRegionManager::getStackRegion() {
202 return LazyAllocate(stack);
203}
204
205MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
206 return LazyAllocate(globals);
207}
208
209MemSpaceRegion* MemRegionManager::getHeapRegion() {
210 return LazyAllocate(heap);
211}
212
Zhongxing Xu17892752008-10-08 02:50:44 +0000213MemSpaceRegion* MemRegionManager::getUnknownRegion() {
214 return LazyAllocate(unknown);
215}
216
Zhongxing Xue9f4e542008-10-25 14:13:41 +0000217StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
218 llvm::FoldingSetNodeID ID;
219 MemSpaceRegion* GlobalsR = getGlobalsRegion();
220
221 StringRegion::ProfileRegion(ID, Str, GlobalsR);
222
223 void* InsertPos;
224 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
225 StringRegion* R = cast_or_null<StringRegion>(data);
226
227 if (!R) {
228 R = (StringRegion*) A.Allocate<StringRegion>();
229 new (R) StringRegion(Str, GlobalsR);
230 Regions.InsertNode(R, InsertPos);
231 }
232
233 return R;
234}
235
Ted Kremenek9a1f03a2008-10-27 21:01:26 +0000236VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
237
238 const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
239 : getGlobalsRegion();
240
Ted Kremenek9e240492008-10-04 05:50:14 +0000241 llvm::FoldingSetNodeID ID;
242 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
243
244 void* InsertPos;
245 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
246 VarRegion* R = cast_or_null<VarRegion>(data);
247
248 if (!R) {
249 R = (VarRegion*) A.Allocate<VarRegion>();
250 new (R) VarRegion(d, superRegion);
251 Regions.InsertNode(R, InsertPos);
252 }
253
254 return R;
255}
256
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000257CompoundLiteralRegion*
258MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
259 // Is this compound literal allocated on the stack or is part of the
260 // global constant pool?
261 const MemRegion* superRegion = CL->isFileScope() ?
262 getGlobalsRegion() : getStackRegion();
263
264 // Profile the compound literal.
265 llvm::FoldingSetNodeID ID;
266 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
267
268 void* InsertPos;
269 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
270 CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
271
272 if (!R) {
273 R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
274 new (R) CompoundLiteralRegion(CL, superRegion);
275 Regions.InsertNode(R, InsertPos);
276 }
277
278 return R;
279}
280
Zhongxing Xu511191c2008-10-21 05:27:10 +0000281ElementRegion* MemRegionManager::getElementRegion(SVal Idx,
282 const MemRegion* superRegion){
283 llvm::FoldingSetNodeID ID;
284 ElementRegion::ProfileRegion(ID, Idx, superRegion);
285
286 void* InsertPos;
287 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
288 ElementRegion* R = cast_or_null<ElementRegion>(data);
289
290 if (!R) {
291 R = (ElementRegion*) A.Allocate<ElementRegion>();
292 new (R) ElementRegion(Idx, superRegion);
293 Regions.InsertNode(R, InsertPos);
294 }
295
296 return R;
297}
298
Ted Kremenek993f1c72008-10-17 20:28:54 +0000299/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
Ted Kremenek2dabd432008-12-05 02:27:51 +0000300SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym) {
Ted Kremenek993f1c72008-10-17 20:28:54 +0000301
302 llvm::FoldingSetNodeID ID;
303 SymbolicRegion::ProfileRegion(ID, sym);
304
305 void* InsertPos;
306 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
307 SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
308
309 if (!R) {
310 R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
311 new (R) SymbolicRegion(sym);
312 Regions.InsertNode(R, InsertPos);
313 }
314
315 return R;
316}
317
Ted Kremenek9e240492008-10-04 05:50:14 +0000318FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
Ted Kremenek993f1c72008-10-17 20:28:54 +0000319 const MemRegion* superRegion) {
Ted Kremenek9e240492008-10-04 05:50:14 +0000320 llvm::FoldingSetNodeID ID;
321 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
322
323 void* InsertPos;
324 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
325 FieldRegion* R = cast_or_null<FieldRegion>(data);
326
327 if (!R) {
328 R = (FieldRegion*) A.Allocate<FieldRegion>();
329 new (R) FieldRegion(d, superRegion);
330 Regions.InsertNode(R, InsertPos);
331 }
332
333 return R;
334}
335
Ted Kremenek993f1c72008-10-17 20:28:54 +0000336ObjCIvarRegion*
337MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
338 const MemRegion* superRegion) {
Ted Kremenek9e240492008-10-04 05:50:14 +0000339 llvm::FoldingSetNodeID ID;
340 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
341
342 void* InsertPos;
343 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
344 ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
345
346 if (!R) {
Zhongxing Xu722c2882008-10-06 03:03:33 +0000347 R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
348 new (R) ObjCIvarRegion(d, superRegion);
Ted Kremenek9e240492008-10-04 05:50:14 +0000349 Regions.InsertNode(R, InsertPos);
350 }
351
352 return R;
353}
354
Ted Kremeneka7f1b9e2008-10-24 20:30:08 +0000355ObjCObjectRegion*
356MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
357 const MemRegion* superRegion) {
358 llvm::FoldingSetNodeID ID;
359 DeclRegion::ProfileRegion(ID, d, superRegion,
360 MemRegion::ObjCObjectRegionKind);
361
362 void* InsertPos;
363 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
364 ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
365
366 if (!R) {
367 R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
368 new (R) ObjCObjectRegion(d, superRegion);
369 Regions.InsertNode(R, InsertPos);
370 }
371
372 return R;
373}
374
Zhongxing Xudc0a25d2008-11-16 04:07:26 +0000375AnonTypedRegion*
376MemRegionManager::getAnonTypedRegion(QualType t, const MemRegion* superRegion) {
377 llvm::FoldingSetNodeID ID;
378 AnonTypedRegion::ProfileRegion(ID, t, superRegion);
379
380 void* InsertPos;
381 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
382 AnonTypedRegion* R = cast_or_null<AnonTypedRegion>(data);
383
384 if (!R) {
385 R = (AnonTypedRegion*) A.Allocate<AnonTypedRegion>();
386 new (R) AnonTypedRegion(t, superRegion);
387 Regions.InsertNode(R, InsertPos);
388 }
389
390 return R;
391}
Ted Kremeneka7f1b9e2008-10-24 20:30:08 +0000392
Zhongxing Xuc5458622008-12-11 09:08:46 +0000393AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(SymbolRef Sym,
394 QualType T) {
Zhongxing Xu17892752008-10-08 02:50:44 +0000395 llvm::FoldingSetNodeID ID;
Zhongxing Xu17892752008-10-08 02:50:44 +0000396 MemRegion* superRegion = getUnknownRegion();
397
Zhongxing Xuc5458622008-12-11 09:08:46 +0000398 AnonPointeeRegion::ProfileRegion(ID, Sym, superRegion);
Zhongxing Xu17892752008-10-08 02:50:44 +0000399
400 void* InsertPos;
401 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
402 AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data);
403
404 if (!R) {
405 R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>();
Zhongxing Xuc5458622008-12-11 09:08:46 +0000406 new (R) AnonPointeeRegion(Sym, T, superRegion);
Zhongxing Xu17892752008-10-08 02:50:44 +0000407 Regions.InsertNode(R, InsertPos);
408 }
409
410 return R;
411}
412
Ted Kremenek7090ae12008-11-02 00:34:33 +0000413AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
414 llvm::FoldingSetNodeID ID;
415 AllocaRegion::ProfileRegion(ID, E, cnt);
416
417 void* InsertPos;
418 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
419 AllocaRegion* R = cast_or_null<AllocaRegion>(data);
420
421 if (!R) {
422 R = (AllocaRegion*) A.Allocate<AllocaRegion>();
423 new (R) AllocaRegion(E, cnt, getStackRegion());
424 Regions.InsertNode(R, InsertPos);
425 }
426
427 return R;
428}
429
Ted Kremenek9e240492008-10-04 05:50:14 +0000430bool MemRegionManager::hasStackStorage(const MemRegion* R) {
Ted Kremenek993f1c72008-10-17 20:28:54 +0000431
432 // Only subregions can have stack storage.
Ted Kremenek7090ae12008-11-02 00:34:33 +0000433 const SubRegion* SR = dyn_cast<SubRegion>(R);
434
Ted Kremenek993f1c72008-10-17 20:28:54 +0000435 if (!SR)
436 return false;
Ted Kremenek7090ae12008-11-02 00:34:33 +0000437
Ted Kremenek9e240492008-10-04 05:50:14 +0000438 MemSpaceRegion* S = getStackRegion();
439
Ted Kremenek993f1c72008-10-17 20:28:54 +0000440 while (SR) {
441 R = SR->getSuperRegion();
442 if (R == S)
443 return true;
444
445 SR = dyn_cast<SubRegion>(R);
Ted Kremenek9e240492008-10-04 05:50:14 +0000446 }
447
448 return false;
449}