blob: a292d98e60525b6c5b9137e07e881a7a74e97ff9 [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 Xu817c67d2008-11-03 04:12:24 +000047QualType AnonPointeeRegion::getType(ASTContext& C) const {
48 QualType T = C.getCanonicalType(Pointer->getType());
49 PointerType* PTy = cast<PointerType>(T.getTypePtr());
50
51 QualType PointeeTy = C.getCanonicalType(PTy->getPointeeType());
52 return PointeeTy;
Ted Kremenek9e240492008-10-04 05:50:14 +000053}
54
Zhongxing Xu17892752008-10-08 02:50:44 +000055void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
Zhongxing Xu817c67d2008-11-03 04:12:24 +000056 const VarDecl* VD,
Zhongxing Xu17892752008-10-08 02:50:44 +000057 const MemRegion* superRegion) {
58 ID.AddInteger((unsigned) AnonPointeeRegionKind);
Zhongxing Xu17892752008-10-08 02:50:44 +000059 ID.AddPointer(VD);
60 ID.AddPointer(superRegion);
61}
62
Ted Kremenek329d6fd2008-10-27 20:57:58 +000063void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
64 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
65}
66
67void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
68 const CompoundLiteralExpr* CL,
69 const MemRegion* superRegion) {
70 ID.AddInteger((unsigned) CompoundLiteralRegionKind);
71 ID.AddPointer(CL);
72 ID.AddPointer(superRegion);
73}
74
Ted Kremenek9e240492008-10-04 05:50:14 +000075void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
76 const MemRegion* superRegion, Kind k) {
77 ID.AddInteger((unsigned) k);
78 ID.AddPointer(D);
79 ID.AddPointer(superRegion);
80}
81
82void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
83 DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
84}
85
Ted Kremenek993f1c72008-10-17 20:28:54 +000086void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolID sym) {
87 ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
88 ID.AddInteger(sym.getNumber());
89}
90
91void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
92 SymbolicRegion::ProfileRegion(ID, sym);
93}
94
Zhongxing Xu511191c2008-10-21 05:27:10 +000095void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SVal Idx,
96 const MemRegion* superRegion) {
97 ID.AddInteger(MemRegion::ElementRegionKind);
98 ID.AddPointer(superRegion);
99 Idx.Profile(ID);
100}
101
102void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
103 ElementRegion::ProfileRegion(ID, Index, superRegion);
104}
Zhongxing Xu27b57062008-10-27 13:17:02 +0000105
106QualType ElementRegion::getType(ASTContext& C) const {
107 QualType T = cast<TypedRegion>(superRegion)->getType(C);
Zhongxing Xu56af9772008-11-13 07:30:58 +0000108
109 if (isa<ArrayType>(T.getTypePtr())) {
110 ArrayType* AT = cast<ArrayType>(T.getTypePtr());
111 return AT->getElementType();
112 }
113 else if (isa<AllocaRegion>(superRegion)) {
114 PointerType* PtrT = cast<PointerType>(T.getTypePtr());
115 QualType PTy = PtrT->getPointeeType();
116 return C.getCanonicalType(PTy);
117 }
118 else
119 assert(0 && "SuperRegion type unsupported.");
Zhongxing Xu27b57062008-10-27 13:17:02 +0000120}
121
Ted Kremenek9e240492008-10-04 05:50:14 +0000122//===----------------------------------------------------------------------===//
123// Region pretty-printing.
124//===----------------------------------------------------------------------===//
125
126std::string MemRegion::getString() const {
127 std::string s;
128 llvm::raw_string_ostream os(s);
129 print(os);
130 return os.str();
131}
132
133void MemRegion::print(llvm::raw_ostream& os) const {
134 os << "<Unknown Region>";
135}
136
Ted Kremenek7090ae12008-11-02 00:34:33 +0000137void AllocaRegion::print(llvm::raw_ostream& os) const {
138 os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
139}
140
Ted Kremenek9e240492008-10-04 05:50:14 +0000141void VarRegion::print(llvm::raw_ostream& os) const {
142 os << cast<VarDecl>(D)->getName();
143}
144
Ted Kremenek993f1c72008-10-17 20:28:54 +0000145void SymbolicRegion::print(llvm::raw_ostream& os) const {
146 os << "$" << sym.getNumber();
147}
148
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000149void FieldRegion::print(llvm::raw_ostream& os) const {
150 superRegion->print(os);
151 os << "->" << getDecl()->getName();
152}
153
Zhongxing Xub21ff772008-10-24 06:30:07 +0000154void ElementRegion::print(llvm::raw_ostream& os) const {
155 superRegion->print(os);
156 os << '['; Index.print(os); os << ']';
157}
158
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000159void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
160 // FIXME: More elaborate pretty-printing.
161 os << "{ " << (void*) CL << " }";
162}
163
Zhongxing Xucc128b32008-11-10 13:05:26 +0000164void StringRegion::print(llvm::raw_ostream& os) const {
Zhongxing Xud2f016f2008-11-11 01:36:32 +0000165 if (Str->isWide()) os << 'L';
166 os << '"';
167
168 // FIXME: this doesn't print wstrings right.
169 for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
170 switch (Str->getStrData()[i]) {
171 default: os << Str->getStrData()[i]; break;
172 // Handle some common ones to make dumps prettier.
173 case '\\': os << "\\\\"; break;
174 case '"': os << "\\\""; break;
175 case '\n': os << "\\n"; break;
176 case '\t': os << "\\t"; break;
177 case '\a': os << "\\a"; break;
178 case '\b': os << "\\b"; break;
179 }
180 }
181 os << '"';
Zhongxing Xucc128b32008-11-10 13:05:26 +0000182}
183
Ted Kremenek9e240492008-10-04 05:50:14 +0000184//===----------------------------------------------------------------------===//
185// MemRegionManager methods.
186//===----------------------------------------------------------------------===//
187
188MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
189
190 if (!region) {
191 region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
192 new (region) MemSpaceRegion();
193 }
194
195 return region;
196}
197
198MemSpaceRegion* MemRegionManager::getStackRegion() {
199 return LazyAllocate(stack);
200}
201
202MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
203 return LazyAllocate(globals);
204}
205
206MemSpaceRegion* MemRegionManager::getHeapRegion() {
207 return LazyAllocate(heap);
208}
209
Zhongxing Xu17892752008-10-08 02:50:44 +0000210MemSpaceRegion* MemRegionManager::getUnknownRegion() {
211 return LazyAllocate(unknown);
212}
213
Zhongxing Xue9f4e542008-10-25 14:13:41 +0000214StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
215 llvm::FoldingSetNodeID ID;
216 MemSpaceRegion* GlobalsR = getGlobalsRegion();
217
218 StringRegion::ProfileRegion(ID, Str, GlobalsR);
219
220 void* InsertPos;
221 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
222 StringRegion* R = cast_or_null<StringRegion>(data);
223
224 if (!R) {
225 R = (StringRegion*) A.Allocate<StringRegion>();
226 new (R) StringRegion(Str, GlobalsR);
227 Regions.InsertNode(R, InsertPos);
228 }
229
230 return R;
231}
232
Ted Kremenek9a1f03a2008-10-27 21:01:26 +0000233VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
234
235 const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
236 : getGlobalsRegion();
237
Ted Kremenek9e240492008-10-04 05:50:14 +0000238 llvm::FoldingSetNodeID ID;
239 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
240
241 void* InsertPos;
242 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
243 VarRegion* R = cast_or_null<VarRegion>(data);
244
245 if (!R) {
246 R = (VarRegion*) A.Allocate<VarRegion>();
247 new (R) VarRegion(d, superRegion);
248 Regions.InsertNode(R, InsertPos);
249 }
250
251 return R;
252}
253
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000254CompoundLiteralRegion*
255MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
256 // Is this compound literal allocated on the stack or is part of the
257 // global constant pool?
258 const MemRegion* superRegion = CL->isFileScope() ?
259 getGlobalsRegion() : getStackRegion();
260
261 // Profile the compound literal.
262 llvm::FoldingSetNodeID ID;
263 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
264
265 void* InsertPos;
266 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
267 CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
268
269 if (!R) {
270 R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
271 new (R) CompoundLiteralRegion(CL, superRegion);
272 Regions.InsertNode(R, InsertPos);
273 }
274
275 return R;
276}
277
Zhongxing Xu511191c2008-10-21 05:27:10 +0000278ElementRegion* MemRegionManager::getElementRegion(SVal Idx,
279 const MemRegion* superRegion){
280 llvm::FoldingSetNodeID ID;
281 ElementRegion::ProfileRegion(ID, Idx, superRegion);
282
283 void* InsertPos;
284 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
285 ElementRegion* R = cast_or_null<ElementRegion>(data);
286
287 if (!R) {
288 R = (ElementRegion*) A.Allocate<ElementRegion>();
289 new (R) ElementRegion(Idx, superRegion);
290 Regions.InsertNode(R, InsertPos);
291 }
292
293 return R;
294}
295
Ted Kremenek993f1c72008-10-17 20:28:54 +0000296/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
297SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolID sym) {
298
299 llvm::FoldingSetNodeID ID;
300 SymbolicRegion::ProfileRegion(ID, sym);
301
302 void* InsertPos;
303 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
304 SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
305
306 if (!R) {
307 R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
308 new (R) SymbolicRegion(sym);
309 Regions.InsertNode(R, InsertPos);
310 }
311
312 return R;
313}
314
Ted Kremenek9e240492008-10-04 05:50:14 +0000315FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
Ted Kremenek993f1c72008-10-17 20:28:54 +0000316 const MemRegion* superRegion) {
Ted Kremenek9e240492008-10-04 05:50:14 +0000317 llvm::FoldingSetNodeID ID;
318 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
319
320 void* InsertPos;
321 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
322 FieldRegion* R = cast_or_null<FieldRegion>(data);
323
324 if (!R) {
325 R = (FieldRegion*) A.Allocate<FieldRegion>();
326 new (R) FieldRegion(d, superRegion);
327 Regions.InsertNode(R, InsertPos);
328 }
329
330 return R;
331}
332
Ted Kremenek993f1c72008-10-17 20:28:54 +0000333ObjCIvarRegion*
334MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
335 const MemRegion* superRegion) {
Ted Kremenek9e240492008-10-04 05:50:14 +0000336 llvm::FoldingSetNodeID ID;
337 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
338
339 void* InsertPos;
340 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
341 ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
342
343 if (!R) {
Zhongxing Xu722c2882008-10-06 03:03:33 +0000344 R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
345 new (R) ObjCIvarRegion(d, superRegion);
Ted Kremenek9e240492008-10-04 05:50:14 +0000346 Regions.InsertNode(R, InsertPos);
347 }
348
349 return R;
350}
351
Ted Kremeneka7f1b9e2008-10-24 20:30:08 +0000352ObjCObjectRegion*
353MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
354 const MemRegion* superRegion) {
355 llvm::FoldingSetNodeID ID;
356 DeclRegion::ProfileRegion(ID, d, superRegion,
357 MemRegion::ObjCObjectRegionKind);
358
359 void* InsertPos;
360 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
361 ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
362
363 if (!R) {
364 R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
365 new (R) ObjCObjectRegion(d, superRegion);
366 Regions.InsertNode(R, InsertPos);
367 }
368
369 return R;
370}
371
372
Zhongxing Xu17892752008-10-08 02:50:44 +0000373AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(const VarDecl* d) {
374 llvm::FoldingSetNodeID ID;
Zhongxing Xu17892752008-10-08 02:50:44 +0000375 MemRegion* superRegion = getUnknownRegion();
376
Zhongxing Xu817c67d2008-11-03 04:12:24 +0000377 AnonPointeeRegion::ProfileRegion(ID, d, superRegion);
Zhongxing Xu17892752008-10-08 02:50:44 +0000378
379 void* InsertPos;
380 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
381 AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data);
382
383 if (!R) {
384 R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>();
Zhongxing Xu817c67d2008-11-03 04:12:24 +0000385 new (R) AnonPointeeRegion(d, superRegion);
Zhongxing Xu17892752008-10-08 02:50:44 +0000386 Regions.InsertNode(R, InsertPos);
387 }
388
389 return R;
390}
391
Ted Kremenek7090ae12008-11-02 00:34:33 +0000392AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
393 llvm::FoldingSetNodeID ID;
394 AllocaRegion::ProfileRegion(ID, E, cnt);
395
396 void* InsertPos;
397 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
398 AllocaRegion* R = cast_or_null<AllocaRegion>(data);
399
400 if (!R) {
401 R = (AllocaRegion*) A.Allocate<AllocaRegion>();
402 new (R) AllocaRegion(E, cnt, getStackRegion());
403 Regions.InsertNode(R, InsertPos);
404 }
405
406 return R;
407}
408
Ted Kremenek9e240492008-10-04 05:50:14 +0000409bool MemRegionManager::hasStackStorage(const MemRegion* R) {
Ted Kremenek993f1c72008-10-17 20:28:54 +0000410
411 // Only subregions can have stack storage.
Ted Kremenek7090ae12008-11-02 00:34:33 +0000412 const SubRegion* SR = dyn_cast<SubRegion>(R);
413
Ted Kremenek993f1c72008-10-17 20:28:54 +0000414 if (!SR)
415 return false;
Ted Kremenek7090ae12008-11-02 00:34:33 +0000416
Ted Kremenek9e240492008-10-04 05:50:14 +0000417 MemSpaceRegion* S = getStackRegion();
418
Ted Kremenek993f1c72008-10-17 20:28:54 +0000419 while (SR) {
420 R = SR->getSuperRegion();
421 if (R == S)
422 return true;
423
424 SR = dyn_cast<SubRegion>(R);
Ted Kremenek9e240492008-10-04 05:50:14 +0000425 }
426
427 return false;
428}