blob: d8efef2e675d934e0d9a35a16568860e50019c05 [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
28void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
29 const MemRegion* superRegion) {
30 ID.AddInteger((unsigned) AnonTypedRegionKind);
31 ID.Add(T);
32 ID.AddPointer(superRegion);
33}
34
Zhongxing Xu79c57f82008-10-08 02:50:44 +000035void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
36 const VarDecl* VD, QualType T,
37 const MemRegion* superRegion) {
38 ID.AddInteger((unsigned) AnonPointeeRegionKind);
39 ID.Add(T);
40 ID.AddPointer(VD);
41 ID.AddPointer(superRegion);
42}
43
Ted Kremenekb15eba42008-10-04 05:50:14 +000044void AnonTypedRegion::Profile(llvm::FoldingSetNodeID& ID) const {
45 AnonTypedRegion::ProfileRegion(ID, T, superRegion);
46}
47
48void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
49 const MemRegion* superRegion, Kind k) {
50 ID.AddInteger((unsigned) k);
51 ID.AddPointer(D);
52 ID.AddPointer(superRegion);
53}
54
55void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
56 DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
57}
58
Ted Kremenek38a4b4b2008-10-17 20:28:54 +000059void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolID sym) {
60 ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
61 ID.AddInteger(sym.getNumber());
62}
63
64void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
65 SymbolicRegion::ProfileRegion(ID, sym);
66}
67
Ted Kremenekb15eba42008-10-04 05:50:14 +000068//===----------------------------------------------------------------------===//
69// Region pretty-printing.
70//===----------------------------------------------------------------------===//
71
72std::string MemRegion::getString() const {
73 std::string s;
74 llvm::raw_string_ostream os(s);
75 print(os);
76 return os.str();
77}
78
79void MemRegion::print(llvm::raw_ostream& os) const {
80 os << "<Unknown Region>";
81}
82
83void VarRegion::print(llvm::raw_ostream& os) const {
84 os << cast<VarDecl>(D)->getName();
85}
86
Ted Kremenek38a4b4b2008-10-17 20:28:54 +000087void SymbolicRegion::print(llvm::raw_ostream& os) const {
88 os << "$" << sym.getNumber();
89}
90
Ted Kremenekdea0c6b2008-10-17 21:05:44 +000091void FieldRegion::print(llvm::raw_ostream& os) const {
92 superRegion->print(os);
93 os << "->" << getDecl()->getName();
94}
95
Ted Kremenekb15eba42008-10-04 05:50:14 +000096//===----------------------------------------------------------------------===//
97// MemRegionManager methods.
98//===----------------------------------------------------------------------===//
99
100MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
101
102 if (!region) {
103 region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
104 new (region) MemSpaceRegion();
105 }
106
107 return region;
108}
109
110MemSpaceRegion* MemRegionManager::getStackRegion() {
111 return LazyAllocate(stack);
112}
113
114MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
115 return LazyAllocate(globals);
116}
117
118MemSpaceRegion* MemRegionManager::getHeapRegion() {
119 return LazyAllocate(heap);
120}
121
Zhongxing Xu79c57f82008-10-08 02:50:44 +0000122MemSpaceRegion* MemRegionManager::getUnknownRegion() {
123 return LazyAllocate(unknown);
124}
125
Ted Kremenekb15eba42008-10-04 05:50:14 +0000126VarRegion* MemRegionManager::getVarRegion(const VarDecl* d,
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000127 const MemRegion* superRegion) {
Ted Kremenekb15eba42008-10-04 05:50:14 +0000128 llvm::FoldingSetNodeID ID;
129 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
130
131 void* InsertPos;
132 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
133 VarRegion* R = cast_or_null<VarRegion>(data);
134
135 if (!R) {
136 R = (VarRegion*) A.Allocate<VarRegion>();
137 new (R) VarRegion(d, superRegion);
138 Regions.InsertNode(R, InsertPos);
139 }
140
141 return R;
142}
143
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000144/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
145SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolID sym) {
146
147 llvm::FoldingSetNodeID ID;
148 SymbolicRegion::ProfileRegion(ID, sym);
149
150 void* InsertPos;
151 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
152 SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
153
154 if (!R) {
155 R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
156 new (R) SymbolicRegion(sym);
157 Regions.InsertNode(R, InsertPos);
158 }
159
160 return R;
161}
162
Ted Kremenekb15eba42008-10-04 05:50:14 +0000163FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000164 const MemRegion* superRegion) {
Ted Kremenekb15eba42008-10-04 05:50:14 +0000165 llvm::FoldingSetNodeID ID;
166 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
167
168 void* InsertPos;
169 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
170 FieldRegion* R = cast_or_null<FieldRegion>(data);
171
172 if (!R) {
173 R = (FieldRegion*) A.Allocate<FieldRegion>();
174 new (R) FieldRegion(d, superRegion);
175 Regions.InsertNode(R, InsertPos);
176 }
177
178 return R;
179}
180
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000181ObjCIvarRegion*
182MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
183 const MemRegion* superRegion) {
Ted Kremenekb15eba42008-10-04 05:50:14 +0000184 llvm::FoldingSetNodeID ID;
185 DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
186
187 void* InsertPos;
188 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
189 ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
190
191 if (!R) {
Zhongxing Xu7a861e82008-10-06 03:03:33 +0000192 R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
193 new (R) ObjCIvarRegion(d, superRegion);
Ted Kremenekb15eba42008-10-04 05:50:14 +0000194 Regions.InsertNode(R, InsertPos);
195 }
196
197 return R;
198}
199
Zhongxing Xu79c57f82008-10-08 02:50:44 +0000200AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(const VarDecl* d) {
201 llvm::FoldingSetNodeID ID;
202 QualType T = d->getType();
203 QualType PointeeType = cast<PointerType>(T.getTypePtr())->getPointeeType();
204 MemRegion* superRegion = getUnknownRegion();
205
206 AnonPointeeRegion::ProfileRegion(ID, d, PointeeType, superRegion);
207
208 void* InsertPos;
209 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
210 AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data);
211
212 if (!R) {
213 R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>();
214 new (R) AnonPointeeRegion(d, PointeeType, superRegion);
215 Regions.InsertNode(R, InsertPos);
216 }
217
218 return R;
219}
220
Ted Kremenekb15eba42008-10-04 05:50:14 +0000221bool MemRegionManager::hasStackStorage(const MemRegion* R) {
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000222 const SubRegion* SR = dyn_cast<SubRegion>(R);
223
224 // Only subregions can have stack storage.
225 if (!SR)
226 return false;
227
Ted Kremenekb15eba42008-10-04 05:50:14 +0000228 MemSpaceRegion* S = getStackRegion();
229
Ted Kremenek38a4b4b2008-10-17 20:28:54 +0000230 while (SR) {
231 R = SR->getSuperRegion();
232 if (R == S)
233 return true;
234
235 SR = dyn_cast<SubRegion>(R);
Ted Kremenekb15eba42008-10-04 05:50:14 +0000236 }
237
238 return false;
239}