File: | tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp |
Warning: | line 1452, column 39 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MemRegion.cpp - Abstract memory regions for static analysis --------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file defines MemRegion and its subclasses. MemRegion defines a | |||
10 | // partially-typed abstraction of memory useful for path-sensitive dataflow | |||
11 | // analyses. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" | |||
16 | #include "clang/AST/ASTContext.h" | |||
17 | #include "clang/AST/Attr.h" | |||
18 | #include "clang/AST/CharUnits.h" | |||
19 | #include "clang/AST/Decl.h" | |||
20 | #include "clang/AST/DeclCXX.h" | |||
21 | #include "clang/AST/DeclObjC.h" | |||
22 | #include "clang/AST/Expr.h" | |||
23 | #include "clang/AST/PrettyPrinter.h" | |||
24 | #include "clang/AST/RecordLayout.h" | |||
25 | #include "clang/AST/Type.h" | |||
26 | #include "clang/Analysis/AnalysisDeclContext.h" | |||
27 | #include "clang/Analysis/Support/BumpVector.h" | |||
28 | #include "clang/Basic/IdentifierTable.h" | |||
29 | #include "clang/Basic/LLVM.h" | |||
30 | #include "clang/Basic/SourceManager.h" | |||
31 | #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" | |||
32 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" | |||
33 | #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" | |||
34 | #include "llvm/ADT/APInt.h" | |||
35 | #include "llvm/ADT/FoldingSet.h" | |||
36 | #include "llvm/ADT/Optional.h" | |||
37 | #include "llvm/ADT/PointerUnion.h" | |||
38 | #include "llvm/ADT/SmallString.h" | |||
39 | #include "llvm/ADT/StringRef.h" | |||
40 | #include "llvm/ADT/Twine.h" | |||
41 | #include "llvm/Support/Allocator.h" | |||
42 | #include "llvm/Support/Casting.h" | |||
43 | #include "llvm/Support/CheckedArithmetic.h" | |||
44 | #include "llvm/Support/Compiler.h" | |||
45 | #include "llvm/Support/Debug.h" | |||
46 | #include "llvm/Support/ErrorHandling.h" | |||
47 | #include "llvm/Support/raw_ostream.h" | |||
48 | #include <cassert> | |||
49 | #include <cstdint> | |||
50 | #include <functional> | |||
51 | #include <iterator> | |||
52 | #include <string> | |||
53 | #include <tuple> | |||
54 | #include <utility> | |||
55 | ||||
56 | using namespace clang; | |||
57 | using namespace ento; | |||
58 | ||||
59 | #define DEBUG_TYPE"MemRegion" "MemRegion" | |||
60 | ||||
61 | //===----------------------------------------------------------------------===// | |||
62 | // MemRegion Construction. | |||
63 | //===----------------------------------------------------------------------===// | |||
64 | ||||
65 | template <typename RegionTy, typename SuperTy, typename Arg1Ty> | |||
66 | RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, | |||
67 | const SuperTy *superRegion) { | |||
68 | llvm::FoldingSetNodeID ID; | |||
69 | RegionTy::ProfileRegion(ID, arg1, superRegion); | |||
70 | void *InsertPos; | |||
71 | auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); | |||
72 | ||||
73 | if (!R) { | |||
74 | R = A.Allocate<RegionTy>(); | |||
75 | new (R) RegionTy(arg1, superRegion); | |||
76 | Regions.InsertNode(R, InsertPos); | |||
77 | } | |||
78 | ||||
79 | return R; | |||
80 | } | |||
81 | ||||
82 | template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty> | |||
83 | RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, | |||
84 | const SuperTy *superRegion) { | |||
85 | llvm::FoldingSetNodeID ID; | |||
86 | RegionTy::ProfileRegion(ID, arg1, arg2, superRegion); | |||
87 | void *InsertPos; | |||
88 | auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); | |||
89 | ||||
90 | if (!R) { | |||
91 | R = A.Allocate<RegionTy>(); | |||
92 | new (R) RegionTy(arg1, arg2, superRegion); | |||
93 | Regions.InsertNode(R, InsertPos); | |||
94 | } | |||
95 | ||||
96 | return R; | |||
97 | } | |||
98 | ||||
99 | template <typename RegionTy, typename SuperTy, | |||
100 | typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> | |||
101 | RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, | |||
102 | const Arg3Ty arg3, | |||
103 | const SuperTy *superRegion) { | |||
104 | llvm::FoldingSetNodeID ID; | |||
105 | RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion); | |||
106 | void *InsertPos; | |||
107 | auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); | |||
108 | ||||
109 | if (!R) { | |||
110 | R = A.Allocate<RegionTy>(); | |||
111 | new (R) RegionTy(arg1, arg2, arg3, superRegion); | |||
112 | Regions.InsertNode(R, InsertPos); | |||
113 | } | |||
114 | ||||
115 | return R; | |||
116 | } | |||
117 | ||||
118 | //===----------------------------------------------------------------------===// | |||
119 | // Object destruction. | |||
120 | //===----------------------------------------------------------------------===// | |||
121 | ||||
122 | MemRegion::~MemRegion() = default; | |||
123 | ||||
124 | // All regions and their data are BumpPtrAllocated. No need to call their | |||
125 | // destructors. | |||
126 | MemRegionManager::~MemRegionManager() = default; | |||
127 | ||||
128 | //===----------------------------------------------------------------------===// | |||
129 | // Basic methods. | |||
130 | //===----------------------------------------------------------------------===// | |||
131 | ||||
132 | bool SubRegion::isSubRegionOf(const MemRegion* R) const { | |||
133 | const MemRegion* r = this; | |||
134 | do { | |||
135 | if (r == R) | |||
136 | return true; | |||
137 | if (const auto *sr = dyn_cast<SubRegion>(r)) | |||
138 | r = sr->getSuperRegion(); | |||
139 | else | |||
140 | break; | |||
141 | } while (r != nullptr); | |||
142 | return false; | |||
143 | } | |||
144 | ||||
145 | MemRegionManager* SubRegion::getMemRegionManager() const { | |||
146 | const SubRegion* r = this; | |||
147 | do { | |||
148 | const MemRegion *superRegion = r->getSuperRegion(); | |||
149 | if (const auto *sr = dyn_cast<SubRegion>(superRegion)) { | |||
150 | r = sr; | |||
151 | continue; | |||
152 | } | |||
153 | return superRegion->getMemRegionManager(); | |||
154 | } while (true); | |||
155 | } | |||
156 | ||||
157 | const StackFrameContext *VarRegion::getStackFrame() const { | |||
158 | const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace()); | |||
159 | return SSR ? SSR->getStackFrame() : nullptr; | |||
160 | } | |||
161 | ||||
162 | //===----------------------------------------------------------------------===// | |||
163 | // Region extents. | |||
164 | //===----------------------------------------------------------------------===// | |||
165 | ||||
166 | DefinedOrUnknownSVal TypedValueRegion::getExtent(SValBuilder &svalBuilder) const { | |||
167 | ASTContext &Ctx = svalBuilder.getContext(); | |||
168 | QualType T = getDesugaredValueType(Ctx); | |||
169 | ||||
170 | if (isa<VariableArrayType>(T)) | |||
171 | return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); | |||
172 | if (T->isIncompleteType()) | |||
173 | return UnknownVal(); | |||
174 | ||||
175 | CharUnits size = Ctx.getTypeSizeInChars(T); | |||
176 | QualType sizeTy = svalBuilder.getArrayIndexType(); | |||
177 | return svalBuilder.makeIntVal(size.getQuantity(), sizeTy); | |||
178 | } | |||
179 | ||||
180 | DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const { | |||
181 | // Force callers to deal with bitfields explicitly. | |||
182 | if (getDecl()->isBitField()) | |||
183 | return UnknownVal(); | |||
184 | ||||
185 | DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder); | |||
186 | ||||
187 | // A zero-length array at the end of a struct often stands for dynamically- | |||
188 | // allocated extra memory. | |||
189 | if (Extent.isZeroConstant()) { | |||
190 | QualType T = getDesugaredValueType(svalBuilder.getContext()); | |||
191 | ||||
192 | if (isa<ConstantArrayType>(T)) | |||
193 | return UnknownVal(); | |||
194 | } | |||
195 | ||||
196 | return Extent; | |||
197 | } | |||
198 | ||||
199 | DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const { | |||
200 | return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); | |||
201 | } | |||
202 | ||||
203 | DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const { | |||
204 | return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); | |||
205 | } | |||
206 | ||||
207 | DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const { | |||
208 | return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1, | |||
209 | svalBuilder.getArrayIndexType()); | |||
210 | } | |||
211 | ||||
212 | ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg) | |||
213 | : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {} | |||
214 | ||||
215 | const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { | |||
216 | return cast<ObjCIvarDecl>(D); | |||
217 | } | |||
218 | ||||
219 | QualType ObjCIvarRegion::getValueType() const { | |||
220 | return getDecl()->getType(); | |||
221 | } | |||
222 | ||||
223 | QualType CXXBaseObjectRegion::getValueType() const { | |||
224 | return QualType(getDecl()->getTypeForDecl(), 0); | |||
225 | } | |||
226 | ||||
227 | QualType CXXDerivedObjectRegion::getValueType() const { | |||
228 | return QualType(getDecl()->getTypeForDecl(), 0); | |||
229 | } | |||
230 | ||||
231 | //===----------------------------------------------------------------------===// | |||
232 | // FoldingSet profiling. | |||
233 | //===----------------------------------------------------------------------===// | |||
234 | ||||
235 | void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
236 | ID.AddInteger(static_cast<unsigned>(getKind())); | |||
237 | } | |||
238 | ||||
239 | void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
240 | ID.AddInteger(static_cast<unsigned>(getKind())); | |||
241 | ID.AddPointer(getStackFrame()); | |||
242 | } | |||
243 | ||||
244 | void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
245 | ID.AddInteger(static_cast<unsigned>(getKind())); | |||
246 | ID.AddPointer(getCodeRegion()); | |||
247 | } | |||
248 | ||||
249 | void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
250 | const StringLiteral *Str, | |||
251 | const MemRegion *superRegion) { | |||
252 | ID.AddInteger(static_cast<unsigned>(StringRegionKind)); | |||
253 | ID.AddPointer(Str); | |||
254 | ID.AddPointer(superRegion); | |||
255 | } | |||
256 | ||||
257 | void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
258 | const ObjCStringLiteral *Str, | |||
259 | const MemRegion *superRegion) { | |||
260 | ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind)); | |||
261 | ID.AddPointer(Str); | |||
262 | ID.AddPointer(superRegion); | |||
263 | } | |||
264 | ||||
265 | void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
266 | const Expr *Ex, unsigned cnt, | |||
267 | const MemRegion *superRegion) { | |||
268 | ID.AddInteger(static_cast<unsigned>(AllocaRegionKind)); | |||
269 | ID.AddPointer(Ex); | |||
270 | ID.AddInteger(cnt); | |||
271 | ID.AddPointer(superRegion); | |||
272 | } | |||
273 | ||||
274 | void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
275 | ProfileRegion(ID, Ex, Cnt, superRegion); | |||
276 | } | |||
277 | ||||
278 | void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
279 | CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion); | |||
280 | } | |||
281 | ||||
282 | void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
283 | const CompoundLiteralExpr *CL, | |||
284 | const MemRegion* superRegion) { | |||
285 | ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind)); | |||
286 | ID.AddPointer(CL); | |||
287 | ID.AddPointer(superRegion); | |||
288 | } | |||
289 | ||||
290 | void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
291 | const PointerType *PT, | |||
292 | const MemRegion *sRegion) { | |||
293 | ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind)); | |||
294 | ID.AddPointer(PT); | |||
295 | ID.AddPointer(sRegion); | |||
296 | } | |||
297 | ||||
298 | void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
299 | CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); | |||
300 | } | |||
301 | ||||
302 | void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
303 | const ObjCIvarDecl *ivd, | |||
304 | const MemRegion* superRegion) { | |||
305 | DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind); | |||
306 | } | |||
307 | ||||
308 | void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, | |||
309 | const MemRegion* superRegion, Kind k) { | |||
310 | ID.AddInteger(static_cast<unsigned>(k)); | |||
311 | ID.AddPointer(D); | |||
312 | ID.AddPointer(superRegion); | |||
313 | } | |||
314 | ||||
315 | void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
316 | DeclRegion::ProfileRegion(ID, D, superRegion, getKind()); | |||
317 | } | |||
318 | ||||
319 | void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
320 | VarRegion::ProfileRegion(ID, getDecl(), superRegion); | |||
321 | } | |||
322 | ||||
323 | void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, | |||
324 | const MemRegion *sreg) { | |||
325 | ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind)); | |||
326 | ID.Add(sym); | |||
327 | ID.AddPointer(sreg); | |||
328 | } | |||
329 | ||||
330 | void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
331 | SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion()); | |||
332 | } | |||
333 | ||||
334 | void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
335 | QualType ElementType, SVal Idx, | |||
336 | const MemRegion* superRegion) { | |||
337 | ID.AddInteger(MemRegion::ElementRegionKind); | |||
338 | ID.Add(ElementType); | |||
339 | ID.AddPointer(superRegion); | |||
340 | Idx.Profile(ID); | |||
341 | } | |||
342 | ||||
343 | void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
344 | ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); | |||
345 | } | |||
346 | ||||
347 | void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
348 | const NamedDecl *FD, | |||
349 | const MemRegion*) { | |||
350 | ID.AddInteger(MemRegion::FunctionCodeRegionKind); | |||
351 | ID.AddPointer(FD); | |||
352 | } | |||
353 | ||||
354 | void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
355 | FunctionCodeRegion::ProfileRegion(ID, FD, superRegion); | |||
356 | } | |||
357 | ||||
358 | void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
359 | const BlockDecl *BD, CanQualType, | |||
360 | const AnalysisDeclContext *AC, | |||
361 | const MemRegion*) { | |||
362 | ID.AddInteger(MemRegion::BlockCodeRegionKind); | |||
363 | ID.AddPointer(BD); | |||
364 | } | |||
365 | ||||
366 | void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
367 | BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); | |||
368 | } | |||
369 | ||||
370 | void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
371 | const BlockCodeRegion *BC, | |||
372 | const LocationContext *LC, | |||
373 | unsigned BlkCount, | |||
374 | const MemRegion *sReg) { | |||
375 | ID.AddInteger(MemRegion::BlockDataRegionKind); | |||
376 | ID.AddPointer(BC); | |||
377 | ID.AddPointer(LC); | |||
378 | ID.AddInteger(BlkCount); | |||
379 | ID.AddPointer(sReg); | |||
380 | } | |||
381 | ||||
382 | void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
383 | BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion()); | |||
384 | } | |||
385 | ||||
386 | void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
387 | Expr const *Ex, | |||
388 | const MemRegion *sReg) { | |||
389 | ID.AddPointer(Ex); | |||
390 | ID.AddPointer(sReg); | |||
391 | } | |||
392 | ||||
393 | void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
394 | ProfileRegion(ID, Ex, getSuperRegion()); | |||
395 | } | |||
396 | ||||
397 | void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
398 | const CXXRecordDecl *RD, | |||
399 | bool IsVirtual, | |||
400 | const MemRegion *SReg) { | |||
401 | ID.AddPointer(RD); | |||
402 | ID.AddBoolean(IsVirtual); | |||
403 | ID.AddPointer(SReg); | |||
404 | } | |||
405 | ||||
406 | void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
407 | ProfileRegion(ID, getDecl(), isVirtual(), superRegion); | |||
408 | } | |||
409 | ||||
410 | void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
411 | const CXXRecordDecl *RD, | |||
412 | const MemRegion *SReg) { | |||
413 | ID.AddPointer(RD); | |||
414 | ID.AddPointer(SReg); | |||
415 | } | |||
416 | ||||
417 | void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
418 | ProfileRegion(ID, getDecl(), superRegion); | |||
419 | } | |||
420 | ||||
421 | //===----------------------------------------------------------------------===// | |||
422 | // Region anchors. | |||
423 | //===----------------------------------------------------------------------===// | |||
424 | ||||
425 | void GlobalsSpaceRegion::anchor() {} | |||
426 | ||||
427 | void NonStaticGlobalSpaceRegion::anchor() {} | |||
428 | ||||
429 | void StackSpaceRegion::anchor() {} | |||
430 | ||||
431 | void TypedRegion::anchor() {} | |||
432 | ||||
433 | void TypedValueRegion::anchor() {} | |||
434 | ||||
435 | void CodeTextRegion::anchor() {} | |||
436 | ||||
437 | void SubRegion::anchor() {} | |||
438 | ||||
439 | //===----------------------------------------------------------------------===// | |||
440 | // Region pretty-printing. | |||
441 | //===----------------------------------------------------------------------===// | |||
442 | ||||
443 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void MemRegion::dump() const { | |||
444 | dumpToStream(llvm::errs()); | |||
445 | } | |||
446 | ||||
447 | std::string MemRegion::getString() const { | |||
448 | std::string s; | |||
449 | llvm::raw_string_ostream os(s); | |||
450 | dumpToStream(os); | |||
451 | return os.str(); | |||
452 | } | |||
453 | ||||
454 | void MemRegion::dumpToStream(raw_ostream &os) const { | |||
455 | os << "<Unknown Region>"; | |||
456 | } | |||
457 | ||||
458 | void AllocaRegion::dumpToStream(raw_ostream &os) const { | |||
459 | os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}'; | |||
460 | } | |||
461 | ||||
462 | void FunctionCodeRegion::dumpToStream(raw_ostream &os) const { | |||
463 | os << "code{" << getDecl()->getDeclName().getAsString() << '}'; | |||
464 | } | |||
465 | ||||
466 | void BlockCodeRegion::dumpToStream(raw_ostream &os) const { | |||
467 | os << "block_code{" << static_cast<const void *>(this) << '}'; | |||
468 | } | |||
469 | ||||
470 | void BlockDataRegion::dumpToStream(raw_ostream &os) const { | |||
471 | os << "block_data{" << BC; | |||
472 | os << "; "; | |||
473 | for (BlockDataRegion::referenced_vars_iterator | |||
474 | I = referenced_vars_begin(), | |||
475 | E = referenced_vars_end(); I != E; ++I) | |||
476 | os << "(" << I.getCapturedRegion() << "<-" << | |||
477 | I.getOriginalRegion() << ") "; | |||
478 | os << '}'; | |||
479 | } | |||
480 | ||||
481 | void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { | |||
482 | // FIXME: More elaborate pretty-printing. | |||
483 | os << "{ S" << CL->getID(getContext()) << " }"; | |||
484 | } | |||
485 | ||||
486 | void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { | |||
487 | os << "temp_object{" << getValueType().getAsString() << ", " | |||
488 | << "S" << Ex->getID(getContext()) << '}'; | |||
489 | } | |||
490 | ||||
491 | void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { | |||
492 | os << "Base{" << superRegion << ',' << getDecl()->getName() << '}'; | |||
493 | } | |||
494 | ||||
495 | void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const { | |||
496 | os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}'; | |||
497 | } | |||
498 | ||||
499 | void CXXThisRegion::dumpToStream(raw_ostream &os) const { | |||
500 | os << "this"; | |||
501 | } | |||
502 | ||||
503 | void ElementRegion::dumpToStream(raw_ostream &os) const { | |||
504 | os << "Element{" << superRegion << ',' | |||
505 | << Index << ',' << getElementType().getAsString() << '}'; | |||
506 | } | |||
507 | ||||
508 | void FieldRegion::dumpToStream(raw_ostream &os) const { | |||
509 | os << superRegion << "->" << *getDecl(); | |||
510 | } | |||
511 | ||||
512 | void ObjCIvarRegion::dumpToStream(raw_ostream &os) const { | |||
513 | os << "Ivar{" << superRegion << ',' << *getDecl() << '}'; | |||
514 | } | |||
515 | ||||
516 | void StringRegion::dumpToStream(raw_ostream &os) const { | |||
517 | assert(Str != nullptr && "Expecting non-null StringLiteral")((Str != nullptr && "Expecting non-null StringLiteral" ) ? static_cast<void> (0) : __assert_fail ("Str != nullptr && \"Expecting non-null StringLiteral\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 517, __PRETTY_FUNCTION__)); | |||
518 | Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); | |||
519 | } | |||
520 | ||||
521 | void ObjCStringRegion::dumpToStream(raw_ostream &os) const { | |||
522 | assert(Str != nullptr && "Expecting non-null ObjCStringLiteral")((Str != nullptr && "Expecting non-null ObjCStringLiteral" ) ? static_cast<void> (0) : __assert_fail ("Str != nullptr && \"Expecting non-null ObjCStringLiteral\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 522, __PRETTY_FUNCTION__)); | |||
523 | Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); | |||
524 | } | |||
525 | ||||
526 | void SymbolicRegion::dumpToStream(raw_ostream &os) const { | |||
527 | if (isa<HeapSpaceRegion>(getSuperRegion())) | |||
528 | os << "Heap"; | |||
529 | os << "SymRegion{" << sym << '}'; | |||
530 | } | |||
531 | ||||
532 | void VarRegion::dumpToStream(raw_ostream &os) const { | |||
533 | const auto *VD = cast<VarDecl>(D); | |||
534 | if (const IdentifierInfo *ID = VD->getIdentifier()) | |||
535 | os << ID->getName(); | |||
536 | else | |||
537 | os << "VarRegion{D" << VD->getID() << '}'; | |||
538 | } | |||
539 | ||||
540 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void RegionRawOffset::dump() const { | |||
541 | dumpToStream(llvm::errs()); | |||
542 | } | |||
543 | ||||
544 | void RegionRawOffset::dumpToStream(raw_ostream &os) const { | |||
545 | os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}'; | |||
546 | } | |||
547 | ||||
548 | void CodeSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
549 | os << "CodeSpaceRegion"; | |||
550 | } | |||
551 | ||||
552 | void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
553 | os << "StaticGlobalsMemSpace{" << CR << '}'; | |||
554 | } | |||
555 | ||||
556 | void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
557 | os << "GlobalInternalSpaceRegion"; | |||
558 | } | |||
559 | ||||
560 | void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
561 | os << "GlobalSystemSpaceRegion"; | |||
562 | } | |||
563 | ||||
564 | void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
565 | os << "GlobalImmutableSpaceRegion"; | |||
566 | } | |||
567 | ||||
568 | void HeapSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
569 | os << "HeapSpaceRegion"; | |||
570 | } | |||
571 | ||||
572 | void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
573 | os << "UnknownSpaceRegion"; | |||
574 | } | |||
575 | ||||
576 | void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
577 | os << "StackArgumentsSpaceRegion"; | |||
578 | } | |||
579 | ||||
580 | void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
581 | os << "StackLocalsSpaceRegion"; | |||
582 | } | |||
583 | ||||
584 | bool MemRegion::canPrintPretty() const { | |||
585 | return canPrintPrettyAsExpr(); | |||
586 | } | |||
587 | ||||
588 | bool MemRegion::canPrintPrettyAsExpr() const { | |||
589 | return false; | |||
590 | } | |||
591 | ||||
592 | void MemRegion::printPretty(raw_ostream &os) const { | |||
593 | assert(canPrintPretty() && "This region cannot be printed pretty.")((canPrintPretty() && "This region cannot be printed pretty." ) ? static_cast<void> (0) : __assert_fail ("canPrintPretty() && \"This region cannot be printed pretty.\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 593, __PRETTY_FUNCTION__)); | |||
594 | os << "'"; | |||
595 | printPrettyAsExpr(os); | |||
596 | os << "'"; | |||
597 | } | |||
598 | ||||
599 | void MemRegion::printPrettyAsExpr(raw_ostream &) const { | |||
600 | llvm_unreachable("This region cannot be printed pretty.")::llvm::llvm_unreachable_internal("This region cannot be printed pretty." , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 600); | |||
601 | } | |||
602 | ||||
603 | bool VarRegion::canPrintPrettyAsExpr() const { | |||
604 | return true; | |||
605 | } | |||
606 | ||||
607 | void VarRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
608 | os << getDecl()->getName(); | |||
609 | } | |||
610 | ||||
611 | bool ObjCIvarRegion::canPrintPrettyAsExpr() const { | |||
612 | return true; | |||
613 | } | |||
614 | ||||
615 | void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
616 | os << getDecl()->getName(); | |||
617 | } | |||
618 | ||||
619 | bool FieldRegion::canPrintPretty() const { | |||
620 | return true; | |||
621 | } | |||
622 | ||||
623 | bool FieldRegion::canPrintPrettyAsExpr() const { | |||
624 | return superRegion->canPrintPrettyAsExpr(); | |||
625 | } | |||
626 | ||||
627 | void FieldRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
628 | assert(canPrintPrettyAsExpr())((canPrintPrettyAsExpr()) ? static_cast<void> (0) : __assert_fail ("canPrintPrettyAsExpr()", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 628, __PRETTY_FUNCTION__)); | |||
629 | superRegion->printPrettyAsExpr(os); | |||
630 | os << "." << getDecl()->getName(); | |||
631 | } | |||
632 | ||||
633 | void FieldRegion::printPretty(raw_ostream &os) const { | |||
634 | if (canPrintPrettyAsExpr()) { | |||
635 | os << "\'"; | |||
636 | printPrettyAsExpr(os); | |||
637 | os << "'"; | |||
638 | } else { | |||
639 | os << "field " << "\'" << getDecl()->getName() << "'"; | |||
640 | } | |||
641 | } | |||
642 | ||||
643 | bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const { | |||
644 | return superRegion->canPrintPrettyAsExpr(); | |||
645 | } | |||
646 | ||||
647 | void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
648 | superRegion->printPrettyAsExpr(os); | |||
649 | } | |||
650 | ||||
651 | bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const { | |||
652 | return superRegion->canPrintPrettyAsExpr(); | |||
653 | } | |||
654 | ||||
655 | void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
656 | superRegion->printPrettyAsExpr(os); | |||
657 | } | |||
658 | ||||
659 | std::string MemRegion::getDescriptiveName(bool UseQuotes) const { | |||
660 | std::string VariableName; | |||
661 | std::string ArrayIndices; | |||
662 | const MemRegion *R = this; | |||
663 | SmallString<50> buf; | |||
664 | llvm::raw_svector_ostream os(buf); | |||
665 | ||||
666 | // Obtain array indices to add them to the variable name. | |||
667 | const ElementRegion *ER = nullptr; | |||
668 | while ((ER = R->getAs<ElementRegion>())) { | |||
669 | // Index is a ConcreteInt. | |||
670 | if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) { | |||
671 | llvm::SmallString<2> Idx; | |||
672 | CI->getValue().toString(Idx); | |||
673 | ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); | |||
674 | } | |||
675 | // If not a ConcreteInt, try to obtain the variable | |||
676 | // name by calling 'getDescriptiveName' recursively. | |||
677 | else { | |||
678 | std::string Idx = ER->getDescriptiveName(false); | |||
679 | if (!Idx.empty()) { | |||
680 | ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); | |||
681 | } | |||
682 | } | |||
683 | R = ER->getSuperRegion(); | |||
684 | } | |||
685 | ||||
686 | // Get variable name. | |||
687 | if (R && R->canPrintPrettyAsExpr()) { | |||
688 | R->printPrettyAsExpr(os); | |||
689 | if (UseQuotes) | |||
690 | return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str(); | |||
691 | else | |||
692 | return (llvm::Twine(os.str()) + ArrayIndices).str(); | |||
693 | } | |||
694 | ||||
695 | return VariableName; | |||
696 | } | |||
697 | ||||
698 | SourceRange MemRegion::sourceRange() const { | |||
699 | const auto *const VR = dyn_cast<VarRegion>(this->getBaseRegion()); | |||
700 | const auto *const FR = dyn_cast<FieldRegion>(this); | |||
701 | ||||
702 | // Check for more specific regions first. | |||
703 | // FieldRegion | |||
704 | if (FR) { | |||
705 | return FR->getDecl()->getSourceRange(); | |||
706 | } | |||
707 | // VarRegion | |||
708 | else if (VR) { | |||
709 | return VR->getDecl()->getSourceRange(); | |||
710 | } | |||
711 | // Return invalid source range (can be checked by client). | |||
712 | else | |||
713 | return {}; | |||
714 | } | |||
715 | ||||
716 | //===----------------------------------------------------------------------===// | |||
717 | // MemRegionManager methods. | |||
718 | //===----------------------------------------------------------------------===// | |||
719 | ||||
720 | template <typename REG> | |||
721 | const REG *MemRegionManager::LazyAllocate(REG*& region) { | |||
722 | if (!region) { | |||
723 | region = A.Allocate<REG>(); | |||
724 | new (region) REG(this); | |||
725 | } | |||
726 | ||||
727 | return region; | |||
728 | } | |||
729 | ||||
730 | template <typename REG, typename ARG> | |||
731 | const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { | |||
732 | if (!region) { | |||
733 | region = A.Allocate<REG>(); | |||
734 | new (region) REG(this, a); | |||
735 | } | |||
736 | ||||
737 | return region; | |||
738 | } | |||
739 | ||||
740 | const StackLocalsSpaceRegion* | |||
741 | MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { | |||
742 | assert(STC)((STC) ? static_cast<void> (0) : __assert_fail ("STC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 742, __PRETTY_FUNCTION__)); | |||
743 | StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; | |||
744 | ||||
745 | if (R) | |||
746 | return R; | |||
747 | ||||
748 | R = A.Allocate<StackLocalsSpaceRegion>(); | |||
749 | new (R) StackLocalsSpaceRegion(this, STC); | |||
750 | return R; | |||
751 | } | |||
752 | ||||
753 | const StackArgumentsSpaceRegion * | |||
754 | MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { | |||
755 | assert(STC)((STC) ? static_cast<void> (0) : __assert_fail ("STC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 755, __PRETTY_FUNCTION__)); | |||
756 | StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC]; | |||
757 | ||||
758 | if (R) | |||
759 | return R; | |||
760 | ||||
761 | R = A.Allocate<StackArgumentsSpaceRegion>(); | |||
762 | new (R) StackArgumentsSpaceRegion(this, STC); | |||
763 | return R; | |||
764 | } | |||
765 | ||||
766 | const GlobalsSpaceRegion | |||
767 | *MemRegionManager::getGlobalsRegion(MemRegion::Kind K, | |||
768 | const CodeTextRegion *CR) { | |||
769 | if (!CR) { | |||
770 | if (K == MemRegion::GlobalSystemSpaceRegionKind) | |||
771 | return LazyAllocate(SystemGlobals); | |||
772 | if (K == MemRegion::GlobalImmutableSpaceRegionKind) | |||
773 | return LazyAllocate(ImmutableGlobals); | |||
774 | assert(K == MemRegion::GlobalInternalSpaceRegionKind)((K == MemRegion::GlobalInternalSpaceRegionKind) ? static_cast <void> (0) : __assert_fail ("K == MemRegion::GlobalInternalSpaceRegionKind" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 774, __PRETTY_FUNCTION__)); | |||
775 | return LazyAllocate(InternalGlobals); | |||
776 | } | |||
777 | ||||
778 | assert(K == MemRegion::StaticGlobalSpaceRegionKind)((K == MemRegion::StaticGlobalSpaceRegionKind) ? static_cast< void> (0) : __assert_fail ("K == MemRegion::StaticGlobalSpaceRegionKind" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 778, __PRETTY_FUNCTION__)); | |||
779 | StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR]; | |||
780 | if (R) | |||
781 | return R; | |||
782 | ||||
783 | R = A.Allocate<StaticGlobalSpaceRegion>(); | |||
784 | new (R) StaticGlobalSpaceRegion(this, CR); | |||
785 | return R; | |||
786 | } | |||
787 | ||||
788 | const HeapSpaceRegion *MemRegionManager::getHeapRegion() { | |||
789 | return LazyAllocate(heap); | |||
790 | } | |||
791 | ||||
792 | const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() { | |||
793 | return LazyAllocate(unknown); | |||
794 | } | |||
795 | ||||
796 | const CodeSpaceRegion *MemRegionManager::getCodeRegion() { | |||
797 | return LazyAllocate(code); | |||
798 | } | |||
799 | ||||
800 | //===----------------------------------------------------------------------===// | |||
801 | // Constructing regions. | |||
802 | //===----------------------------------------------------------------------===// | |||
803 | ||||
804 | const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){ | |||
805 | return getSubRegion<StringRegion>( | |||
806 | Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); | |||
807 | } | |||
808 | ||||
809 | const ObjCStringRegion * | |||
810 | MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){ | |||
811 | return getSubRegion<ObjCStringRegion>( | |||
812 | Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); | |||
813 | } | |||
814 | ||||
815 | /// Look through a chain of LocationContexts to either find the | |||
816 | /// StackFrameContext that matches a DeclContext, or find a VarRegion | |||
817 | /// for a variable captured by a block. | |||
818 | static llvm::PointerUnion<const StackFrameContext *, const VarRegion *> | |||
819 | getStackOrCaptureRegionForDeclContext(const LocationContext *LC, | |||
820 | const DeclContext *DC, | |||
821 | const VarDecl *VD) { | |||
822 | while (LC) { | |||
823 | if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) { | |||
824 | if (cast<DeclContext>(SFC->getDecl()) == DC) | |||
825 | return SFC; | |||
826 | } | |||
827 | if (const auto *BC = dyn_cast<BlockInvocationContext>(LC)) { | |||
828 | const auto *BR = | |||
829 | static_cast<const BlockDataRegion *>(BC->getContextData()); | |||
830 | // FIXME: This can be made more efficient. | |||
831 | for (BlockDataRegion::referenced_vars_iterator | |||
832 | I = BR->referenced_vars_begin(), | |||
833 | E = BR->referenced_vars_end(); I != E; ++I) { | |||
834 | const VarRegion *VR = I.getOriginalRegion(); | |||
835 | if (VR->getDecl() == VD) | |||
836 | return cast<VarRegion>(I.getCapturedRegion()); | |||
837 | } | |||
838 | } | |||
839 | ||||
840 | LC = LC->getParent(); | |||
841 | } | |||
842 | return (const StackFrameContext *)nullptr; | |||
843 | } | |||
844 | ||||
845 | const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, | |||
846 | const LocationContext *LC) { | |||
847 | D = D->getCanonicalDecl(); | |||
848 | const MemRegion *sReg = nullptr; | |||
849 | ||||
850 | if (D->hasGlobalStorage() && !D->isStaticLocal()) { | |||
851 | ||||
852 | // First handle the globals defined in system headers. | |||
853 | if (C.getSourceManager().isInSystemHeader(D->getLocation())) { | |||
854 | // Whitelist the system globals which often DO GET modified, assume the | |||
855 | // rest are immutable. | |||
856 | if (D->getName().find("errno") != StringRef::npos) | |||
857 | sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); | |||
858 | else | |||
859 | sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); | |||
860 | ||||
861 | // Treat other globals as GlobalInternal unless they are constants. | |||
862 | } else { | |||
863 | QualType GQT = D->getType(); | |||
864 | const Type *GT = GQT.getTypePtrOrNull(); | |||
865 | // TODO: We could walk the complex types here and see if everything is | |||
866 | // constified. | |||
867 | if (GT && GQT.isConstQualified() && GT->isArithmeticType()) | |||
868 | sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); | |||
869 | else | |||
870 | sReg = getGlobalsRegion(); | |||
871 | } | |||
872 | ||||
873 | // Finally handle static locals. | |||
874 | } else { | |||
875 | // FIXME: Once we implement scope handling, we will need to properly lookup | |||
876 | // 'D' to the proper LocationContext. | |||
877 | const DeclContext *DC = D->getDeclContext(); | |||
878 | llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V = | |||
879 | getStackOrCaptureRegionForDeclContext(LC, DC, D); | |||
880 | ||||
881 | if (V.is<const VarRegion*>()) | |||
882 | return V.get<const VarRegion*>(); | |||
883 | ||||
884 | const auto *STC = V.get<const StackFrameContext *>(); | |||
885 | ||||
886 | if (!STC) { | |||
887 | // FIXME: Assign a more sensible memory space to static locals | |||
888 | // we see from within blocks that we analyze as top-level declarations. | |||
889 | sReg = getUnknownRegion(); | |||
890 | } else { | |||
891 | if (D->hasLocalStorage()) { | |||
892 | sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) | |||
893 | ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC)) | |||
894 | : static_cast<const MemRegion*>(getStackLocalsRegion(STC)); | |||
895 | } | |||
896 | else { | |||
897 | assert(D->isStaticLocal())((D->isStaticLocal()) ? static_cast<void> (0) : __assert_fail ("D->isStaticLocal()", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 897, __PRETTY_FUNCTION__)); | |||
898 | const Decl *STCD = STC->getDecl(); | |||
899 | if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD)) | |||
900 | sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, | |||
901 | getFunctionCodeRegion(cast<NamedDecl>(STCD))); | |||
902 | else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) { | |||
903 | // FIXME: The fallback type here is totally bogus -- though it should | |||
904 | // never be queried, it will prevent uniquing with the real | |||
905 | // BlockCodeRegion. Ideally we'd fix the AST so that we always had a | |||
906 | // signature. | |||
907 | QualType T; | |||
908 | if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) | |||
909 | T = TSI->getType(); | |||
910 | if (T.isNull()) | |||
911 | T = getContext().VoidTy; | |||
912 | if (!T->getAs<FunctionType>()) | |||
913 | T = getContext().getFunctionNoProtoType(T); | |||
914 | T = getContext().getBlockPointerType(T); | |||
915 | ||||
916 | const BlockCodeRegion *BTR = | |||
917 | getBlockCodeRegion(BD, C.getCanonicalType(T), | |||
918 | STC->getAnalysisDeclContext()); | |||
919 | sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, | |||
920 | BTR); | |||
921 | } | |||
922 | else { | |||
923 | sReg = getGlobalsRegion(); | |||
924 | } | |||
925 | } | |||
926 | } | |||
927 | } | |||
928 | ||||
929 | return getSubRegion<VarRegion>(D, sReg); | |||
930 | } | |||
931 | ||||
932 | const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, | |||
933 | const MemRegion *superR) { | |||
934 | D = D->getCanonicalDecl(); | |||
935 | return getSubRegion<VarRegion>(D, superR); | |||
936 | } | |||
937 | ||||
938 | const BlockDataRegion * | |||
939 | MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, | |||
940 | const LocationContext *LC, | |||
941 | unsigned blockCount) { | |||
942 | const MemSpaceRegion *sReg = nullptr; | |||
943 | const BlockDecl *BD = BC->getDecl(); | |||
944 | if (!BD->hasCaptures()) { | |||
945 | // This handles 'static' blocks. | |||
946 | sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); | |||
947 | } | |||
948 | else { | |||
949 | if (LC) { | |||
950 | // FIXME: Once we implement scope handling, we want the parent region | |||
951 | // to be the scope. | |||
952 | const StackFrameContext *STC = LC->getStackFrame(); | |||
953 | assert(STC)((STC) ? static_cast<void> (0) : __assert_fail ("STC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 953, __PRETTY_FUNCTION__)); | |||
954 | sReg = getStackLocalsRegion(STC); | |||
955 | } | |||
956 | else { | |||
957 | // We allow 'LC' to be NULL for cases where want BlockDataRegions | |||
958 | // without context-sensitivity. | |||
959 | sReg = getUnknownRegion(); | |||
960 | } | |||
961 | } | |||
962 | ||||
963 | return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg); | |||
964 | } | |||
965 | ||||
966 | const CXXTempObjectRegion * | |||
967 | MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) { | |||
968 | return getSubRegion<CXXTempObjectRegion>( | |||
969 | Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr)); | |||
970 | } | |||
971 | ||||
972 | const CompoundLiteralRegion* | |||
973 | MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, | |||
974 | const LocationContext *LC) { | |||
975 | const MemSpaceRegion *sReg = nullptr; | |||
976 | ||||
977 | if (CL->isFileScope()) | |||
978 | sReg = getGlobalsRegion(); | |||
979 | else { | |||
980 | const StackFrameContext *STC = LC->getStackFrame(); | |||
981 | assert(STC)((STC) ? static_cast<void> (0) : __assert_fail ("STC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 981, __PRETTY_FUNCTION__)); | |||
982 | sReg = getStackLocalsRegion(STC); | |||
983 | } | |||
984 | ||||
985 | return getSubRegion<CompoundLiteralRegion>(CL, sReg); | |||
986 | } | |||
987 | ||||
988 | const ElementRegion* | |||
989 | MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, | |||
990 | const SubRegion* superRegion, | |||
991 | ASTContext &Ctx){ | |||
992 | QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); | |||
993 | ||||
994 | llvm::FoldingSetNodeID ID; | |||
995 | ElementRegion::ProfileRegion(ID, T, Idx, superRegion); | |||
996 | ||||
997 | void *InsertPos; | |||
998 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | |||
999 | auto *R = cast_or_null<ElementRegion>(data); | |||
1000 | ||||
1001 | if (!R) { | |||
1002 | R = A.Allocate<ElementRegion>(); | |||
1003 | new (R) ElementRegion(T, Idx, superRegion); | |||
1004 | Regions.InsertNode(R, InsertPos); | |||
1005 | } | |||
1006 | ||||
1007 | return R; | |||
1008 | } | |||
1009 | ||||
1010 | const FunctionCodeRegion * | |||
1011 | MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) { | |||
1012 | // To think: should we canonicalize the declaration here? | |||
1013 | return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion()); | |||
1014 | } | |||
1015 | ||||
1016 | const BlockCodeRegion * | |||
1017 | MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, | |||
1018 | AnalysisDeclContext *AC) { | |||
1019 | return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion()); | |||
1020 | } | |||
1021 | ||||
1022 | /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. | |||
1023 | const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) { | |||
1024 | return getSubRegion<SymbolicRegion>(sym, getUnknownRegion()); | |||
1025 | } | |||
1026 | ||||
1027 | const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) { | |||
1028 | return getSubRegion<SymbolicRegion>(Sym, getHeapRegion()); | |||
1029 | } | |||
1030 | ||||
1031 | const FieldRegion* | |||
1032 | MemRegionManager::getFieldRegion(const FieldDecl *d, | |||
1033 | const SubRegion* superRegion){ | |||
1034 | return getSubRegion<FieldRegion>(d, superRegion); | |||
1035 | } | |||
1036 | ||||
1037 | const ObjCIvarRegion* | |||
1038 | MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, | |||
1039 | const SubRegion* superRegion) { | |||
1040 | return getSubRegion<ObjCIvarRegion>(d, superRegion); | |||
1041 | } | |||
1042 | ||||
1043 | const CXXTempObjectRegion* | |||
1044 | MemRegionManager::getCXXTempObjectRegion(Expr const *E, | |||
1045 | LocationContext const *LC) { | |||
1046 | const StackFrameContext *SFC = LC->getStackFrame(); | |||
1047 | assert(SFC)((SFC) ? static_cast<void> (0) : __assert_fail ("SFC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1047, __PRETTY_FUNCTION__)); | |||
1048 | return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC)); | |||
1049 | } | |||
1050 | ||||
1051 | /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base | |||
1052 | /// class of the type of \p Super. | |||
1053 | static bool isValidBaseClass(const CXXRecordDecl *BaseClass, | |||
1054 | const TypedValueRegion *Super, | |||
1055 | bool IsVirtual) { | |||
1056 | BaseClass = BaseClass->getCanonicalDecl(); | |||
1057 | ||||
1058 | const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl(); | |||
1059 | if (!Class) | |||
1060 | return true; | |||
1061 | ||||
1062 | if (IsVirtual) | |||
1063 | return Class->isVirtuallyDerivedFrom(BaseClass); | |||
1064 | ||||
1065 | for (const auto &I : Class->bases()) { | |||
1066 | if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass) | |||
1067 | return true; | |||
1068 | } | |||
1069 | ||||
1070 | return false; | |||
1071 | } | |||
1072 | ||||
1073 | const CXXBaseObjectRegion * | |||
1074 | MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, | |||
1075 | const SubRegion *Super, | |||
1076 | bool IsVirtual) { | |||
1077 | if (isa<TypedValueRegion>(Super)) { | |||
1078 | assert(isValidBaseClass(RD, dyn_cast<TypedValueRegion>(Super), IsVirtual))((isValidBaseClass(RD, dyn_cast<TypedValueRegion>(Super ), IsVirtual)) ? static_cast<void> (0) : __assert_fail ( "isValidBaseClass(RD, dyn_cast<TypedValueRegion>(Super), IsVirtual)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1078, __PRETTY_FUNCTION__)); | |||
1079 | (void)&isValidBaseClass; | |||
1080 | ||||
1081 | if (IsVirtual) { | |||
1082 | // Virtual base regions should not be layered, since the layout rules | |||
1083 | // are different. | |||
1084 | while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super)) | |||
1085 | Super = cast<SubRegion>(Base->getSuperRegion()); | |||
1086 | assert(Super && !isa<MemSpaceRegion>(Super))((Super && !isa<MemSpaceRegion>(Super)) ? static_cast <void> (0) : __assert_fail ("Super && !isa<MemSpaceRegion>(Super)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1086, __PRETTY_FUNCTION__)); | |||
1087 | } | |||
1088 | } | |||
1089 | ||||
1090 | return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super); | |||
1091 | } | |||
1092 | ||||
1093 | const CXXDerivedObjectRegion * | |||
1094 | MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD, | |||
1095 | const SubRegion *Super) { | |||
1096 | return getSubRegion<CXXDerivedObjectRegion>(RD, Super); | |||
1097 | } | |||
1098 | ||||
1099 | const CXXThisRegion* | |||
1100 | MemRegionManager::getCXXThisRegion(QualType thisPointerTy, | |||
1101 | const LocationContext *LC) { | |||
1102 | const auto *PT = thisPointerTy->getAs<PointerType>(); | |||
1103 | assert(PT)((PT) ? static_cast<void> (0) : __assert_fail ("PT", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1103, __PRETTY_FUNCTION__)); | |||
1104 | // Inside the body of the operator() of a lambda a this expr might refer to an | |||
1105 | // object in one of the parent location contexts. | |||
1106 | const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl()); | |||
1107 | // FIXME: when operator() of lambda is analyzed as a top level function and | |||
1108 | // 'this' refers to a this to the enclosing scope, there is no right region to | |||
1109 | // return. | |||
1110 | while (!LC->inTopFrame() && (!D || D->isStatic() || | |||
1111 | PT != D->getThisType()->getAs<PointerType>())) { | |||
1112 | LC = LC->getParent(); | |||
1113 | D = dyn_cast<CXXMethodDecl>(LC->getDecl()); | |||
1114 | } | |||
1115 | const StackFrameContext *STC = LC->getStackFrame(); | |||
1116 | assert(STC)((STC) ? static_cast<void> (0) : __assert_fail ("STC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1116, __PRETTY_FUNCTION__)); | |||
1117 | return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); | |||
1118 | } | |||
1119 | ||||
1120 | const AllocaRegion* | |||
1121 | MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, | |||
1122 | const LocationContext *LC) { | |||
1123 | const StackFrameContext *STC = LC->getStackFrame(); | |||
1124 | assert(STC)((STC) ? static_cast<void> (0) : __assert_fail ("STC", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1124, __PRETTY_FUNCTION__)); | |||
1125 | return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC)); | |||
1126 | } | |||
1127 | ||||
1128 | const MemSpaceRegion *MemRegion::getMemorySpace() const { | |||
1129 | const MemRegion *R = this; | |||
1130 | const auto *SR = dyn_cast<SubRegion>(this); | |||
1131 | ||||
1132 | while (SR) { | |||
1133 | R = SR->getSuperRegion(); | |||
1134 | SR = dyn_cast<SubRegion>(R); | |||
1135 | } | |||
1136 | ||||
1137 | return dyn_cast<MemSpaceRegion>(R); | |||
1138 | } | |||
1139 | ||||
1140 | bool MemRegion::hasStackStorage() const { | |||
1141 | return isa<StackSpaceRegion>(getMemorySpace()); | |||
1142 | } | |||
1143 | ||||
1144 | bool MemRegion::hasStackNonParametersStorage() const { | |||
1145 | return isa<StackLocalsSpaceRegion>(getMemorySpace()); | |||
1146 | } | |||
1147 | ||||
1148 | bool MemRegion::hasStackParametersStorage() const { | |||
1149 | return isa<StackArgumentsSpaceRegion>(getMemorySpace()); | |||
1150 | } | |||
1151 | ||||
1152 | bool MemRegion::hasGlobalsOrParametersStorage() const { | |||
1153 | const MemSpaceRegion *MS = getMemorySpace(); | |||
1154 | return isa<StackArgumentsSpaceRegion>(MS) || | |||
1155 | isa<GlobalsSpaceRegion>(MS); | |||
1156 | } | |||
1157 | ||||
1158 | // getBaseRegion strips away all elements and fields, and get the base region | |||
1159 | // of them. | |||
1160 | const MemRegion *MemRegion::getBaseRegion() const { | |||
1161 | const MemRegion *R = this; | |||
1162 | while (true) { | |||
1163 | switch (R->getKind()) { | |||
1164 | case MemRegion::ElementRegionKind: | |||
1165 | case MemRegion::FieldRegionKind: | |||
1166 | case MemRegion::ObjCIvarRegionKind: | |||
1167 | case MemRegion::CXXBaseObjectRegionKind: | |||
1168 | case MemRegion::CXXDerivedObjectRegionKind: | |||
1169 | R = cast<SubRegion>(R)->getSuperRegion(); | |||
1170 | continue; | |||
1171 | default: | |||
1172 | break; | |||
1173 | } | |||
1174 | break; | |||
1175 | } | |||
1176 | return R; | |||
1177 | } | |||
1178 | ||||
1179 | // getgetMostDerivedObjectRegion gets the region of the root class of a C++ | |||
1180 | // class hierarchy. | |||
1181 | const MemRegion *MemRegion::getMostDerivedObjectRegion() const { | |||
1182 | const MemRegion *R = this; | |||
1183 | while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R)) | |||
1184 | R = BR->getSuperRegion(); | |||
1185 | return R; | |||
1186 | } | |||
1187 | ||||
1188 | bool MemRegion::isSubRegionOf(const MemRegion *) const { | |||
1189 | return false; | |||
1190 | } | |||
1191 | ||||
1192 | //===----------------------------------------------------------------------===// | |||
1193 | // View handling. | |||
1194 | //===----------------------------------------------------------------------===// | |||
1195 | ||||
1196 | const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const { | |||
1197 | const MemRegion *R = this; | |||
1198 | while (true) { | |||
1199 | switch (R->getKind()) { | |||
1200 | case ElementRegionKind: { | |||
1201 | const auto *ER = cast<ElementRegion>(R); | |||
1202 | if (!ER->getIndex().isZeroConstant()) | |||
1203 | return R; | |||
1204 | R = ER->getSuperRegion(); | |||
1205 | break; | |||
1206 | } | |||
1207 | case CXXBaseObjectRegionKind: | |||
1208 | case CXXDerivedObjectRegionKind: | |||
1209 | if (!StripBaseAndDerivedCasts) | |||
1210 | return R; | |||
1211 | R = cast<TypedValueRegion>(R)->getSuperRegion(); | |||
1212 | break; | |||
1213 | default: | |||
1214 | return R; | |||
1215 | } | |||
1216 | } | |||
1217 | } | |||
1218 | ||||
1219 | const SymbolicRegion *MemRegion::getSymbolicBase() const { | |||
1220 | const auto *SubR = dyn_cast<SubRegion>(this); | |||
1221 | ||||
1222 | while (SubR) { | |||
1223 | if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR)) | |||
1224 | return SymR; | |||
1225 | SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); | |||
1226 | } | |||
1227 | return nullptr; | |||
1228 | } | |||
1229 | ||||
1230 | RegionRawOffset ElementRegion::getAsArrayOffset() const { | |||
1231 | int64_t offset = 0; | |||
1232 | const ElementRegion *ER = this; | |||
1233 | const MemRegion *superR = nullptr; | |||
1234 | ASTContext &C = getContext(); | |||
1235 | ||||
1236 | // FIXME: Handle multi-dimensional arrays. | |||
1237 | ||||
1238 | while (ER) { | |||
1239 | superR = ER->getSuperRegion(); | |||
1240 | ||||
1241 | // FIXME: generalize to symbolic offsets. | |||
1242 | SVal index = ER->getIndex(); | |||
1243 | if (auto CI = index.getAs<nonloc::ConcreteInt>()) { | |||
1244 | // Update the offset. | |||
1245 | int64_t i = CI->getValue().getSExtValue(); | |||
1246 | ||||
1247 | if (i != 0) { | |||
1248 | QualType elemType = ER->getElementType(); | |||
1249 | ||||
1250 | // If we are pointing to an incomplete type, go no further. | |||
1251 | if (elemType->isIncompleteType()) { | |||
1252 | superR = ER; | |||
1253 | break; | |||
1254 | } | |||
1255 | ||||
1256 | int64_t size = C.getTypeSizeInChars(elemType).getQuantity(); | |||
1257 | if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) { | |||
1258 | offset = *NewOffset; | |||
1259 | } else { | |||
1260 | LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("MemRegion")) { llvm::dbgs() << "MemRegion::getAsArrayOffset: " << "offset overflowing, returning unknown\n"; } } while (false) | |||
1261 | << "offset overflowing, returning unknown\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("MemRegion")) { llvm::dbgs() << "MemRegion::getAsArrayOffset: " << "offset overflowing, returning unknown\n"; } } while (false); | |||
1262 | ||||
1263 | return nullptr; | |||
1264 | } | |||
1265 | } | |||
1266 | ||||
1267 | // Go to the next ElementRegion (if any). | |||
1268 | ER = dyn_cast<ElementRegion>(superR); | |||
1269 | continue; | |||
1270 | } | |||
1271 | ||||
1272 | return nullptr; | |||
1273 | } | |||
1274 | ||||
1275 | assert(superR && "super region cannot be NULL")((superR && "super region cannot be NULL") ? static_cast <void> (0) : __assert_fail ("superR && \"super region cannot be NULL\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1275, __PRETTY_FUNCTION__)); | |||
1276 | return RegionRawOffset(superR, CharUnits::fromQuantity(offset)); | |||
1277 | } | |||
1278 | ||||
1279 | /// Returns true if \p Base is an immediate base class of \p Child | |||
1280 | static bool isImmediateBase(const CXXRecordDecl *Child, | |||
1281 | const CXXRecordDecl *Base) { | |||
1282 | assert(Child && "Child must not be null")((Child && "Child must not be null") ? static_cast< void> (0) : __assert_fail ("Child && \"Child must not be null\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1282, __PRETTY_FUNCTION__)); | |||
1283 | // Note that we do NOT canonicalize the base class here, because | |||
1284 | // ASTRecordLayout doesn't either. If that leads us down the wrong path, | |||
1285 | // so be it; at least we won't crash. | |||
1286 | for (const auto &I : Child->bases()) { | |||
1287 | if (I.getType()->getAsCXXRecordDecl() == Base) | |||
1288 | return true; | |||
1289 | } | |||
1290 | ||||
1291 | return false; | |||
1292 | } | |||
1293 | ||||
1294 | static RegionOffset calculateOffset(const MemRegion *R) { | |||
1295 | const MemRegion *SymbolicOffsetBase = nullptr; | |||
1296 | int64_t Offset = 0; | |||
1297 | ||||
1298 | while (true) { | |||
1299 | switch (R->getKind()) { | |||
1300 | case MemRegion::CodeSpaceRegionKind: | |||
1301 | case MemRegion::StackLocalsSpaceRegionKind: | |||
1302 | case MemRegion::StackArgumentsSpaceRegionKind: | |||
1303 | case MemRegion::HeapSpaceRegionKind: | |||
1304 | case MemRegion::UnknownSpaceRegionKind: | |||
1305 | case MemRegion::StaticGlobalSpaceRegionKind: | |||
1306 | case MemRegion::GlobalInternalSpaceRegionKind: | |||
1307 | case MemRegion::GlobalSystemSpaceRegionKind: | |||
1308 | case MemRegion::GlobalImmutableSpaceRegionKind: | |||
1309 | // Stores can bind directly to a region space to set a default value. | |||
1310 | assert(Offset == 0 && !SymbolicOffsetBase)((Offset == 0 && !SymbolicOffsetBase) ? static_cast< void> (0) : __assert_fail ("Offset == 0 && !SymbolicOffsetBase" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1310, __PRETTY_FUNCTION__)); | |||
1311 | goto Finish; | |||
1312 | ||||
1313 | case MemRegion::FunctionCodeRegionKind: | |||
1314 | case MemRegion::BlockCodeRegionKind: | |||
1315 | case MemRegion::BlockDataRegionKind: | |||
1316 | // These will never have bindings, but may end up having values requested | |||
1317 | // if the user does some strange casting. | |||
1318 | if (Offset != 0) | |||
1319 | SymbolicOffsetBase = R; | |||
1320 | goto Finish; | |||
1321 | ||||
1322 | case MemRegion::SymbolicRegionKind: | |||
1323 | case MemRegion::AllocaRegionKind: | |||
1324 | case MemRegion::CompoundLiteralRegionKind: | |||
1325 | case MemRegion::CXXThisRegionKind: | |||
1326 | case MemRegion::StringRegionKind: | |||
1327 | case MemRegion::ObjCStringRegionKind: | |||
1328 | case MemRegion::VarRegionKind: | |||
1329 | case MemRegion::CXXTempObjectRegionKind: | |||
1330 | // Usual base regions. | |||
1331 | goto Finish; | |||
1332 | ||||
1333 | case MemRegion::ObjCIvarRegionKind: | |||
1334 | // This is a little strange, but it's a compromise between | |||
1335 | // ObjCIvarRegions having unknown compile-time offsets (when using the | |||
1336 | // non-fragile runtime) and yet still being distinct, non-overlapping | |||
1337 | // regions. Thus we treat them as "like" base regions for the purposes | |||
1338 | // of computing offsets. | |||
1339 | goto Finish; | |||
1340 | ||||
1341 | case MemRegion::CXXBaseObjectRegionKind: { | |||
1342 | const auto *BOR = cast<CXXBaseObjectRegion>(R); | |||
1343 | R = BOR->getSuperRegion(); | |||
1344 | ||||
1345 | QualType Ty; | |||
1346 | bool RootIsSymbolic = false; | |||
1347 | if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) { | |||
1348 | Ty = TVR->getDesugaredValueType(R->getContext()); | |||
1349 | } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) { | |||
1350 | // If our base region is symbolic, we don't know what type it really is. | |||
1351 | // Pretend the type of the symbol is the true dynamic type. | |||
1352 | // (This will at least be self-consistent for the life of the symbol.) | |||
1353 | Ty = SR->getSymbol()->getType()->getPointeeType(); | |||
1354 | RootIsSymbolic = true; | |||
1355 | } | |||
1356 | ||||
1357 | const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl(); | |||
1358 | if (!Child) { | |||
1359 | // We cannot compute the offset of the base class. | |||
1360 | SymbolicOffsetBase = R; | |||
1361 | } else { | |||
1362 | if (RootIsSymbolic) { | |||
1363 | // Base layers on symbolic regions may not be type-correct. | |||
1364 | // Double-check the inheritance here, and revert to a symbolic offset | |||
1365 | // if it's invalid (e.g. due to a reinterpret_cast). | |||
1366 | if (BOR->isVirtual()) { | |||
1367 | if (!Child->isVirtuallyDerivedFrom(BOR->getDecl())) | |||
1368 | SymbolicOffsetBase = R; | |||
1369 | } else { | |||
1370 | if (!isImmediateBase(Child, BOR->getDecl())) | |||
1371 | SymbolicOffsetBase = R; | |||
1372 | } | |||
1373 | } | |||
1374 | } | |||
1375 | ||||
1376 | // Don't bother calculating precise offsets if we already have a | |||
1377 | // symbolic offset somewhere in the chain. | |||
1378 | if (SymbolicOffsetBase) | |||
1379 | continue; | |||
1380 | ||||
1381 | CharUnits BaseOffset; | |||
1382 | const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child); | |||
1383 | if (BOR->isVirtual()) | |||
1384 | BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl()); | |||
1385 | else | |||
1386 | BaseOffset = Layout.getBaseClassOffset(BOR->getDecl()); | |||
1387 | ||||
1388 | // The base offset is in chars, not in bits. | |||
1389 | Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth(); | |||
1390 | break; | |||
1391 | } | |||
1392 | ||||
1393 | case MemRegion::CXXDerivedObjectRegionKind: { | |||
1394 | // TODO: Store the base type in the CXXDerivedObjectRegion and use it. | |||
1395 | goto Finish; | |||
1396 | } | |||
1397 | ||||
1398 | case MemRegion::ElementRegionKind: { | |||
1399 | const auto *ER = cast<ElementRegion>(R); | |||
1400 | R = ER->getSuperRegion(); | |||
1401 | ||||
1402 | QualType EleTy = ER->getValueType(); | |||
1403 | if (EleTy->isIncompleteType()) { | |||
1404 | // We cannot compute the offset of the base class. | |||
1405 | SymbolicOffsetBase = R; | |||
1406 | continue; | |||
1407 | } | |||
1408 | ||||
1409 | SVal Index = ER->getIndex(); | |||
1410 | if (Optional<nonloc::ConcreteInt> CI = | |||
1411 | Index.getAs<nonloc::ConcreteInt>()) { | |||
1412 | // Don't bother calculating precise offsets if we already have a | |||
1413 | // symbolic offset somewhere in the chain. | |||
1414 | if (SymbolicOffsetBase) | |||
1415 | continue; | |||
1416 | ||||
1417 | int64_t i = CI->getValue().getSExtValue(); | |||
1418 | // This type size is in bits. | |||
1419 | Offset += i * R->getContext().getTypeSize(EleTy); | |||
1420 | } else { | |||
1421 | // We cannot compute offset for non-concrete index. | |||
1422 | SymbolicOffsetBase = R; | |||
1423 | } | |||
1424 | break; | |||
1425 | } | |||
1426 | case MemRegion::FieldRegionKind: { | |||
1427 | const auto *FR = cast<FieldRegion>(R); | |||
1428 | R = FR->getSuperRegion(); | |||
1429 | ||||
1430 | const RecordDecl *RD = FR->getDecl()->getParent(); | |||
1431 | if (RD->isUnion() || !RD->isCompleteDefinition()) { | |||
1432 | // We cannot compute offset for incomplete type. | |||
1433 | // For unions, we could treat everything as offset 0, but we'd rather | |||
1434 | // treat each field as a symbolic offset so they aren't stored on top | |||
1435 | // of each other, since we depend on things in typed regions actually | |||
1436 | // matching their types. | |||
1437 | SymbolicOffsetBase = R; | |||
1438 | } | |||
1439 | ||||
1440 | // Don't bother calculating precise offsets if we already have a | |||
1441 | // symbolic offset somewhere in the chain. | |||
1442 | if (SymbolicOffsetBase) | |||
1443 | continue; | |||
1444 | ||||
1445 | // Get the field number. | |||
1446 | unsigned idx = 0; | |||
1447 | for (RecordDecl::field_iterator FI = RD->field_begin(), | |||
1448 | FE = RD->field_end(); FI != FE; ++FI, ++idx) { | |||
1449 | if (FR->getDecl() == *FI) | |||
1450 | break; | |||
1451 | } | |||
1452 | const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD); | |||
| ||||
1453 | // This is offset in bits. | |||
1454 | Offset += Layout.getFieldOffset(idx); | |||
1455 | break; | |||
1456 | } | |||
1457 | } | |||
1458 | } | |||
1459 | ||||
1460 | Finish: | |||
1461 | if (SymbolicOffsetBase) | |||
1462 | return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic); | |||
1463 | return RegionOffset(R, Offset); | |||
1464 | } | |||
1465 | ||||
1466 | RegionOffset MemRegion::getAsOffset() const { | |||
1467 | if (!cachedOffset) | |||
| ||||
1468 | cachedOffset = calculateOffset(this); | |||
1469 | return *cachedOffset; | |||
1470 | } | |||
1471 | ||||
1472 | //===----------------------------------------------------------------------===// | |||
1473 | // BlockDataRegion | |||
1474 | //===----------------------------------------------------------------------===// | |||
1475 | ||||
1476 | std::pair<const VarRegion *, const VarRegion *> | |||
1477 | BlockDataRegion::getCaptureRegions(const VarDecl *VD) { | |||
1478 | MemRegionManager &MemMgr = *getMemRegionManager(); | |||
1479 | const VarRegion *VR = nullptr; | |||
1480 | const VarRegion *OriginalVR = nullptr; | |||
1481 | ||||
1482 | if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) { | |||
1483 | VR = MemMgr.getVarRegion(VD, this); | |||
1484 | OriginalVR = MemMgr.getVarRegion(VD, LC); | |||
1485 | } | |||
1486 | else { | |||
1487 | if (LC) { | |||
1488 | VR = MemMgr.getVarRegion(VD, LC); | |||
1489 | OriginalVR = VR; | |||
1490 | } | |||
1491 | else { | |||
1492 | VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion()); | |||
1493 | OriginalVR = MemMgr.getVarRegion(VD, LC); | |||
1494 | } | |||
1495 | } | |||
1496 | return std::make_pair(VR, OriginalVR); | |||
1497 | } | |||
1498 | ||||
1499 | void BlockDataRegion::LazyInitializeReferencedVars() { | |||
1500 | if (ReferencedVars) | |||
1501 | return; | |||
1502 | ||||
1503 | AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext(); | |||
1504 | const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl()); | |||
1505 | auto NumBlockVars = | |||
1506 | std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end()); | |||
1507 | ||||
1508 | if (NumBlockVars == 0) { | |||
1509 | ReferencedVars = (void*) 0x1; | |||
1510 | return; | |||
1511 | } | |||
1512 | ||||
1513 | MemRegionManager &MemMgr = *getMemRegionManager(); | |||
1514 | llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); | |||
1515 | BumpVectorContext BC(A); | |||
1516 | ||||
1517 | using VarVec = BumpVector<const MemRegion *>; | |||
1518 | ||||
1519 | auto *BV = A.Allocate<VarVec>(); | |||
1520 | new (BV) VarVec(BC, NumBlockVars); | |||
1521 | auto *BVOriginal = A.Allocate<VarVec>(); | |||
1522 | new (BVOriginal) VarVec(BC, NumBlockVars); | |||
1523 | ||||
1524 | for (const auto *VD : ReferencedBlockVars) { | |||
1525 | const VarRegion *VR = nullptr; | |||
1526 | const VarRegion *OriginalVR = nullptr; | |||
1527 | std::tie(VR, OriginalVR) = getCaptureRegions(VD); | |||
1528 | assert(VR)((VR) ? static_cast<void> (0) : __assert_fail ("VR", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1528, __PRETTY_FUNCTION__)); | |||
1529 | assert(OriginalVR)((OriginalVR) ? static_cast<void> (0) : __assert_fail ( "OriginalVR", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1529, __PRETTY_FUNCTION__)); | |||
1530 | BV->push_back(VR, BC); | |||
1531 | BVOriginal->push_back(OriginalVR, BC); | |||
1532 | } | |||
1533 | ||||
1534 | ReferencedVars = BV; | |||
1535 | OriginalVars = BVOriginal; | |||
1536 | } | |||
1537 | ||||
1538 | BlockDataRegion::referenced_vars_iterator | |||
1539 | BlockDataRegion::referenced_vars_begin() const { | |||
1540 | const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); | |||
1541 | ||||
1542 | auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); | |||
1543 | ||||
1544 | if (Vec == (void*) 0x1) | |||
1545 | return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); | |||
1546 | ||||
1547 | auto *VecOriginal = | |||
1548 | static_cast<BumpVector<const MemRegion *> *>(OriginalVars); | |||
1549 | ||||
1550 | return BlockDataRegion::referenced_vars_iterator(Vec->begin(), | |||
1551 | VecOriginal->begin()); | |||
1552 | } | |||
1553 | ||||
1554 | BlockDataRegion::referenced_vars_iterator | |||
1555 | BlockDataRegion::referenced_vars_end() const { | |||
1556 | const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); | |||
1557 | ||||
1558 | auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); | |||
1559 | ||||
1560 | if (Vec == (void*) 0x1) | |||
1561 | return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); | |||
1562 | ||||
1563 | auto *VecOriginal = | |||
1564 | static_cast<BumpVector<const MemRegion *> *>(OriginalVars); | |||
1565 | ||||
1566 | return BlockDataRegion::referenced_vars_iterator(Vec->end(), | |||
1567 | VecOriginal->end()); | |||
1568 | } | |||
1569 | ||||
1570 | const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const { | |||
1571 | for (referenced_vars_iterator I = referenced_vars_begin(), | |||
1572 | E = referenced_vars_end(); | |||
1573 | I != E; ++I) { | |||
1574 | if (I.getCapturedRegion() == R) | |||
1575 | return I.getOriginalRegion(); | |||
1576 | } | |||
1577 | return nullptr; | |||
1578 | } | |||
1579 | ||||
1580 | //===----------------------------------------------------------------------===// | |||
1581 | // RegionAndSymbolInvalidationTraits | |||
1582 | //===----------------------------------------------------------------------===// | |||
1583 | ||||
1584 | void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym, | |||
1585 | InvalidationKinds IK) { | |||
1586 | SymTraitsMap[Sym] |= IK; | |||
1587 | } | |||
1588 | ||||
1589 | void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR, | |||
1590 | InvalidationKinds IK) { | |||
1591 | assert(MR)((MR) ? static_cast<void> (0) : __assert_fail ("MR", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1591, __PRETTY_FUNCTION__)); | |||
1592 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) | |||
1593 | setTrait(SR->getSymbol(), IK); | |||
1594 | else | |||
1595 | MRTraitsMap[MR] |= IK; | |||
1596 | } | |||
1597 | ||||
1598 | bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym, | |||
1599 | InvalidationKinds IK) const { | |||
1600 | const_symbol_iterator I = SymTraitsMap.find(Sym); | |||
1601 | if (I != SymTraitsMap.end()) | |||
1602 | return I->second & IK; | |||
1603 | ||||
1604 | return false; | |||
1605 | } | |||
1606 | ||||
1607 | bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR, | |||
1608 | InvalidationKinds IK) const { | |||
1609 | if (!MR) | |||
1610 | return false; | |||
1611 | ||||
1612 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) | |||
1613 | return hasTrait(SR->getSymbol(), IK); | |||
1614 | ||||
1615 | const_region_iterator I = MRTraitsMap.find(MR); | |||
1616 | if (I != MRTraitsMap.end()) | |||
1617 | return I->second & IK; | |||
1618 | ||||
1619 | return false; | |||
1620 | } |
1 | //==- MemRegion.h - Abstract memory regions for static analysis -*- C++ -*--==// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines MemRegion and its subclasses. MemRegion defines a |
10 | // partially-typed abstraction of memory useful for path-sensitive dataflow |
11 | // analyses. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H |
16 | #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H |
17 | |
18 | #include "clang/AST/ASTContext.h" |
19 | #include "clang/AST/CharUnits.h" |
20 | #include "clang/AST/Decl.h" |
21 | #include "clang/AST/DeclObjC.h" |
22 | #include "clang/AST/DeclarationName.h" |
23 | #include "clang/AST/Expr.h" |
24 | #include "clang/AST/ExprObjC.h" |
25 | #include "clang/AST/Type.h" |
26 | #include "clang/Analysis/AnalysisDeclContext.h" |
27 | #include "clang/Basic/LLVM.h" |
28 | #include "clang/Basic/SourceLocation.h" |
29 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" |
30 | #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" |
31 | #include "llvm/ADT/DenseMap.h" |
32 | #include "llvm/ADT/FoldingSet.h" |
33 | #include "llvm/ADT/Optional.h" |
34 | #include "llvm/ADT/PointerIntPair.h" |
35 | #include "llvm/Support/Allocator.h" |
36 | #include "llvm/Support/Casting.h" |
37 | #include <cassert> |
38 | #include <cstdint> |
39 | #include <limits> |
40 | #include <string> |
41 | #include <utility> |
42 | |
43 | namespace clang { |
44 | |
45 | class AnalysisDeclContext; |
46 | class CXXRecordDecl; |
47 | class Decl; |
48 | class LocationContext; |
49 | class StackFrameContext; |
50 | |
51 | namespace ento { |
52 | |
53 | class CodeTextRegion; |
54 | class MemRegion; |
55 | class MemRegionManager; |
56 | class MemSpaceRegion; |
57 | class SValBuilder; |
58 | class SymbolicRegion; |
59 | class VarRegion; |
60 | |
61 | /// Represent a region's offset within the top level base region. |
62 | class RegionOffset { |
63 | /// The base region. |
64 | const MemRegion *R = nullptr; |
65 | |
66 | /// The bit offset within the base region. Can be negative. |
67 | int64_t Offset; |
68 | |
69 | public: |
70 | // We're using a const instead of an enumeration due to the size required; |
71 | // Visual Studio will only create enumerations of size int, not long long. |
72 | static const int64_t Symbolic = std::numeric_limits<int64_t>::max(); |
73 | |
74 | RegionOffset() = default; |
75 | RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} |
76 | |
77 | const MemRegion *getRegion() const { return R; } |
78 | |
79 | bool hasSymbolicOffset() const { return Offset == Symbolic; } |
80 | |
81 | int64_t getOffset() const { |
82 | assert(!hasSymbolicOffset())((!hasSymbolicOffset()) ? static_cast<void> (0) : __assert_fail ("!hasSymbolicOffset()", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 82, __PRETTY_FUNCTION__)); |
83 | return Offset; |
84 | } |
85 | |
86 | bool isValid() const { return R; } |
87 | }; |
88 | |
89 | //===----------------------------------------------------------------------===// |
90 | // Base region classes. |
91 | //===----------------------------------------------------------------------===// |
92 | |
93 | /// MemRegion - The root abstract class for all memory regions. |
94 | class MemRegion : public llvm::FoldingSetNode { |
95 | public: |
96 | enum Kind { |
97 | #define REGION(Id, Parent) Id ## Kind, |
98 | #define REGION_RANGE(Id, First, Last) BEGIN_##Id = First, END_##Id = Last, |
99 | #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" |
100 | }; |
101 | |
102 | private: |
103 | const Kind kind; |
104 | mutable Optional<RegionOffset> cachedOffset; |
105 | |
106 | protected: |
107 | MemRegion(Kind k) : kind(k) {} |
108 | virtual ~MemRegion(); |
109 | |
110 | public: |
111 | ASTContext &getContext() const; |
112 | |
113 | virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0; |
114 | |
115 | virtual MemRegionManager* getMemRegionManager() const = 0; |
116 | |
117 | const MemSpaceRegion *getMemorySpace() const; |
118 | |
119 | const MemRegion *getBaseRegion() const; |
120 | |
121 | /// Recursively retrieve the region of the most derived class instance of |
122 | /// regions of C++ base class instances. |
123 | const MemRegion *getMostDerivedObjectRegion() const; |
124 | |
125 | /// Check if the region is a subregion of the given region. |
126 | /// Each region is a subregion of itself. |
127 | virtual bool isSubRegionOf(const MemRegion *R) const; |
128 | |
129 | const MemRegion *StripCasts(bool StripBaseAndDerivedCasts = true) const; |
130 | |
131 | /// If this is a symbolic region, returns the region. Otherwise, |
132 | /// goes up the base chain looking for the first symbolic base region. |
133 | const SymbolicRegion *getSymbolicBase() const; |
134 | |
135 | bool hasGlobalsOrParametersStorage() const; |
136 | |
137 | bool hasStackStorage() const; |
138 | |
139 | bool hasStackNonParametersStorage() const; |
140 | |
141 | bool hasStackParametersStorage() const; |
142 | |
143 | /// Compute the offset within the top level memory object. |
144 | RegionOffset getAsOffset() const; |
145 | |
146 | /// Get a string representation of a region for debug use. |
147 | std::string getString() const; |
148 | |
149 | virtual void dumpToStream(raw_ostream &os) const; |
150 | |
151 | void dump() const; |
152 | |
153 | /// Returns true if this region can be printed in a user-friendly way. |
154 | virtual bool canPrintPretty() const; |
155 | |
156 | /// Print the region for use in diagnostics. |
157 | virtual void printPretty(raw_ostream &os) const; |
158 | |
159 | /// Returns true if this region's textual representation can be used |
160 | /// as part of a larger expression. |
161 | virtual bool canPrintPrettyAsExpr() const; |
162 | |
163 | /// Print the region as expression. |
164 | /// |
165 | /// When this region represents a subexpression, the method is for printing |
166 | /// an expression containing it. |
167 | virtual void printPrettyAsExpr(raw_ostream &os) const; |
168 | |
169 | Kind getKind() const { return kind; } |
170 | |
171 | template<typename RegionTy> const RegionTy* getAs() const; |
172 | |
173 | virtual bool isBoundable() const { return false; } |
174 | |
175 | /// Get descriptive name for memory region. The name is obtained from |
176 | /// the variable/field declaration retrieved from the memory region. |
177 | /// Regions that point to an element of an array are returned as: "arr[0]". |
178 | /// Regions that point to a struct are returned as: "st.var". |
179 | // |
180 | /// \param UseQuotes Set if the name should be quoted. |
181 | /// |
182 | /// \returns variable name for memory region |
183 | std::string getDescriptiveName(bool UseQuotes = true) const; |
184 | |
185 | /// Retrieve source range from memory region. The range retrieval |
186 | /// is based on the decl obtained from the memory region. |
187 | /// For a VarRegion the range of the base region is returned. |
188 | /// For a FieldRegion the range of the field is returned. |
189 | /// If no declaration is found, an empty source range is returned. |
190 | /// The client is responsible for checking if the returned range is valid. |
191 | /// |
192 | /// \returns source range for declaration retrieved from memory region |
193 | SourceRange sourceRange() const; |
194 | }; |
195 | |
196 | /// MemSpaceRegion - A memory region that represents a "memory space"; |
197 | /// for example, the set of global variables, the stack frame, etc. |
198 | class MemSpaceRegion : public MemRegion { |
199 | protected: |
200 | MemRegionManager *Mgr; |
201 | |
202 | MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) { |
203 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 203, __PRETTY_FUNCTION__)); |
204 | assert(mgr)((mgr) ? static_cast<void> (0) : __assert_fail ("mgr", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 204, __PRETTY_FUNCTION__)); |
205 | } |
206 | |
207 | MemRegionManager* getMemRegionManager() const override { return Mgr; } |
208 | |
209 | public: |
210 | bool isBoundable() const override { return false; } |
211 | |
212 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
213 | |
214 | static bool classof(const MemRegion *R) { |
215 | Kind k = R->getKind(); |
216 | return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES; |
217 | } |
218 | }; |
219 | |
220 | /// CodeSpaceRegion - The memory space that holds the executable code of |
221 | /// functions and blocks. |
222 | class CodeSpaceRegion : public MemSpaceRegion { |
223 | friend class MemRegionManager; |
224 | |
225 | CodeSpaceRegion(MemRegionManager *mgr) |
226 | : MemSpaceRegion(mgr, CodeSpaceRegionKind) {} |
227 | |
228 | public: |
229 | void dumpToStream(raw_ostream &os) const override; |
230 | |
231 | static bool classof(const MemRegion *R) { |
232 | return R->getKind() == CodeSpaceRegionKind; |
233 | } |
234 | }; |
235 | |
236 | class GlobalsSpaceRegion : public MemSpaceRegion { |
237 | virtual void anchor(); |
238 | |
239 | protected: |
240 | GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) { |
241 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 241, __PRETTY_FUNCTION__)); |
242 | } |
243 | |
244 | public: |
245 | static bool classof(const MemRegion *R) { |
246 | Kind k = R->getKind(); |
247 | return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES; |
248 | } |
249 | }; |
250 | |
251 | /// The region of the static variables within the current CodeTextRegion |
252 | /// scope. |
253 | /// |
254 | /// Currently, only the static locals are placed there, so we know that these |
255 | /// variables do not get invalidated by calls to other functions. |
256 | class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { |
257 | friend class MemRegionManager; |
258 | |
259 | const CodeTextRegion *CR; |
260 | |
261 | StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr) |
262 | : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) { |
263 | assert(cr)((cr) ? static_cast<void> (0) : __assert_fail ("cr", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 263, __PRETTY_FUNCTION__)); |
264 | } |
265 | |
266 | public: |
267 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
268 | |
269 | void dumpToStream(raw_ostream &os) const override; |
270 | |
271 | const CodeTextRegion *getCodeRegion() const { return CR; } |
272 | |
273 | static bool classof(const MemRegion *R) { |
274 | return R->getKind() == StaticGlobalSpaceRegionKind; |
275 | } |
276 | }; |
277 | |
278 | /// The region for all the non-static global variables. |
279 | /// |
280 | /// This class is further split into subclasses for efficient implementation of |
281 | /// invalidating a set of related global values as is done in |
282 | /// RegionStoreManager::invalidateRegions (instead of finding all the dependent |
283 | /// globals, we invalidate the whole parent region). |
284 | class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { |
285 | void anchor() override; |
286 | |
287 | protected: |
288 | NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) |
289 | : GlobalsSpaceRegion(mgr, k) { |
290 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 290, __PRETTY_FUNCTION__)); |
291 | } |
292 | |
293 | public: |
294 | static bool classof(const MemRegion *R) { |
295 | Kind k = R->getKind(); |
296 | return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES && |
297 | k <= END_NON_STATIC_GLOBAL_MEMSPACES; |
298 | } |
299 | }; |
300 | |
301 | /// The region containing globals which are defined in system/external |
302 | /// headers and are considered modifiable by system calls (ex: errno). |
303 | class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion { |
304 | friend class MemRegionManager; |
305 | |
306 | GlobalSystemSpaceRegion(MemRegionManager *mgr) |
307 | : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {} |
308 | |
309 | public: |
310 | void dumpToStream(raw_ostream &os) const override; |
311 | |
312 | static bool classof(const MemRegion *R) { |
313 | return R->getKind() == GlobalSystemSpaceRegionKind; |
314 | } |
315 | }; |
316 | |
317 | /// The region containing globals which are considered not to be modified |
318 | /// or point to data which could be modified as a result of a function call |
319 | /// (system or internal). Ex: Const global scalars would be modeled as part of |
320 | /// this region. This region also includes most system globals since they have |
321 | /// low chance of being modified. |
322 | class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion { |
323 | friend class MemRegionManager; |
324 | |
325 | GlobalImmutableSpaceRegion(MemRegionManager *mgr) |
326 | : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {} |
327 | |
328 | public: |
329 | void dumpToStream(raw_ostream &os) const override; |
330 | |
331 | static bool classof(const MemRegion *R) { |
332 | return R->getKind() == GlobalImmutableSpaceRegionKind; |
333 | } |
334 | }; |
335 | |
336 | /// The region containing globals which can be modified by calls to |
337 | /// "internally" defined functions - (for now just) functions other then system |
338 | /// calls. |
339 | class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { |
340 | friend class MemRegionManager; |
341 | |
342 | GlobalInternalSpaceRegion(MemRegionManager *mgr) |
343 | : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {} |
344 | |
345 | public: |
346 | void dumpToStream(raw_ostream &os) const override; |
347 | |
348 | static bool classof(const MemRegion *R) { |
349 | return R->getKind() == GlobalInternalSpaceRegionKind; |
350 | } |
351 | }; |
352 | |
353 | class HeapSpaceRegion : public MemSpaceRegion { |
354 | friend class MemRegionManager; |
355 | |
356 | HeapSpaceRegion(MemRegionManager *mgr) |
357 | : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} |
358 | |
359 | public: |
360 | void dumpToStream(raw_ostream &os) const override; |
361 | |
362 | static bool classof(const MemRegion *R) { |
363 | return R->getKind() == HeapSpaceRegionKind; |
364 | } |
365 | }; |
366 | |
367 | class UnknownSpaceRegion : public MemSpaceRegion { |
368 | friend class MemRegionManager; |
369 | |
370 | UnknownSpaceRegion(MemRegionManager *mgr) |
371 | : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} |
372 | |
373 | public: |
374 | void dumpToStream(raw_ostream &os) const override; |
375 | |
376 | static bool classof(const MemRegion *R) { |
377 | return R->getKind() == UnknownSpaceRegionKind; |
378 | } |
379 | }; |
380 | |
381 | class StackSpaceRegion : public MemSpaceRegion { |
382 | virtual void anchor(); |
383 | |
384 | const StackFrameContext *SFC; |
385 | |
386 | protected: |
387 | StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) |
388 | : MemSpaceRegion(mgr, k), SFC(sfc) { |
389 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 389, __PRETTY_FUNCTION__)); |
390 | assert(sfc)((sfc) ? static_cast<void> (0) : __assert_fail ("sfc", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 390, __PRETTY_FUNCTION__)); |
391 | } |
392 | |
393 | public: |
394 | const StackFrameContext *getStackFrame() const { return SFC; } |
395 | |
396 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
397 | |
398 | static bool classof(const MemRegion *R) { |
399 | Kind k = R->getKind(); |
400 | return k >= BEGIN_STACK_MEMSPACES && k <= END_STACK_MEMSPACES; |
401 | } |
402 | }; |
403 | |
404 | class StackLocalsSpaceRegion : public StackSpaceRegion { |
405 | friend class MemRegionManager; |
406 | |
407 | StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) |
408 | : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} |
409 | |
410 | public: |
411 | void dumpToStream(raw_ostream &os) const override; |
412 | |
413 | static bool classof(const MemRegion *R) { |
414 | return R->getKind() == StackLocalsSpaceRegionKind; |
415 | } |
416 | }; |
417 | |
418 | class StackArgumentsSpaceRegion : public StackSpaceRegion { |
419 | private: |
420 | friend class MemRegionManager; |
421 | |
422 | StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) |
423 | : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} |
424 | |
425 | public: |
426 | void dumpToStream(raw_ostream &os) const override; |
427 | |
428 | static bool classof(const MemRegion *R) { |
429 | return R->getKind() == StackArgumentsSpaceRegionKind; |
430 | } |
431 | }; |
432 | |
433 | /// SubRegion - A region that subsets another larger region. Most regions |
434 | /// are subclasses of SubRegion. |
435 | class SubRegion : public MemRegion { |
436 | virtual void anchor(); |
437 | |
438 | protected: |
439 | const MemRegion* superRegion; |
440 | |
441 | SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) { |
442 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 442, __PRETTY_FUNCTION__)); |
443 | assert(sReg)((sReg) ? static_cast<void> (0) : __assert_fail ("sReg" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 443, __PRETTY_FUNCTION__)); |
444 | } |
445 | |
446 | public: |
447 | const MemRegion* getSuperRegion() const { |
448 | return superRegion; |
449 | } |
450 | |
451 | /// getExtent - Returns the size of the region in bytes. |
452 | virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const { |
453 | return UnknownVal(); |
454 | } |
455 | |
456 | MemRegionManager* getMemRegionManager() const override; |
457 | |
458 | bool isSubRegionOf(const MemRegion* R) const override; |
459 | |
460 | static bool classof(const MemRegion* R) { |
461 | return R->getKind() > END_MEMSPACES; |
462 | } |
463 | }; |
464 | |
465 | //===----------------------------------------------------------------------===// |
466 | // MemRegion subclasses. |
467 | //===----------------------------------------------------------------------===// |
468 | |
469 | /// AllocaRegion - A region that represents an untyped blob of bytes created |
470 | /// by a call to 'alloca'. |
471 | class AllocaRegion : public SubRegion { |
472 | friend class MemRegionManager; |
473 | |
474 | // Block counter. Used to distinguish different pieces of memory allocated by |
475 | // alloca at the same call site. |
476 | unsigned Cnt; |
477 | |
478 | const Expr *Ex; |
479 | |
480 | AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion) |
481 | : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) { |
482 | assert(Ex)((Ex) ? static_cast<void> (0) : __assert_fail ("Ex", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 482, __PRETTY_FUNCTION__)); |
483 | } |
484 | |
485 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, |
486 | unsigned Cnt, const MemRegion *superRegion); |
487 | |
488 | public: |
489 | const Expr *getExpr() const { return Ex; } |
490 | |
491 | bool isBoundable() const override { return true; } |
492 | |
493 | DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; |
494 | |
495 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
496 | |
497 | void dumpToStream(raw_ostream &os) const override; |
498 | |
499 | static bool classof(const MemRegion* R) { |
500 | return R->getKind() == AllocaRegionKind; |
501 | } |
502 | }; |
503 | |
504 | /// TypedRegion - An abstract class representing regions that are typed. |
505 | class TypedRegion : public SubRegion { |
506 | void anchor() override; |
507 | |
508 | protected: |
509 | TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) { |
510 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 510, __PRETTY_FUNCTION__)); |
511 | } |
512 | |
513 | public: |
514 | virtual QualType getLocationType() const = 0; |
515 | |
516 | QualType getDesugaredLocationType(ASTContext &Context) const { |
517 | return getLocationType().getDesugaredType(Context); |
518 | } |
519 | |
520 | bool isBoundable() const override { return true; } |
521 | |
522 | static bool classof(const MemRegion* R) { |
523 | unsigned k = R->getKind(); |
524 | return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS; |
525 | } |
526 | }; |
527 | |
528 | /// TypedValueRegion - An abstract class representing regions having a typed value. |
529 | class TypedValueRegion : public TypedRegion { |
530 | void anchor() override; |
531 | |
532 | protected: |
533 | TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) { |
534 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 534, __PRETTY_FUNCTION__)); |
535 | } |
536 | |
537 | public: |
538 | virtual QualType getValueType() const = 0; |
539 | |
540 | QualType getLocationType() const override { |
541 | // FIXME: We can possibly optimize this later to cache this value. |
542 | QualType T = getValueType(); |
543 | ASTContext &ctx = getContext(); |
544 | if (T->getAs<ObjCObjectType>()) |
545 | return ctx.getObjCObjectPointerType(T); |
546 | return ctx.getPointerType(getValueType()); |
547 | } |
548 | |
549 | QualType getDesugaredValueType(ASTContext &Context) const { |
550 | QualType T = getValueType(); |
551 | return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T; |
552 | } |
553 | |
554 | DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; |
555 | |
556 | static bool classof(const MemRegion* R) { |
557 | unsigned k = R->getKind(); |
558 | return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS; |
559 | } |
560 | }; |
561 | |
562 | class CodeTextRegion : public TypedRegion { |
563 | void anchor() override; |
564 | |
565 | protected: |
566 | CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) { |
567 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 567, __PRETTY_FUNCTION__)); |
568 | } |
569 | |
570 | public: |
571 | bool isBoundable() const override { return false; } |
572 | |
573 | static bool classof(const MemRegion* R) { |
574 | Kind k = R->getKind(); |
575 | return k >= BEGIN_CODE_TEXT_REGIONS && k <= END_CODE_TEXT_REGIONS; |
576 | } |
577 | }; |
578 | |
579 | /// FunctionCodeRegion - A region that represents code texts of function. |
580 | class FunctionCodeRegion : public CodeTextRegion { |
581 | friend class MemRegionManager; |
582 | |
583 | const NamedDecl *FD; |
584 | |
585 | FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg) |
586 | : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { |
587 | assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd))((isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd )) ? static_cast<void> (0) : __assert_fail ("isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 587, __PRETTY_FUNCTION__)); |
588 | } |
589 | |
590 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, |
591 | const MemRegion*); |
592 | |
593 | public: |
594 | QualType getLocationType() const override { |
595 | const ASTContext &Ctx = getContext(); |
596 | if (const auto *D = dyn_cast<FunctionDecl>(FD)) { |
597 | return Ctx.getPointerType(D->getType()); |
598 | } |
599 | |
600 | assert(isa<ObjCMethodDecl>(FD))((isa<ObjCMethodDecl>(FD)) ? static_cast<void> (0 ) : __assert_fail ("isa<ObjCMethodDecl>(FD)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 600, __PRETTY_FUNCTION__)); |
601 | assert(false && "Getting the type of ObjCMethod is not supported yet")((false && "Getting the type of ObjCMethod is not supported yet" ) ? static_cast<void> (0) : __assert_fail ("false && \"Getting the type of ObjCMethod is not supported yet\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 601, __PRETTY_FUNCTION__)); |
602 | |
603 | // TODO: We might want to return a different type here (ex: id (*ty)(...)) |
604 | // depending on how it is used. |
605 | return {}; |
606 | } |
607 | |
608 | const NamedDecl *getDecl() const { |
609 | return FD; |
610 | } |
611 | |
612 | void dumpToStream(raw_ostream &os) const override; |
613 | |
614 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
615 | |
616 | static bool classof(const MemRegion* R) { |
617 | return R->getKind() == FunctionCodeRegionKind; |
618 | } |
619 | }; |
620 | |
621 | /// BlockCodeRegion - A region that represents code texts of blocks (closures). |
622 | /// Blocks are represented with two kinds of regions. BlockCodeRegions |
623 | /// represent the "code", while BlockDataRegions represent instances of blocks, |
624 | /// which correspond to "code+data". The distinction is important, because |
625 | /// like a closure a block captures the values of externally referenced |
626 | /// variables. |
627 | class BlockCodeRegion : public CodeTextRegion { |
628 | friend class MemRegionManager; |
629 | |
630 | const BlockDecl *BD; |
631 | AnalysisDeclContext *AC; |
632 | CanQualType locTy; |
633 | |
634 | BlockCodeRegion(const BlockDecl *bd, CanQualType lTy, |
635 | AnalysisDeclContext *ac, const CodeSpaceRegion* sreg) |
636 | : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) { |
637 | assert(bd)((bd) ? static_cast<void> (0) : __assert_fail ("bd", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 637, __PRETTY_FUNCTION__)); |
638 | assert(ac)((ac) ? static_cast<void> (0) : __assert_fail ("ac", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 638, __PRETTY_FUNCTION__)); |
639 | assert(lTy->getTypePtr()->isBlockPointerType())((lTy->getTypePtr()->isBlockPointerType()) ? static_cast <void> (0) : __assert_fail ("lTy->getTypePtr()->isBlockPointerType()" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 639, __PRETTY_FUNCTION__)); |
640 | } |
641 | |
642 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, |
643 | CanQualType, const AnalysisDeclContext*, |
644 | const MemRegion*); |
645 | |
646 | public: |
647 | QualType getLocationType() const override { |
648 | return locTy; |
649 | } |
650 | |
651 | const BlockDecl *getDecl() const { |
652 | return BD; |
653 | } |
654 | |
655 | AnalysisDeclContext *getAnalysisDeclContext() const { return AC; } |
656 | |
657 | void dumpToStream(raw_ostream &os) const override; |
658 | |
659 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
660 | |
661 | static bool classof(const MemRegion* R) { |
662 | return R->getKind() == BlockCodeRegionKind; |
663 | } |
664 | }; |
665 | |
666 | /// BlockDataRegion - A region that represents a block instance. |
667 | /// Blocks are represented with two kinds of regions. BlockCodeRegions |
668 | /// represent the "code", while BlockDataRegions represent instances of blocks, |
669 | /// which correspond to "code+data". The distinction is important, because |
670 | /// like a closure a block captures the values of externally referenced |
671 | /// variables. |
672 | class BlockDataRegion : public TypedRegion { |
673 | friend class MemRegionManager; |
674 | |
675 | const BlockCodeRegion *BC; |
676 | const LocationContext *LC; // Can be null |
677 | unsigned BlockCount; |
678 | void *ReferencedVars = nullptr; |
679 | void *OriginalVars = nullptr; |
680 | |
681 | BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, |
682 | unsigned count, const MemSpaceRegion *sreg) |
683 | : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), |
684 | BlockCount(count) { |
685 | assert(bc)((bc) ? static_cast<void> (0) : __assert_fail ("bc", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 685, __PRETTY_FUNCTION__)); |
686 | assert(lc)((lc) ? static_cast<void> (0) : __assert_fail ("lc", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 686, __PRETTY_FUNCTION__)); |
687 | assert(isa<GlobalImmutableSpaceRegion>(sreg) ||((isa<GlobalImmutableSpaceRegion>(sreg) || isa<StackLocalsSpaceRegion >(sreg) || isa<UnknownSpaceRegion>(sreg)) ? static_cast <void> (0) : __assert_fail ("isa<GlobalImmutableSpaceRegion>(sreg) || isa<StackLocalsSpaceRegion>(sreg) || isa<UnknownSpaceRegion>(sreg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 689, __PRETTY_FUNCTION__)) |
688 | isa<StackLocalsSpaceRegion>(sreg) ||((isa<GlobalImmutableSpaceRegion>(sreg) || isa<StackLocalsSpaceRegion >(sreg) || isa<UnknownSpaceRegion>(sreg)) ? static_cast <void> (0) : __assert_fail ("isa<GlobalImmutableSpaceRegion>(sreg) || isa<StackLocalsSpaceRegion>(sreg) || isa<UnknownSpaceRegion>(sreg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 689, __PRETTY_FUNCTION__)) |
689 | isa<UnknownSpaceRegion>(sreg))((isa<GlobalImmutableSpaceRegion>(sreg) || isa<StackLocalsSpaceRegion >(sreg) || isa<UnknownSpaceRegion>(sreg)) ? static_cast <void> (0) : __assert_fail ("isa<GlobalImmutableSpaceRegion>(sreg) || isa<StackLocalsSpaceRegion>(sreg) || isa<UnknownSpaceRegion>(sreg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 689, __PRETTY_FUNCTION__)); |
690 | } |
691 | |
692 | static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *, |
693 | const LocationContext *, unsigned, |
694 | const MemRegion *); |
695 | |
696 | public: |
697 | const BlockCodeRegion *getCodeRegion() const { return BC; } |
698 | |
699 | const BlockDecl *getDecl() const { return BC->getDecl(); } |
700 | |
701 | QualType getLocationType() const override { return BC->getLocationType(); } |
702 | |
703 | class referenced_vars_iterator { |
704 | const MemRegion * const *R; |
705 | const MemRegion * const *OriginalR; |
706 | |
707 | public: |
708 | explicit referenced_vars_iterator(const MemRegion * const *r, |
709 | const MemRegion * const *originalR) |
710 | : R(r), OriginalR(originalR) {} |
711 | |
712 | const VarRegion *getCapturedRegion() const { |
713 | return cast<VarRegion>(*R); |
714 | } |
715 | |
716 | const VarRegion *getOriginalRegion() const { |
717 | return cast<VarRegion>(*OriginalR); |
718 | } |
719 | |
720 | bool operator==(const referenced_vars_iterator &I) const { |
721 | assert((R == nullptr) == (I.R == nullptr))(((R == nullptr) == (I.R == nullptr)) ? static_cast<void> (0) : __assert_fail ("(R == nullptr) == (I.R == nullptr)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 721, __PRETTY_FUNCTION__)); |
722 | return I.R == R; |
723 | } |
724 | |
725 | bool operator!=(const referenced_vars_iterator &I) const { |
726 | assert((R == nullptr) == (I.R == nullptr))(((R == nullptr) == (I.R == nullptr)) ? static_cast<void> (0) : __assert_fail ("(R == nullptr) == (I.R == nullptr)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 726, __PRETTY_FUNCTION__)); |
727 | return I.R != R; |
728 | } |
729 | |
730 | referenced_vars_iterator &operator++() { |
731 | ++R; |
732 | ++OriginalR; |
733 | return *this; |
734 | } |
735 | }; |
736 | |
737 | /// Return the original region for a captured region, if |
738 | /// one exists. |
739 | const VarRegion *getOriginalRegion(const VarRegion *VR) const; |
740 | |
741 | referenced_vars_iterator referenced_vars_begin() const; |
742 | referenced_vars_iterator referenced_vars_end() const; |
743 | |
744 | void dumpToStream(raw_ostream &os) const override; |
745 | |
746 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
747 | |
748 | static bool classof(const MemRegion* R) { |
749 | return R->getKind() == BlockDataRegionKind; |
750 | } |
751 | |
752 | private: |
753 | void LazyInitializeReferencedVars(); |
754 | std::pair<const VarRegion *, const VarRegion *> |
755 | getCaptureRegions(const VarDecl *VD); |
756 | }; |
757 | |
758 | /// SymbolicRegion - A special, "non-concrete" region. Unlike other region |
759 | /// classes, SymbolicRegion represents a region that serves as an alias for |
760 | /// either a real region, a NULL pointer, etc. It essentially is used to |
761 | /// map the concept of symbolic values into the domain of regions. Symbolic |
762 | /// regions do not need to be typed. |
763 | class SymbolicRegion : public SubRegion { |
764 | friend class MemRegionManager; |
765 | |
766 | const SymbolRef sym; |
767 | |
768 | SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg) |
769 | : SubRegion(sreg, SymbolicRegionKind), sym(s) { |
770 | // Because pointer arithmetic is represented by ElementRegion layers, |
771 | // the base symbol here should not contain any arithmetic. |
772 | assert(s && isa<SymbolData>(s))((s && isa<SymbolData>(s)) ? static_cast<void > (0) : __assert_fail ("s && isa<SymbolData>(s)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 772, __PRETTY_FUNCTION__)); |
773 | assert(s->getType()->isAnyPointerType() ||((s->getType()->isAnyPointerType() || s->getType()-> isReferenceType() || s->getType()->isBlockPointerType() ) ? static_cast<void> (0) : __assert_fail ("s->getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 775, __PRETTY_FUNCTION__)) |
774 | s->getType()->isReferenceType() ||((s->getType()->isAnyPointerType() || s->getType()-> isReferenceType() || s->getType()->isBlockPointerType() ) ? static_cast<void> (0) : __assert_fail ("s->getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 775, __PRETTY_FUNCTION__)) |
775 | s->getType()->isBlockPointerType())((s->getType()->isAnyPointerType() || s->getType()-> isReferenceType() || s->getType()->isBlockPointerType() ) ? static_cast<void> (0) : __assert_fail ("s->getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 775, __PRETTY_FUNCTION__)); |
776 | assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg))((isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion >(sreg)) ? static_cast<void> (0) : __assert_fail ("isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 776, __PRETTY_FUNCTION__)); |
777 | } |
778 | |
779 | public: |
780 | SymbolRef getSymbol() const { return sym; } |
781 | |
782 | bool isBoundable() const override { return true; } |
783 | |
784 | DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; |
785 | |
786 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
787 | |
788 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, |
789 | SymbolRef sym, |
790 | const MemRegion* superRegion); |
791 | |
792 | void dumpToStream(raw_ostream &os) const override; |
793 | |
794 | static bool classof(const MemRegion* R) { |
795 | return R->getKind() == SymbolicRegionKind; |
796 | } |
797 | }; |
798 | |
799 | /// StringRegion - Region associated with a StringLiteral. |
800 | class StringRegion : public TypedValueRegion { |
801 | friend class MemRegionManager; |
802 | |
803 | const StringLiteral *Str; |
804 | |
805 | StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg) |
806 | : TypedValueRegion(sreg, StringRegionKind), Str(str) { |
807 | assert(str)((str) ? static_cast<void> (0) : __assert_fail ("str", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 807, __PRETTY_FUNCTION__)); |
808 | } |
809 | |
810 | static void ProfileRegion(llvm::FoldingSetNodeID &ID, |
811 | const StringLiteral *Str, |
812 | const MemRegion *superRegion); |
813 | |
814 | public: |
815 | const StringLiteral *getStringLiteral() const { return Str; } |
816 | |
817 | QualType getValueType() const override { return Str->getType(); } |
818 | |
819 | DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; |
820 | |
821 | bool isBoundable() const override { return false; } |
822 | |
823 | void Profile(llvm::FoldingSetNodeID& ID) const override { |
824 | ProfileRegion(ID, Str, superRegion); |
825 | } |
826 | |
827 | void dumpToStream(raw_ostream &os) const override; |
828 | |
829 | static bool classof(const MemRegion* R) { |
830 | return R->getKind() == StringRegionKind; |
831 | } |
832 | }; |
833 | |
834 | /// The region associated with an ObjCStringLiteral. |
835 | class ObjCStringRegion : public TypedValueRegion { |
836 | friend class MemRegionManager; |
837 | |
838 | const ObjCStringLiteral *Str; |
839 | |
840 | ObjCStringRegion(const ObjCStringLiteral *str, |
841 | const GlobalInternalSpaceRegion *sreg) |
842 | : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) { |
843 | assert(str)((str) ? static_cast<void> (0) : __assert_fail ("str", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 843, __PRETTY_FUNCTION__)); |
844 | } |
845 | |
846 | static void ProfileRegion(llvm::FoldingSetNodeID &ID, |
847 | const ObjCStringLiteral *Str, |
848 | const MemRegion *superRegion); |
849 | |
850 | public: |
851 | const ObjCStringLiteral *getObjCStringLiteral() const { return Str; } |
852 | |
853 | QualType getValueType() const override { return Str->getType(); } |
854 | |
855 | bool isBoundable() const override { return false; } |
856 | |
857 | void Profile(llvm::FoldingSetNodeID& ID) const override { |
858 | ProfileRegion(ID, Str, superRegion); |
859 | } |
860 | |
861 | void dumpToStream(raw_ostream &os) const override; |
862 | |
863 | static bool classof(const MemRegion* R) { |
864 | return R->getKind() == ObjCStringRegionKind; |
865 | } |
866 | }; |
867 | |
868 | /// CompoundLiteralRegion - A memory region representing a compound literal. |
869 | /// Compound literals are essentially temporaries that are stack allocated |
870 | /// or in the global constant pool. |
871 | class CompoundLiteralRegion : public TypedValueRegion { |
872 | friend class MemRegionManager; |
873 | |
874 | const CompoundLiteralExpr *CL; |
875 | |
876 | CompoundLiteralRegion(const CompoundLiteralExpr *cl, |
877 | const MemSpaceRegion *sReg) |
878 | : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) { |
879 | assert(cl)((cl) ? static_cast<void> (0) : __assert_fail ("cl", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 879, __PRETTY_FUNCTION__)); |
880 | assert(isa<GlobalInternalSpaceRegion>(sReg) ||((isa<GlobalInternalSpaceRegion>(sReg) || isa<StackLocalsSpaceRegion >(sReg)) ? static_cast<void> (0) : __assert_fail ("isa<GlobalInternalSpaceRegion>(sReg) || isa<StackLocalsSpaceRegion>(sReg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 881, __PRETTY_FUNCTION__)) |
881 | isa<StackLocalsSpaceRegion>(sReg))((isa<GlobalInternalSpaceRegion>(sReg) || isa<StackLocalsSpaceRegion >(sReg)) ? static_cast<void> (0) : __assert_fail ("isa<GlobalInternalSpaceRegion>(sReg) || isa<StackLocalsSpaceRegion>(sReg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 881, __PRETTY_FUNCTION__)); |
882 | } |
883 | |
884 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, |
885 | const CompoundLiteralExpr *CL, |
886 | const MemRegion* superRegion); |
887 | |
888 | public: |
889 | QualType getValueType() const override { return CL->getType(); } |
890 | |
891 | bool isBoundable() const override { return !CL->isFileScope(); } |
892 | |
893 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
894 | |
895 | void dumpToStream(raw_ostream &os) const override; |
896 | |
897 | const CompoundLiteralExpr *getLiteralExpr() const { return CL; } |
898 | |
899 | static bool classof(const MemRegion* R) { |
900 | return R->getKind() == CompoundLiteralRegionKind; |
901 | } |
902 | }; |
903 | |
904 | class DeclRegion : public TypedValueRegion { |
905 | protected: |
906 | const ValueDecl *D; |
907 | |
908 | DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k) |
909 | : TypedValueRegion(sReg, k), D(d) { |
910 | assert(classof(this))((classof(this)) ? static_cast<void> (0) : __assert_fail ("classof(this)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 910, __PRETTY_FUNCTION__)); |
911 | assert(d && d->isCanonicalDecl())((d && d->isCanonicalDecl()) ? static_cast<void > (0) : __assert_fail ("d && d->isCanonicalDecl()" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 911, __PRETTY_FUNCTION__)); |
912 | } |
913 | |
914 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, |
915 | const MemRegion* superRegion, Kind k); |
916 | |
917 | public: |
918 | const ValueDecl *getDecl() const { return D; } |
919 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
920 | |
921 | static bool classof(const MemRegion* R) { |
922 | unsigned k = R->getKind(); |
923 | return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS; |
924 | } |
925 | }; |
926 | |
927 | class VarRegion : public DeclRegion { |
928 | friend class MemRegionManager; |
929 | |
930 | // Constructors and private methods. |
931 | VarRegion(const VarDecl *vd, const MemRegion *sReg) |
932 | : DeclRegion(vd, sReg, VarRegionKind) { |
933 | // VarRegion appears in unknown space when it's a block variable as seen |
934 | // from a block using it, when this block is analyzed at top-level. |
935 | // Other block variables appear within block data regions, |
936 | // which, unlike everything else on this list, are not memory spaces. |
937 | assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||((isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion >(sReg) || isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion >(sReg)) ? static_cast<void> (0) : __assert_fail ("isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) || isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 938, __PRETTY_FUNCTION__)) |
938 | isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg))((isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion >(sReg) || isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion >(sReg)) ? static_cast<void> (0) : __assert_fail ("isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) || isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 938, __PRETTY_FUNCTION__)); |
939 | } |
940 | |
941 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD, |
942 | const MemRegion *superRegion) { |
943 | DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); |
944 | } |
945 | |
946 | public: |
947 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
948 | |
949 | const VarDecl *getDecl() const { return cast<VarDecl>(D); } |
950 | |
951 | const StackFrameContext *getStackFrame() const; |
952 | |
953 | QualType getValueType() const override { |
954 | // FIXME: We can cache this if needed. |
955 | return getDecl()->getType(); |
956 | } |
957 | |
958 | void dumpToStream(raw_ostream &os) const override; |
959 | |
960 | bool canPrintPrettyAsExpr() const override; |
961 | |
962 | void printPrettyAsExpr(raw_ostream &os) const override; |
963 | |
964 | static bool classof(const MemRegion* R) { |
965 | return R->getKind() == VarRegionKind; |
966 | } |
967 | }; |
968 | |
969 | /// CXXThisRegion - Represents the region for the implicit 'this' parameter |
970 | /// in a call to a C++ method. This region doesn't represent the object |
971 | /// referred to by 'this', but rather 'this' itself. |
972 | class CXXThisRegion : public TypedValueRegion { |
973 | friend class MemRegionManager; |
974 | |
975 | CXXThisRegion(const PointerType *thisPointerTy, |
976 | const StackArgumentsSpaceRegion *sReg) |
977 | : TypedValueRegion(sReg, CXXThisRegionKind), |
978 | ThisPointerTy(thisPointerTy) { |
979 | assert(ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() &&((ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && "Invalid region type!") ? static_cast<void> (0) : __assert_fail ("ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && \"Invalid region type!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 980, __PRETTY_FUNCTION__)) |
980 | "Invalid region type!")((ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && "Invalid region type!") ? static_cast<void> (0) : __assert_fail ("ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && \"Invalid region type!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 980, __PRETTY_FUNCTION__)); |
981 | } |
982 | |
983 | static void ProfileRegion(llvm::FoldingSetNodeID &ID, |
984 | const PointerType *PT, |
985 | const MemRegion *sReg); |
986 | |
987 | public: |
988 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
989 | |
990 | QualType getValueType() const override { |
991 | return QualType(ThisPointerTy, 0); |
992 | } |
993 | |
994 | void dumpToStream(raw_ostream &os) const override; |
995 | |
996 | static bool classof(const MemRegion* R) { |
997 | return R->getKind() == CXXThisRegionKind; |
998 | } |
999 | |
1000 | private: |
1001 | const PointerType *ThisPointerTy; |
1002 | }; |
1003 | |
1004 | class FieldRegion : public DeclRegion { |
1005 | friend class MemRegionManager; |
1006 | |
1007 | FieldRegion(const FieldDecl *fd, const SubRegion* sReg) |
1008 | : DeclRegion(fd, sReg, FieldRegionKind) {} |
1009 | |
1010 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, |
1011 | const MemRegion* superRegion) { |
1012 | DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); |
1013 | } |
1014 | |
1015 | public: |
1016 | const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } |
1017 | |
1018 | QualType getValueType() const override { |
1019 | // FIXME: We can cache this if needed. |
1020 | return getDecl()->getType(); |
1021 | } |
1022 | |
1023 | DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; |
1024 | |
1025 | void dumpToStream(raw_ostream &os) const override; |
1026 | |
1027 | bool canPrintPretty() const override; |
1028 | void printPretty(raw_ostream &os) const override; |
1029 | bool canPrintPrettyAsExpr() const override; |
1030 | void printPrettyAsExpr(raw_ostream &os) const override; |
1031 | |
1032 | static bool classof(const MemRegion* R) { |
1033 | return R->getKind() == FieldRegionKind; |
1034 | } |
1035 | }; |
1036 | |
1037 | class ObjCIvarRegion : public DeclRegion { |
1038 | friend class MemRegionManager; |
1039 | |
1040 | ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg); |
1041 | |
1042 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd, |
1043 | const MemRegion* superRegion); |
1044 | |
1045 | public: |
1046 | const ObjCIvarDecl *getDecl() const; |
1047 | QualType getValueType() const override; |
1048 | |
1049 | bool canPrintPrettyAsExpr() const override; |
1050 | void printPrettyAsExpr(raw_ostream &os) const override; |
1051 | |
1052 | void dumpToStream(raw_ostream &os) const override; |
1053 | |
1054 | static bool classof(const MemRegion* R) { |
1055 | return R->getKind() == ObjCIvarRegionKind; |
1056 | } |
1057 | }; |
1058 | |
1059 | //===----------------------------------------------------------------------===// |
1060 | // Auxiliary data classes for use with MemRegions. |
1061 | //===----------------------------------------------------------------------===// |
1062 | |
1063 | class RegionRawOffset { |
1064 | friend class ElementRegion; |
1065 | |
1066 | const MemRegion *Region; |
1067 | CharUnits Offset; |
1068 | |
1069 | RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero()) |
1070 | : Region(reg), Offset(offset) {} |
1071 | |
1072 | public: |
1073 | // FIXME: Eventually support symbolic offsets. |
1074 | CharUnits getOffset() const { return Offset; } |
1075 | const MemRegion *getRegion() const { return Region; } |
1076 | |
1077 | void dumpToStream(raw_ostream &os) const; |
1078 | void dump() const; |
1079 | }; |
1080 | |
1081 | /// ElementRegion is used to represent both array elements and casts. |
1082 | class ElementRegion : public TypedValueRegion { |
1083 | friend class MemRegionManager; |
1084 | |
1085 | QualType ElementType; |
1086 | NonLoc Index; |
1087 | |
1088 | ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg) |
1089 | : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType), |
1090 | Index(Idx) { |
1091 | assert((!Idx.getAs<nonloc::ConcreteInt>() ||(((!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc ::ConcreteInt>().getValue().isSigned()) && "The index must be signed" ) ? static_cast<void> (0) : __assert_fail ("(!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && \"The index must be signed\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1093, __PRETTY_FUNCTION__)) |
1092 | Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&(((!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc ::ConcreteInt>().getValue().isSigned()) && "The index must be signed" ) ? static_cast<void> (0) : __assert_fail ("(!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && \"The index must be signed\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1093, __PRETTY_FUNCTION__)) |
1093 | "The index must be signed")(((!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc ::ConcreteInt>().getValue().isSigned()) && "The index must be signed" ) ? static_cast<void> (0) : __assert_fail ("(!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && \"The index must be signed\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1093, __PRETTY_FUNCTION__)); |
1094 | assert(!elementType.isNull() && !elementType->isVoidType() &&((!elementType.isNull() && !elementType->isVoidType () && "Invalid region type!") ? static_cast<void> (0) : __assert_fail ("!elementType.isNull() && !elementType->isVoidType() && \"Invalid region type!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1095, __PRETTY_FUNCTION__)) |
1095 | "Invalid region type!")((!elementType.isNull() && !elementType->isVoidType () && "Invalid region type!") ? static_cast<void> (0) : __assert_fail ("!elementType.isNull() && !elementType->isVoidType() && \"Invalid region type!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1095, __PRETTY_FUNCTION__)); |
1096 | } |
1097 | |
1098 | static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType, |
1099 | SVal Idx, const MemRegion* superRegion); |
1100 | |
1101 | public: |
1102 | NonLoc getIndex() const { return Index; } |
1103 | |
1104 | QualType getValueType() const override { return ElementType; } |
1105 | |
1106 | QualType getElementType() const { return ElementType; } |
1107 | |
1108 | /// Compute the offset within the array. The array might also be a subobject. |
1109 | RegionRawOffset getAsArrayOffset() const; |
1110 | |
1111 | void dumpToStream(raw_ostream &os) const override; |
1112 | |
1113 | void Profile(llvm::FoldingSetNodeID& ID) const override; |
1114 | |
1115 | static bool classof(const MemRegion* R) { |
1116 | return R->getKind() == ElementRegionKind; |
1117 | } |
1118 | }; |
1119 | |
1120 | // C++ temporary object associated with an expression. |
1121 | class CXXTempObjectRegion : public TypedValueRegion { |
1122 | friend class MemRegionManager; |
1123 | |
1124 | Expr const *Ex; |
1125 | |
1126 | CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg) |
1127 | : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) { |
1128 | assert(E)((E) ? static_cast<void> (0) : __assert_fail ("E", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1128, __PRETTY_FUNCTION__)); |
1129 | assert(isa<StackLocalsSpaceRegion>(sReg) ||((isa<StackLocalsSpaceRegion>(sReg) || isa<GlobalInternalSpaceRegion >(sReg)) ? static_cast<void> (0) : __assert_fail ("isa<StackLocalsSpaceRegion>(sReg) || isa<GlobalInternalSpaceRegion>(sReg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1130, __PRETTY_FUNCTION__)) |
1130 | isa<GlobalInternalSpaceRegion>(sReg))((isa<StackLocalsSpaceRegion>(sReg) || isa<GlobalInternalSpaceRegion >(sReg)) ? static_cast<void> (0) : __assert_fail ("isa<StackLocalsSpaceRegion>(sReg) || isa<GlobalInternalSpaceRegion>(sReg)" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1130, __PRETTY_FUNCTION__)); |
1131 | } |
1132 | |
1133 | static void ProfileRegion(llvm::FoldingSetNodeID &ID, |
1134 | Expr const *E, const MemRegion *sReg); |
1135 | |
1136 | public: |
1137 | const Expr *getExpr() const { return Ex; } |
1138 | |
1139 | QualType getValueType() const override { return Ex->getType(); } |
1140 | |
1141 | void dumpToStream(raw_ostream &os) const override; |
1142 | |
1143 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
1144 | |
1145 | static bool classof(const MemRegion* R) { |
1146 | return R->getKind() == CXXTempObjectRegionKind; |
1147 | } |
1148 | }; |
1149 | |
1150 | // CXXBaseObjectRegion represents a base object within a C++ object. It is |
1151 | // identified by the base class declaration and the region of its parent object. |
1152 | class CXXBaseObjectRegion : public TypedValueRegion { |
1153 | friend class MemRegionManager; |
1154 | |
1155 | llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data; |
1156 | |
1157 | CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual, |
1158 | const SubRegion *SReg) |
1159 | : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) { |
1160 | assert(RD)((RD) ? static_cast<void> (0) : __assert_fail ("RD", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1160, __PRETTY_FUNCTION__)); |
1161 | } |
1162 | |
1163 | static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD, |
1164 | bool IsVirtual, const MemRegion *SReg); |
1165 | |
1166 | public: |
1167 | const CXXRecordDecl *getDecl() const { return Data.getPointer(); } |
1168 | bool isVirtual() const { return Data.getInt(); } |
1169 | |
1170 | QualType getValueType() const override; |
1171 | |
1172 | void dumpToStream(raw_ostream &os) const override; |
1173 | |
1174 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
1175 | |
1176 | bool canPrintPrettyAsExpr() const override; |
1177 | |
1178 | void printPrettyAsExpr(raw_ostream &os) const override; |
1179 | |
1180 | static bool classof(const MemRegion *region) { |
1181 | return region->getKind() == CXXBaseObjectRegionKind; |
1182 | } |
1183 | }; |
1184 | |
1185 | // CXXDerivedObjectRegion represents a derived-class object that surrounds |
1186 | // a C++ object. It is identified by the derived class declaration and the |
1187 | // region of its parent object. It is a bit counter-intuitive (but not otherwise |
1188 | // unseen) that this region represents a larger segment of memory that its |
1189 | // super-region. |
1190 | class CXXDerivedObjectRegion : public TypedValueRegion { |
1191 | friend class MemRegionManager; |
1192 | |
1193 | const CXXRecordDecl *DerivedD; |
1194 | |
1195 | CXXDerivedObjectRegion(const CXXRecordDecl *DerivedD, const SubRegion *SReg) |
1196 | : TypedValueRegion(SReg, CXXDerivedObjectRegionKind), DerivedD(DerivedD) { |
1197 | assert(DerivedD)((DerivedD) ? static_cast<void> (0) : __assert_fail ("DerivedD" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1197, __PRETTY_FUNCTION__)); |
1198 | // In case of a concrete region, it should always be possible to model |
1199 | // the base-to-derived cast by undoing a previous derived-to-base cast, |
1200 | // otherwise the cast is most likely ill-formed. |
1201 | assert(SReg->getSymbolicBase() &&((SReg->getSymbolicBase() && "Should have unwrapped a base region instead!" ) ? static_cast<void> (0) : __assert_fail ("SReg->getSymbolicBase() && \"Should have unwrapped a base region instead!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1202, __PRETTY_FUNCTION__)) |
1202 | "Should have unwrapped a base region instead!")((SReg->getSymbolicBase() && "Should have unwrapped a base region instead!" ) ? static_cast<void> (0) : __assert_fail ("SReg->getSymbolicBase() && \"Should have unwrapped a base region instead!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" , 1202, __PRETTY_FUNCTION__)); |
1203 | } |
1204 | |
1205 | static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD, |
1206 | const MemRegion *SReg); |
1207 | |
1208 | public: |
1209 | const CXXRecordDecl *getDecl() const { return DerivedD; } |
1210 | |
1211 | QualType getValueType() const override; |
1212 | |
1213 | void dumpToStream(raw_ostream &os) const override; |
1214 | |
1215 | void Profile(llvm::FoldingSetNodeID &ID) const override; |
1216 | |
1217 | bool canPrintPrettyAsExpr() const override; |
1218 | |
1219 | void printPrettyAsExpr(raw_ostream &os) const override; |
1220 | |
1221 | static bool classof(const MemRegion *region) { |
1222 | return region->getKind() == CXXDerivedObjectRegionKind; |
1223 | } |
1224 | }; |
1225 | |
1226 | template<typename RegionTy> |
1227 | const RegionTy* MemRegion::getAs() const { |
1228 | if (const auto *RT = dyn_cast<RegionTy>(this)) |
1229 | return RT; |
1230 | |
1231 | return nullptr; |
1232 | } |
1233 | |
1234 | //===----------------------------------------------------------------------===// |
1235 | // MemRegionManager - Factory object for creating regions. |
1236 | //===----------------------------------------------------------------------===// |
1237 | |
1238 | class MemRegionManager { |
1239 | ASTContext &C; |
1240 | llvm::BumpPtrAllocator& A; |
1241 | llvm::FoldingSet<MemRegion> Regions; |
1242 | |
1243 | GlobalInternalSpaceRegion *InternalGlobals = nullptr; |
1244 | GlobalSystemSpaceRegion *SystemGlobals = nullptr; |
1245 | GlobalImmutableSpaceRegion *ImmutableGlobals = nullptr; |
1246 | |
1247 | llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> |
1248 | StackLocalsSpaceRegions; |
1249 | llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *> |
1250 | StackArgumentsSpaceRegions; |
1251 | llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *> |
1252 | StaticsGlobalSpaceRegions; |
1253 | |
1254 | HeapSpaceRegion *heap = nullptr; |
1255 | UnknownSpaceRegion *unknown = nullptr; |
1256 | CodeSpaceRegion *code = nullptr; |
1257 | |
1258 | public: |
1259 | MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : C(c), A(a) {} |
1260 | ~MemRegionManager(); |
1261 | |
1262 | ASTContext &getContext() { return C; } |
1263 | |
1264 | llvm::BumpPtrAllocator &getAllocator() { return A; } |
1265 | |
1266 | /// getStackLocalsRegion - Retrieve the memory region associated with the |
1267 | /// specified stack frame. |
1268 | const StackLocalsSpaceRegion * |
1269 | getStackLocalsRegion(const StackFrameContext *STC); |
1270 | |
1271 | /// getStackArgumentsRegion - Retrieve the memory region associated with |
1272 | /// function/method arguments of the specified stack frame. |
1273 | const StackArgumentsSpaceRegion * |
1274 | getStackArgumentsRegion(const StackFrameContext *STC); |
1275 | |
1276 | /// getGlobalsRegion - Retrieve the memory region associated with |
1277 | /// global variables. |
1278 | const GlobalsSpaceRegion *getGlobalsRegion( |
1279 | MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind, |
1280 | const CodeTextRegion *R = nullptr); |
1281 | |
1282 | /// getHeapRegion - Retrieve the memory region associated with the |
1283 | /// generic "heap". |
1284 | const HeapSpaceRegion *getHeapRegion(); |
1285 | |
1286 | /// getUnknownRegion - Retrieve the memory region associated with unknown |
1287 | /// memory space. |
1288 | const UnknownSpaceRegion *getUnknownRegion(); |
1289 | |
1290 | const CodeSpaceRegion *getCodeRegion(); |
1291 | |
1292 | /// getAllocaRegion - Retrieve a region associated with a call to alloca(). |
1293 | const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt, |
1294 | const LocationContext *LC); |
1295 | |
1296 | /// getCompoundLiteralRegion - Retrieve the region associated with a |
1297 | /// given CompoundLiteral. |
1298 | const CompoundLiteralRegion* |
1299 | getCompoundLiteralRegion(const CompoundLiteralExpr *CL, |
1300 | const LocationContext *LC); |
1301 | |
1302 | /// getCXXThisRegion - Retrieve the [artificial] region associated with the |
1303 | /// parameter 'this'. |
1304 | const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, |
1305 | const LocationContext *LC); |
1306 | |
1307 | /// Retrieve or create a "symbolic" memory region. |
1308 | const SymbolicRegion* getSymbolicRegion(SymbolRef Sym); |
1309 | |
1310 | /// Return a unique symbolic region belonging to heap memory space. |
1311 | const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym); |
1312 | |
1313 | const StringRegion *getStringRegion(const StringLiteral *Str); |
1314 | |
1315 | const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str); |
1316 | |
1317 | /// getVarRegion - Retrieve or create the memory region associated with |
1318 | /// a specified VarDecl and LocationContext. |
1319 | const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); |
1320 | |
1321 | /// getVarRegion - Retrieve or create the memory region associated with |
1322 | /// a specified VarDecl and super region. |
1323 | const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR); |
1324 | |
1325 | /// getElementRegion - Retrieve the memory region associated with the |
1326 | /// associated element type, index, and super region. |
1327 | const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx, |
1328 | const SubRegion *superRegion, |
1329 | ASTContext &Ctx); |
1330 | |
1331 | const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, |
1332 | const SubRegion *superRegion) { |
1333 | return getElementRegion(ER->getElementType(), ER->getIndex(), |
1334 | superRegion, ER->getContext()); |
1335 | } |
1336 | |
1337 | /// getFieldRegion - Retrieve or create the memory region associated with |
1338 | /// a specified FieldDecl. 'superRegion' corresponds to the containing |
1339 | /// memory region (which typically represents the memory representing |
1340 | /// a structure or class). |
1341 | const FieldRegion *getFieldRegion(const FieldDecl *fd, |
1342 | const SubRegion* superRegion); |
1343 | |
1344 | const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, |
1345 | const SubRegion *superRegion) { |
1346 | return getFieldRegion(FR->getDecl(), superRegion); |
1347 | } |
1348 | |
1349 | /// getObjCIvarRegion - Retrieve or create the memory region associated with |
1350 | /// a specified Objective-c instance variable. 'superRegion' corresponds |
1351 | /// to the containing region (which typically represents the Objective-C |
1352 | /// object). |
1353 | const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd, |
1354 | const SubRegion* superRegion); |
1355 | |
1356 | const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex, |
1357 | LocationContext const *LC); |
1358 | |
1359 | /// Create a CXXBaseObjectRegion with the given base class for region |
1360 | /// \p Super. |
1361 | /// |
1362 | /// The type of \p Super is assumed be a class deriving from \p BaseClass. |
1363 | const CXXBaseObjectRegion * |
1364 | getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, |
1365 | bool IsVirtual); |
1366 | |
1367 | /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different |
1368 | /// super region. |
1369 | const CXXBaseObjectRegion * |
1370 | getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg, |
1371 | const SubRegion *superRegion) { |
1372 | return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion, |
1373 | baseReg->isVirtual()); |
1374 | } |
1375 | |
1376 | /// Create a CXXDerivedObjectRegion with the given derived class for region |
1377 | /// \p Super. This should not be used for casting an existing |
1378 | /// CXXBaseObjectRegion back to the derived type; instead, CXXBaseObjectRegion |
1379 | /// should be removed. |
1380 | const CXXDerivedObjectRegion * |
1381 | getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass, |
1382 | const SubRegion *Super); |
1383 | |
1384 | const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD); |
1385 | const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD, |
1386 | CanQualType locTy, |
1387 | AnalysisDeclContext *AC); |
1388 | |
1389 | /// getBlockDataRegion - Get the memory region associated with an instance |
1390 | /// of a block. Unlike many other MemRegions, the LocationContext* |
1391 | /// argument is allowed to be NULL for cases where we have no known |
1392 | /// context. |
1393 | const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc, |
1394 | const LocationContext *lc, |
1395 | unsigned blockCount); |
1396 | |
1397 | /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended |
1398 | /// by static references. This differs from getCXXTempObjectRegion in the |
1399 | /// super-region used. |
1400 | const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex); |
1401 | |
1402 | private: |
1403 | template <typename RegionTy, typename SuperTy, |
1404 | typename Arg1Ty> |
1405 | RegionTy* getSubRegion(const Arg1Ty arg1, |
1406 | const SuperTy* superRegion); |
1407 | |
1408 | template <typename RegionTy, typename SuperTy, |
1409 | typename Arg1Ty, typename Arg2Ty> |
1410 | RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, |
1411 | const SuperTy* superRegion); |
1412 | |
1413 | template <typename RegionTy, typename SuperTy, |
1414 | typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> |
1415 | RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, |
1416 | const Arg3Ty arg3, |
1417 | const SuperTy* superRegion); |
1418 | |
1419 | template <typename REG> |
1420 | const REG* LazyAllocate(REG*& region); |
1421 | |
1422 | template <typename REG, typename ARG> |
1423 | const REG* LazyAllocate(REG*& region, ARG a); |
1424 | }; |
1425 | |
1426 | //===----------------------------------------------------------------------===// |
1427 | // Out-of-line member definitions. |
1428 | //===----------------------------------------------------------------------===// |
1429 | |
1430 | inline ASTContext &MemRegion::getContext() const { |
1431 | return getMemRegionManager()->getContext(); |
1432 | } |
1433 | |
1434 | //===----------------------------------------------------------------------===// |
1435 | // Means for storing region/symbol handling traits. |
1436 | //===----------------------------------------------------------------------===// |
1437 | |
1438 | /// Information about invalidation for a particular region/symbol. |
1439 | class RegionAndSymbolInvalidationTraits { |
1440 | using StorageTypeForKinds = unsigned char; |
1441 | |
1442 | llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap; |
1443 | llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap; |
1444 | |
1445 | using const_region_iterator = |
1446 | llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator; |
1447 | using const_symbol_iterator = |
1448 | llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator; |
1449 | |
1450 | public: |
1451 | /// Describes different invalidation traits. |
1452 | enum InvalidationKinds { |
1453 | /// Tells that a region's contents is not changed. |
1454 | TK_PreserveContents = 0x1, |
1455 | |
1456 | /// Suppress pointer-escaping of a region. |
1457 | TK_SuppressEscape = 0x2, |
1458 | |
1459 | // Do not invalidate super region. |
1460 | TK_DoNotInvalidateSuperRegion = 0x4, |
1461 | |
1462 | /// When applied to a MemSpaceRegion, indicates the entire memory space |
1463 | /// should be invalidated. |
1464 | TK_EntireMemSpace = 0x8 |
1465 | |
1466 | // Do not forget to extend StorageTypeForKinds if number of traits exceed |
1467 | // the number of bits StorageTypeForKinds can store. |
1468 | }; |
1469 | |
1470 | void setTrait(SymbolRef Sym, InvalidationKinds IK); |
1471 | void setTrait(const MemRegion *MR, InvalidationKinds IK); |
1472 | bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const; |
1473 | bool hasTrait(const MemRegion *MR, InvalidationKinds IK) const; |
1474 | }; |
1475 | |
1476 | //===----------------------------------------------------------------------===// |
1477 | // Pretty-printing regions. |
1478 | //===----------------------------------------------------------------------===// |
1479 | inline raw_ostream &operator<<(raw_ostream &os, const MemRegion *R) { |
1480 | R->dumpToStream(os); |
1481 | return os; |
1482 | } |
1483 | |
1484 | } // namespace ento |
1485 | |
1486 | } // namespace clang |
1487 | |
1488 | #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H |