blob: eafeee66d546359a3269e4ba7e6286585a3d38f3 [file] [log] [blame]
Ted Kremenekb15eba42008-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 Xu73507bd2008-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 Kremenekea9ca502008-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 Xu8fbe7ae2008-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 Kremenek6bc91b92008-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 Kremenekb15eba42008-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 Kremenekb9cd9a72008-12-05 02:27:51 +000077void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym) {
Ted Kremenek38a4b4b2008-10-17 20:28:54 +000078 ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
Ted Kremeneke8993f12008-12-05 02:39:38 +000079 ID.Add(sym);
Ted Kremenek38a4b4b2008-10-17 20:28:54 +000080}
81
82void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
83 SymbolicRegion::ProfileRegion(ID, sym);
84}
85
Zhongxing Xu54969732008-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 Xu1a563da2008-10-27 13:17:02 +000096
Ted Kremenekf5da3252008-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 Xu9f801532008-11-13 07:30:58 +0000100 if (isa<ArrayType>(T.getTypePtr())) {
101 ArrayType* AT = cast<ArrayType>(T.getTypePtr());
102 return AT->getElementType();
103 }
Ted Kremenek3ba2c5f2008-11-17 22:55:12 +0000104 else {
Zhongxing Xu9f801532008-11-13 07:30:58 +0000105 PointerType* PtrT = cast<PointerType>(T.getTypePtr());
106 QualType PTy = PtrT->getPointeeType();
107 return C.getCanonicalType(PTy);
108 }
Zhongxing Xu1a563da2008-10-27 13:17:02 +0000109}
110
Ted Kremenekb15eba42008-10-04 05:50:14 +0000111//===----------------------------------------------------------------------===//
Ted Kremenekf5da3252008-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 Kremenekb15eba42008-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 Kremenekea9ca502008-11-02 00:34:33 +0000134void AllocaRegion::print(llvm::raw_ostream& os) const {
135 os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
136}
137
Ted Kremenek542c34d2008-12-17 19:25:50 +0000138void AnonTypedRegion::print(llvm::raw_ostream& os) const {
139 os << "anon_type{" << T.getAsString() << ',';
140 getSuperRegion()->print(os);
141 os << '}';
142}
143
Ted Kremenekb15eba42008-10-04 05:50:14 +0000144void VarRegion::print(llvm::raw_ostream& os) const {
Chris Lattner271d4c22008-11-24 05:29:24 +0000145 os << cast<VarDecl>(D)->getNameAsString();
Ted Kremenekb15eba42008-10-04 05:50:14 +0000146}
147
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000148void SymbolicRegion::print(llvm::raw_ostream& os) const {
Ted Kremenek8b60bad2008-12-05 02:45:20 +0000149 os << "SymRegion-";
150 sym.print(os);
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000151}
152
Ted Kremenekdea0c6b2008-10-17 21:05:44 +0000153void FieldRegion::print(llvm::raw_ostream& os) const {
154 superRegion->print(os);
Chris Lattner271d4c22008-11-24 05:29:24 +0000155 os << "->" << getDecl()->getNameAsString();
Ted Kremenekdea0c6b2008-10-17 21:05:44 +0000156}
157
Zhongxing Xu74a4e3a2008-10-24 06:30:07 +0000158void ElementRegion::print(llvm::raw_ostream& os) const {
159 superRegion->print(os);
160 os << '['; Index.print(os); os << ']';
161}
162
Ted Kremenek6bc91b92008-10-27 20:57:58 +0000163void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
164 // FIXME: More elaborate pretty-printing.
165 os << "{ " << (void*) CL << " }";
166}
167
Zhongxing Xu4c9390f2008-11-10 13:05:26 +0000168void StringRegion::print(llvm::raw_ostream& os) const {
Zhongxing Xuff81fc52008-11-11 01:36:32 +0000169 if (Str->isWide()) os << 'L';
170 os << '"';
171
172 // FIXME: this doesn't print wstrings right.
173 for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
174 switch (Str->getStrData()[i]) {
175 default: os << Str->getStrData()[i]; break;
176 // Handle some common ones to make dumps prettier.
177 case '\\': os << "\\\\"; break;
178 case '"': os << "\\\""; break;
179 case '\n': os << "\\n"; break;
180 case '\t': os << "\\t"; break;
181 case '\a': os << "\\a"; break;
182 case '\b': os << "\\b"; break;
183 }
184 }
185 os << '"';
Zhongxing Xu4c9390f2008-11-10 13:05:26 +0000186}
187
Ted Kremenekb15eba42008-10-04 05:50:14 +0000188//===----------------------------------------------------------------------===//
189// MemRegionManager methods.
190//===----------------------------------------------------------------------===//
191
192MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
193
194 if (!region) {
195 region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
196 new (region) MemSpaceRegion();
197 }
198
199 return region;
200}
201
202MemSpaceRegion* MemRegionManager::getStackRegion() {
203 return LazyAllocate(stack);
204}
205
206MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
207 return LazyAllocate(globals);
208}
209
210MemSpaceRegion* MemRegionManager::getHeapRegion() {
211 return LazyAllocate(heap);
212}
213
Zhongxing Xu79c57f82008-10-08 02:50:44 +0000214MemSpaceRegion* MemRegionManager::getUnknownRegion() {
215 return LazyAllocate(unknown);
216}
217
Zhongxing Xu73507bd2008-10-25 14:13:41 +0000218StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
219 llvm::FoldingSetNodeID ID;
220 MemSpaceRegion* GlobalsR = getGlobalsRegion();
221
222 StringRegion::ProfileRegion(ID, Str, GlobalsR);
223
224 void* InsertPos;
225 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
226 StringRegion* R = cast_or_null<StringRegion>(data);
227
228 if (!R) {
229 R = (StringRegion*) A.Allocate<StringRegion>();
230 new (R) StringRegion(Str, GlobalsR);
231 Regions.InsertNode(R, InsertPos);
232 }
233
234 return R;
235}
236
Ted Kremenek81329ab2008-10-27 21:01:26 +0000237VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
238
239 const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
240 : getGlobalsRegion();
241
Ted Kremenekb15eba42008-10-04 05:50:14 +0000242 llvm::FoldingSetNodeID ID;
243 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
244
245 void* InsertPos;
246 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
247 VarRegion* R = cast_or_null<VarRegion>(data);
248
249 if (!R) {
250 R = (VarRegion*) A.Allocate<VarRegion>();
251 new (R) VarRegion(d, superRegion);
252 Regions.InsertNode(R, InsertPos);
253 }
254
255 return R;
256}
257
Ted Kremenek6bc91b92008-10-27 20:57:58 +0000258CompoundLiteralRegion*
259MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
260 // Is this compound literal allocated on the stack or is part of the
261 // global constant pool?
262 const MemRegion* superRegion = CL->isFileScope() ?
263 getGlobalsRegion() : getStackRegion();
264
265 // Profile the compound literal.
266 llvm::FoldingSetNodeID ID;
267 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
268
269 void* InsertPos;
270 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
271 CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
272
273 if (!R) {
274 R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
275 new (R) CompoundLiteralRegion(CL, superRegion);
276 Regions.InsertNode(R, InsertPos);
277 }
278
279 return R;
280}
281
Ted Kremenek2c0de352008-12-13 19:24:37 +0000282ElementRegion*
283MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){
284
Zhongxing Xu54969732008-10-21 05:27:10 +0000285 llvm::FoldingSetNodeID ID;
286 ElementRegion::ProfileRegion(ID, Idx, superRegion);
287
288 void* InsertPos;
289 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
290 ElementRegion* R = cast_or_null<ElementRegion>(data);
291
292 if (!R) {
293 R = (ElementRegion*) A.Allocate<ElementRegion>();
294 new (R) ElementRegion(Idx, superRegion);
295 Regions.InsertNode(R, InsertPos);
296 }
297
298 return R;
299}
300
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000301/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
Ted Kremenekb9cd9a72008-12-05 02:27:51 +0000302SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym) {
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000303
304 llvm::FoldingSetNodeID ID;
305 SymbolicRegion::ProfileRegion(ID, sym);
306
307 void* InsertPos;
308 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
309 SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
310
311 if (!R) {
312 R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
313 new (R) SymbolicRegion(sym);
314 Regions.InsertNode(R, InsertPos);
315 }
316
317 return R;
318}
319
Ted Kremenekb15eba42008-10-04 05:50:14 +0000320FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000321 const MemRegion* superRegion) {
Ted Kremenekb15eba42008-10-04 05:50:14 +0000322 llvm::FoldingSetNodeID ID;
323 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
324
325 void* InsertPos;
326 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
327 FieldRegion* R = cast_or_null<FieldRegion>(data);
328
329 if (!R) {
330 R = (FieldRegion*) A.Allocate<FieldRegion>();
331 new (R) FieldRegion(d, superRegion);
332 Regions.InsertNode(R, InsertPos);
333 }
334
335 return R;
336}
337
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000338ObjCIvarRegion*
339MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
340 const MemRegion* superRegion) {
Ted Kremenekb15eba42008-10-04 05:50:14 +0000341 llvm::FoldingSetNodeID ID;
342 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
343
344 void* InsertPos;
345 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
346 ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
347
348 if (!R) {
Zhongxing Xu7a861e82008-10-06 03:03:33 +0000349 R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
350 new (R) ObjCIvarRegion(d, superRegion);
Ted Kremenekb15eba42008-10-04 05:50:14 +0000351 Regions.InsertNode(R, InsertPos);
352 }
353
354 return R;
355}
356
Ted Kremenek2539c112008-10-24 20:30:08 +0000357ObjCObjectRegion*
358MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
359 const MemRegion* superRegion) {
360 llvm::FoldingSetNodeID ID;
361 DeclRegion::ProfileRegion(ID, d, superRegion,
362 MemRegion::ObjCObjectRegionKind);
363
364 void* InsertPos;
365 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
366 ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
367
368 if (!R) {
369 R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
370 new (R) ObjCObjectRegion(d, superRegion);
371 Regions.InsertNode(R, InsertPos);
372 }
373
374 return R;
375}
376
Zhongxing Xu8fbe7ae2008-11-16 04:07:26 +0000377AnonTypedRegion*
378MemRegionManager::getAnonTypedRegion(QualType t, const MemRegion* superRegion) {
379 llvm::FoldingSetNodeID ID;
380 AnonTypedRegion::ProfileRegion(ID, t, superRegion);
381
382 void* InsertPos;
383 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
384 AnonTypedRegion* R = cast_or_null<AnonTypedRegion>(data);
385
386 if (!R) {
387 R = (AnonTypedRegion*) A.Allocate<AnonTypedRegion>();
388 new (R) AnonTypedRegion(t, superRegion);
389 Regions.InsertNode(R, InsertPos);
390 }
391
392 return R;
393}
Ted Kremenek2539c112008-10-24 20:30:08 +0000394
Ted Kremenekea9ca502008-11-02 00:34:33 +0000395AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
396 llvm::FoldingSetNodeID ID;
397 AllocaRegion::ProfileRegion(ID, E, cnt);
398
399 void* InsertPos;
400 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
401 AllocaRegion* R = cast_or_null<AllocaRegion>(data);
402
403 if (!R) {
404 R = (AllocaRegion*) A.Allocate<AllocaRegion>();
405 new (R) AllocaRegion(E, cnt, getStackRegion());
406 Regions.InsertNode(R, InsertPos);
407 }
408
409 return R;
410}
411
Ted Kremenekb15eba42008-10-04 05:50:14 +0000412bool MemRegionManager::hasStackStorage(const MemRegion* R) {
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000413
414 // Only subregions can have stack storage.
Ted Kremenekea9ca502008-11-02 00:34:33 +0000415 const SubRegion* SR = dyn_cast<SubRegion>(R);
416
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000417 if (!SR)
418 return false;
Ted Kremenekea9ca502008-11-02 00:34:33 +0000419
Ted Kremenekb15eba42008-10-04 05:50:14 +0000420 MemSpaceRegion* S = getStackRegion();
421
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000422 while (SR) {
423 R = SR->getSuperRegion();
424 if (R == S)
425 return true;
426
427 SR = dyn_cast<SubRegion>(R);
Ted Kremenekb15eba42008-10-04 05:50:14 +0000428 }
429
430 return false;
431}