blob: 898aff031f2a2ce2cc207355a91a505ee6c015a6 [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
Ted Kremenek329d6fd2008-10-27 20:57:58 +000054void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
55 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
56}
57
58void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
59 const CompoundLiteralExpr* CL,
60 const MemRegion* superRegion) {
61 ID.AddInteger((unsigned) CompoundLiteralRegionKind);
62 ID.AddPointer(CL);
63 ID.AddPointer(superRegion);
64}
65
Ted Kremenek9e240492008-10-04 05:50:14 +000066void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
67 const MemRegion* superRegion, Kind k) {
68 ID.AddInteger((unsigned) k);
69 ID.AddPointer(D);
70 ID.AddPointer(superRegion);
71}
72
73void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
74 DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
75}
76
Ted Kremenek2dabd432008-12-05 02:27:51 +000077void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym) {
Ted Kremenek993f1c72008-10-17 20:28:54 +000078 ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
Ted Kremenek6d0e2d22008-12-05 02:39:38 +000079 ID.Add(sym);
Ted Kremenek993f1c72008-10-17 20:28:54 +000080}
81
82void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
83 SymbolicRegion::ProfileRegion(ID, sym);
84}
85
Zhongxing Xu511191c2008-10-21 05:27:10 +000086void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SVal Idx,
87 const MemRegion* superRegion) {
88 ID.AddInteger(MemRegion::ElementRegionKind);
89 ID.AddPointer(superRegion);
90 Idx.Profile(ID);
91}
92
93void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
94 ElementRegion::ProfileRegion(ID, Index, superRegion);
95}
Zhongxing Xu27b57062008-10-27 13:17:02 +000096
Ted Kremenek6eddeb12008-12-13 21:49:13 +000097QualType ElementRegion::getRValueType(ASTContext& C) const {
98 QualType T = getArrayRegion()->getLValueType(C);
99 // FIXME: Should ArrayType be considered an LValue or RValue type?
Zhongxing Xu56af9772008-11-13 07:30:58 +0000100 if (isa<ArrayType>(T.getTypePtr())) {
101 ArrayType* AT = cast<ArrayType>(T.getTypePtr());
102 return AT->getElementType();
103 }
Ted Kremenek34265e72008-11-17 22:55:12 +0000104 else {
Zhongxing Xu56af9772008-11-13 07:30:58 +0000105 PointerType* PtrT = cast<PointerType>(T.getTypePtr());
106 QualType PTy = PtrT->getPointeeType();
107 return C.getCanonicalType(PTy);
108 }
Zhongxing Xu27b57062008-10-27 13:17:02 +0000109}
110
Ted Kremenek9e240492008-10-04 05:50:14 +0000111//===----------------------------------------------------------------------===//
Ted Kremenek6eddeb12008-12-13 21:49:13 +0000112// getLValueType() and getRValueType()
113//===----------------------------------------------------------------------===//
114
115QualType StringRegion::getRValueType(ASTContext& C) const {
116 return Str->getType();
117}
118
119//===----------------------------------------------------------------------===//
Ted Kremenek9e240492008-10-04 05:50:14 +0000120// Region pretty-printing.
121//===----------------------------------------------------------------------===//
122
123std::string MemRegion::getString() const {
124 std::string s;
125 llvm::raw_string_ostream os(s);
126 print(os);
127 return os.str();
128}
129
130void MemRegion::print(llvm::raw_ostream& os) const {
131 os << "<Unknown Region>";
132}
133
Ted Kremenek7090ae12008-11-02 00:34:33 +0000134void AllocaRegion::print(llvm::raw_ostream& os) const {
135 os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
136}
137
Ted Kremenek9e240492008-10-04 05:50:14 +0000138void VarRegion::print(llvm::raw_ostream& os) const {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000139 os << cast<VarDecl>(D)->getNameAsString();
Ted Kremenek9e240492008-10-04 05:50:14 +0000140}
141
Ted Kremenek993f1c72008-10-17 20:28:54 +0000142void SymbolicRegion::print(llvm::raw_ostream& os) const {
Ted Kremenek562731e2008-12-05 02:45:20 +0000143 os << "SymRegion-";
144 sym.print(os);
Ted Kremenek993f1c72008-10-17 20:28:54 +0000145}
146
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000147void FieldRegion::print(llvm::raw_ostream& os) const {
148 superRegion->print(os);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000149 os << "->" << getDecl()->getNameAsString();
Ted Kremenek4bd1eef2008-10-17 21:05:44 +0000150}
151
Zhongxing Xub21ff772008-10-24 06:30:07 +0000152void ElementRegion::print(llvm::raw_ostream& os) const {
153 superRegion->print(os);
154 os << '['; Index.print(os); os << ']';
155}
156
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000157void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
158 // FIXME: More elaborate pretty-printing.
159 os << "{ " << (void*) CL << " }";
160}
161
Zhongxing Xucc128b32008-11-10 13:05:26 +0000162void StringRegion::print(llvm::raw_ostream& os) const {
Zhongxing Xud2f016f2008-11-11 01:36:32 +0000163 if (Str->isWide()) os << 'L';
164 os << '"';
165
166 // FIXME: this doesn't print wstrings right.
167 for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
168 switch (Str->getStrData()[i]) {
169 default: os << Str->getStrData()[i]; break;
170 // Handle some common ones to make dumps prettier.
171 case '\\': os << "\\\\"; break;
172 case '"': os << "\\\""; break;
173 case '\n': os << "\\n"; break;
174 case '\t': os << "\\t"; break;
175 case '\a': os << "\\a"; break;
176 case '\b': os << "\\b"; break;
177 }
178 }
179 os << '"';
Zhongxing Xucc128b32008-11-10 13:05:26 +0000180}
181
Ted Kremenek9e240492008-10-04 05:50:14 +0000182//===----------------------------------------------------------------------===//
183// MemRegionManager methods.
184//===----------------------------------------------------------------------===//
185
186MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
187
188 if (!region) {
189 region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
190 new (region) MemSpaceRegion();
191 }
192
193 return region;
194}
195
196MemSpaceRegion* MemRegionManager::getStackRegion() {
197 return LazyAllocate(stack);
198}
199
200MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
201 return LazyAllocate(globals);
202}
203
204MemSpaceRegion* MemRegionManager::getHeapRegion() {
205 return LazyAllocate(heap);
206}
207
Zhongxing Xu17892752008-10-08 02:50:44 +0000208MemSpaceRegion* MemRegionManager::getUnknownRegion() {
209 return LazyAllocate(unknown);
210}
211
Zhongxing Xue9f4e542008-10-25 14:13:41 +0000212StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
213 llvm::FoldingSetNodeID ID;
214 MemSpaceRegion* GlobalsR = getGlobalsRegion();
215
216 StringRegion::ProfileRegion(ID, Str, GlobalsR);
217
218 void* InsertPos;
219 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
220 StringRegion* R = cast_or_null<StringRegion>(data);
221
222 if (!R) {
223 R = (StringRegion*) A.Allocate<StringRegion>();
224 new (R) StringRegion(Str, GlobalsR);
225 Regions.InsertNode(R, InsertPos);
226 }
227
228 return R;
229}
230
Ted Kremenek9a1f03a2008-10-27 21:01:26 +0000231VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
232
233 const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
234 : getGlobalsRegion();
235
Ted Kremenek9e240492008-10-04 05:50:14 +0000236 llvm::FoldingSetNodeID ID;
237 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
238
239 void* InsertPos;
240 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
241 VarRegion* R = cast_or_null<VarRegion>(data);
242
243 if (!R) {
244 R = (VarRegion*) A.Allocate<VarRegion>();
245 new (R) VarRegion(d, superRegion);
246 Regions.InsertNode(R, InsertPos);
247 }
248
249 return R;
250}
251
Ted Kremenek329d6fd2008-10-27 20:57:58 +0000252CompoundLiteralRegion*
253MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
254 // Is this compound literal allocated on the stack or is part of the
255 // global constant pool?
256 const MemRegion* superRegion = CL->isFileScope() ?
257 getGlobalsRegion() : getStackRegion();
258
259 // Profile the compound literal.
260 llvm::FoldingSetNodeID ID;
261 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
262
263 void* InsertPos;
264 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
265 CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
266
267 if (!R) {
268 R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
269 new (R) CompoundLiteralRegion(CL, superRegion);
270 Regions.InsertNode(R, InsertPos);
271 }
272
273 return R;
274}
275
Ted Kremenekabb042f2008-12-13 19:24:37 +0000276ElementRegion*
277MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){
278
Zhongxing Xu511191c2008-10-21 05:27:10 +0000279 llvm::FoldingSetNodeID ID;
280 ElementRegion::ProfileRegion(ID, Idx, superRegion);
281
282 void* InsertPos;
283 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
284 ElementRegion* R = cast_or_null<ElementRegion>(data);
285
286 if (!R) {
287 R = (ElementRegion*) A.Allocate<ElementRegion>();
288 new (R) ElementRegion(Idx, superRegion);
289 Regions.InsertNode(R, InsertPos);
290 }
291
292 return R;
293}
294
Ted Kremenek993f1c72008-10-17 20:28:54 +0000295/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
Ted Kremenek2dabd432008-12-05 02:27:51 +0000296SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym) {
Ted Kremenek993f1c72008-10-17 20:28:54 +0000297
298 llvm::FoldingSetNodeID ID;
299 SymbolicRegion::ProfileRegion(ID, sym);
300
301 void* InsertPos;
302 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
303 SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
304
305 if (!R) {
306 R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
307 new (R) SymbolicRegion(sym);
308 Regions.InsertNode(R, InsertPos);
309 }
310
311 return R;
312}
313
Ted Kremenek9e240492008-10-04 05:50:14 +0000314FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
Ted Kremenek993f1c72008-10-17 20:28:54 +0000315 const MemRegion* superRegion) {
Ted Kremenek9e240492008-10-04 05:50:14 +0000316 llvm::FoldingSetNodeID ID;
317 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
318
319 void* InsertPos;
320 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
321 FieldRegion* R = cast_or_null<FieldRegion>(data);
322
323 if (!R) {
324 R = (FieldRegion*) A.Allocate<FieldRegion>();
325 new (R) FieldRegion(d, superRegion);
326 Regions.InsertNode(R, InsertPos);
327 }
328
329 return R;
330}
331
Ted Kremenek993f1c72008-10-17 20:28:54 +0000332ObjCIvarRegion*
333MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
334 const MemRegion* superRegion) {
Ted Kremenek9e240492008-10-04 05:50:14 +0000335 llvm::FoldingSetNodeID ID;
336 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
337
338 void* InsertPos;
339 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
340 ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
341
342 if (!R) {
Zhongxing Xu722c2882008-10-06 03:03:33 +0000343 R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
344 new (R) ObjCIvarRegion(d, superRegion);
Ted Kremenek9e240492008-10-04 05:50:14 +0000345 Regions.InsertNode(R, InsertPos);
346 }
347
348 return R;
349}
350
Ted Kremeneka7f1b9e2008-10-24 20:30:08 +0000351ObjCObjectRegion*
352MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
353 const MemRegion* superRegion) {
354 llvm::FoldingSetNodeID ID;
355 DeclRegion::ProfileRegion(ID, d, superRegion,
356 MemRegion::ObjCObjectRegionKind);
357
358 void* InsertPos;
359 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
360 ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
361
362 if (!R) {
363 R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
364 new (R) ObjCObjectRegion(d, superRegion);
365 Regions.InsertNode(R, InsertPos);
366 }
367
368 return R;
369}
370
Zhongxing Xudc0a25d2008-11-16 04:07:26 +0000371AnonTypedRegion*
372MemRegionManager::getAnonTypedRegion(QualType t, const MemRegion* superRegion) {
373 llvm::FoldingSetNodeID ID;
374 AnonTypedRegion::ProfileRegion(ID, t, superRegion);
375
376 void* InsertPos;
377 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
378 AnonTypedRegion* R = cast_or_null<AnonTypedRegion>(data);
379
380 if (!R) {
381 R = (AnonTypedRegion*) A.Allocate<AnonTypedRegion>();
382 new (R) AnonTypedRegion(t, superRegion);
383 Regions.InsertNode(R, InsertPos);
384 }
385
386 return R;
387}
Ted Kremeneka7f1b9e2008-10-24 20:30:08 +0000388
Ted Kremenek7090ae12008-11-02 00:34:33 +0000389AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
390 llvm::FoldingSetNodeID ID;
391 AllocaRegion::ProfileRegion(ID, E, cnt);
392
393 void* InsertPos;
394 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
395 AllocaRegion* R = cast_or_null<AllocaRegion>(data);
396
397 if (!R) {
398 R = (AllocaRegion*) A.Allocate<AllocaRegion>();
399 new (R) AllocaRegion(E, cnt, getStackRegion());
400 Regions.InsertNode(R, InsertPos);
401 }
402
403 return R;
404}
405
Ted Kremenek9e240492008-10-04 05:50:14 +0000406bool MemRegionManager::hasStackStorage(const MemRegion* R) {
Ted Kremenek993f1c72008-10-17 20:28:54 +0000407
408 // Only subregions can have stack storage.
Ted Kremenek7090ae12008-11-02 00:34:33 +0000409 const SubRegion* SR = dyn_cast<SubRegion>(R);
410
Ted Kremenek993f1c72008-10-17 20:28:54 +0000411 if (!SR)
412 return false;
Ted Kremenek7090ae12008-11-02 00:34:33 +0000413
Ted Kremenek9e240492008-10-04 05:50:14 +0000414 MemSpaceRegion* S = getStackRegion();
415
Ted Kremenek993f1c72008-10-17 20:28:54 +0000416 while (SR) {
417 R = SR->getSuperRegion();
418 if (R == S)
419 return true;
420
421 SR = dyn_cast<SubRegion>(R);
Ted Kremenek9e240492008-10-04 05:50:14 +0000422 }
423
424 return false;
425}