blob: 94ffb3f15252de308fbcd68017a0b1045fddf456 [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 {
Ted Kremenekabb042f2008-12-13 19:24:37 +0000110 QualType T = getArrayRegion()->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 {
Zhongxing Xu56af9772008-11-13 07:30:58 +0000117 PointerType* PtrT = cast<PointerType>(T.getTypePtr());
118 QualType PTy = PtrT->getPointeeType();
119 return C.getCanonicalType(PTy);
120 }
Zhongxing Xu27b57062008-10-27 13:17:02 +0000121}
122
Ted Kremenek9e240492008-10-04 05:50:14 +0000123//===----------------------------------------------------------------------===//
124// Region pretty-printing.
125//===----------------------------------------------------------------------===//
126
127std::string MemRegion::getString() const {
128 std::string s;
129 llvm::raw_string_ostream os(s);
130 print(os);
131 return os.str();
132}
133
134void MemRegion::print(llvm::raw_ostream& os) const {
135 os << "<Unknown Region>";
136}
137
Ted Kremenek7090ae12008-11-02 00:34:33 +0000138void AllocaRegion::print(llvm::raw_ostream& os) const {
139 os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
140}
141
Ted Kremenek9e240492008-10-04 05:50:14 +0000142void VarRegion::print(llvm::raw_ostream& os) const {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000143 os << cast<VarDecl>(D)->getNameAsString();
Ted Kremenek9e240492008-10-04 05:50:14 +0000144}
145
Ted Kremenek993f1c72008-10-17 20:28:54 +0000146void SymbolicRegion::print(llvm::raw_ostream& os) const {
Ted Kremenek562731e2008-12-05 02:45:20 +0000147 os << "SymRegion-";
148 sym.print(os);
Ted Kremenek993f1c72008-10-17 20:28:54 +0000149}
150
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000151void FieldRegion::print(llvm::raw_ostream& os) const {
152 superRegion->print(os);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000153 os << "->" << getDecl()->getNameAsString();
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000154}
155
Zhongxing Xub21ff772008-10-24 06:30:07 +0000156void ElementRegion::print(llvm::raw_ostream& os) const {
157 superRegion->print(os);
158 os << '['; Index.print(os); os << ']';
159}
160
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000161void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
162 // FIXME: More elaborate pretty-printing.
163 os << "{ " << (void*) CL << " }";
164}
165
Zhongxing Xucc128b32008-11-10 13:05:26 +0000166void StringRegion::print(llvm::raw_ostream& os) const {
Zhongxing Xud2f016f2008-11-11 01:36:32 +0000167 if (Str->isWide()) os << 'L';
168 os << '"';
169
170 // FIXME: this doesn't print wstrings right.
171 for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
172 switch (Str->getStrData()[i]) {
173 default: os << Str->getStrData()[i]; break;
174 // Handle some common ones to make dumps prettier.
175 case '\\': os << "\\\\"; break;
176 case '"': os << "\\\""; break;
177 case '\n': os << "\\n"; break;
178 case '\t': os << "\\t"; break;
179 case '\a': os << "\\a"; break;
180 case '\b': os << "\\b"; break;
181 }
182 }
183 os << '"';
Zhongxing Xucc128b32008-11-10 13:05:26 +0000184}
185
Ted Kremenek9e240492008-10-04 05:50:14 +0000186//===----------------------------------------------------------------------===//
187// MemRegionManager methods.
188//===----------------------------------------------------------------------===//
189
190MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
191
192 if (!region) {
193 region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
194 new (region) MemSpaceRegion();
195 }
196
197 return region;
198}
199
200MemSpaceRegion* MemRegionManager::getStackRegion() {
201 return LazyAllocate(stack);
202}
203
204MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
205 return LazyAllocate(globals);
206}
207
208MemSpaceRegion* MemRegionManager::getHeapRegion() {
209 return LazyAllocate(heap);
210}
211
Zhongxing Xu17892752008-10-08 02:50:44 +0000212MemSpaceRegion* MemRegionManager::getUnknownRegion() {
213 return LazyAllocate(unknown);
214}
215
Zhongxing Xue9f4e542008-10-25 14:13:41 +0000216StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
217 llvm::FoldingSetNodeID ID;
218 MemSpaceRegion* GlobalsR = getGlobalsRegion();
219
220 StringRegion::ProfileRegion(ID, Str, GlobalsR);
221
222 void* InsertPos;
223 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
224 StringRegion* R = cast_or_null<StringRegion>(data);
225
226 if (!R) {
227 R = (StringRegion*) A.Allocate<StringRegion>();
228 new (R) StringRegion(Str, GlobalsR);
229 Regions.InsertNode(R, InsertPos);
230 }
231
232 return R;
233}
234
Ted Kremenek9a1f03a2008-10-27 21:01:26 +0000235VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
236
237 const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
238 : getGlobalsRegion();
239
Ted Kremenek9e240492008-10-04 05:50:14 +0000240 llvm::FoldingSetNodeID ID;
241 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
242
243 void* InsertPos;
244 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
245 VarRegion* R = cast_or_null<VarRegion>(data);
246
247 if (!R) {
248 R = (VarRegion*) A.Allocate<VarRegion>();
249 new (R) VarRegion(d, superRegion);
250 Regions.InsertNode(R, InsertPos);
251 }
252
253 return R;
254}
255
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000256CompoundLiteralRegion*
257MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
258 // Is this compound literal allocated on the stack or is part of the
259 // global constant pool?
260 const MemRegion* superRegion = CL->isFileScope() ?
261 getGlobalsRegion() : getStackRegion();
262
263 // Profile the compound literal.
264 llvm::FoldingSetNodeID ID;
265 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
266
267 void* InsertPos;
268 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
269 CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
270
271 if (!R) {
272 R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
273 new (R) CompoundLiteralRegion(CL, superRegion);
274 Regions.InsertNode(R, InsertPos);
275 }
276
277 return R;
278}
279
Ted Kremenekabb042f2008-12-13 19:24:37 +0000280ElementRegion*
281MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){
282
Zhongxing Xu511191c2008-10-21 05:27:10 +0000283 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}