File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang/lib/StaticAnalyzer/Core/MemRegion.cpp |
Warning: | line 951, column 36 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/AnalyzerOptions.h" | |||
32 | #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" | |||
33 | #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" | |||
34 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" | |||
35 | #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" | |||
36 | #include "llvm/ADT/APInt.h" | |||
37 | #include "llvm/ADT/FoldingSet.h" | |||
38 | #include "llvm/ADT/Optional.h" | |||
39 | #include "llvm/ADT/PointerUnion.h" | |||
40 | #include "llvm/ADT/SmallString.h" | |||
41 | #include "llvm/ADT/StringRef.h" | |||
42 | #include "llvm/ADT/Twine.h" | |||
43 | #include "llvm/Support/Allocator.h" | |||
44 | #include "llvm/Support/Casting.h" | |||
45 | #include "llvm/Support/CheckedArithmetic.h" | |||
46 | #include "llvm/Support/Compiler.h" | |||
47 | #include "llvm/Support/Debug.h" | |||
48 | #include "llvm/Support/ErrorHandling.h" | |||
49 | #include "llvm/Support/raw_ostream.h" | |||
50 | #include <cassert> | |||
51 | #include <cstdint> | |||
52 | #include <functional> | |||
53 | #include <iterator> | |||
54 | #include <string> | |||
55 | #include <tuple> | |||
56 | #include <utility> | |||
57 | ||||
58 | using namespace clang; | |||
59 | using namespace ento; | |||
60 | ||||
61 | #define DEBUG_TYPE"MemRegion" "MemRegion" | |||
62 | ||||
63 | //===----------------------------------------------------------------------===// | |||
64 | // MemRegion Construction. | |||
65 | //===----------------------------------------------------------------------===// | |||
66 | ||||
67 | template <typename RegionTy, typename SuperTy, typename Arg1Ty> | |||
68 | RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, | |||
69 | const SuperTy *superRegion) { | |||
70 | llvm::FoldingSetNodeID ID; | |||
71 | RegionTy::ProfileRegion(ID, arg1, superRegion); | |||
72 | void *InsertPos; | |||
73 | auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); | |||
74 | ||||
75 | if (!R) { | |||
76 | R = A.Allocate<RegionTy>(); | |||
77 | new (R) RegionTy(arg1, superRegion); | |||
78 | Regions.InsertNode(R, InsertPos); | |||
79 | } | |||
80 | ||||
81 | return R; | |||
82 | } | |||
83 | ||||
84 | template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty> | |||
85 | RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, | |||
86 | const SuperTy *superRegion) { | |||
87 | llvm::FoldingSetNodeID ID; | |||
88 | RegionTy::ProfileRegion(ID, arg1, arg2, superRegion); | |||
89 | void *InsertPos; | |||
90 | auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); | |||
91 | ||||
92 | if (!R) { | |||
93 | R = A.Allocate<RegionTy>(); | |||
94 | new (R) RegionTy(arg1, arg2, superRegion); | |||
95 | Regions.InsertNode(R, InsertPos); | |||
96 | } | |||
97 | ||||
98 | return R; | |||
99 | } | |||
100 | ||||
101 | template <typename RegionTy, typename SuperTy, | |||
102 | typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> | |||
103 | RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, | |||
104 | const Arg3Ty arg3, | |||
105 | const SuperTy *superRegion) { | |||
106 | llvm::FoldingSetNodeID ID; | |||
107 | RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion); | |||
108 | void *InsertPos; | |||
109 | auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); | |||
110 | ||||
111 | if (!R) { | |||
112 | R = A.Allocate<RegionTy>(); | |||
113 | new (R) RegionTy(arg1, arg2, arg3, superRegion); | |||
114 | Regions.InsertNode(R, InsertPos); | |||
115 | } | |||
116 | ||||
117 | return R; | |||
118 | } | |||
119 | ||||
120 | //===----------------------------------------------------------------------===// | |||
121 | // Object destruction. | |||
122 | //===----------------------------------------------------------------------===// | |||
123 | ||||
124 | MemRegion::~MemRegion() = default; | |||
125 | ||||
126 | // All regions and their data are BumpPtrAllocated. No need to call their | |||
127 | // destructors. | |||
128 | MemRegionManager::~MemRegionManager() = default; | |||
129 | ||||
130 | //===----------------------------------------------------------------------===// | |||
131 | // Basic methods. | |||
132 | //===----------------------------------------------------------------------===// | |||
133 | ||||
134 | bool SubRegion::isSubRegionOf(const MemRegion* R) const { | |||
135 | const MemRegion* r = this; | |||
136 | do { | |||
137 | if (r == R) | |||
138 | return true; | |||
139 | if (const auto *sr = dyn_cast<SubRegion>(r)) | |||
140 | r = sr->getSuperRegion(); | |||
141 | else | |||
142 | break; | |||
143 | } while (r != nullptr); | |||
144 | return false; | |||
145 | } | |||
146 | ||||
147 | MemRegionManager &SubRegion::getMemRegionManager() const { | |||
148 | const SubRegion* r = this; | |||
149 | do { | |||
150 | const MemRegion *superRegion = r->getSuperRegion(); | |||
151 | if (const auto *sr = dyn_cast<SubRegion>(superRegion)) { | |||
152 | r = sr; | |||
153 | continue; | |||
154 | } | |||
155 | return superRegion->getMemRegionManager(); | |||
156 | } while (true); | |||
157 | } | |||
158 | ||||
159 | const StackFrameContext *VarRegion::getStackFrame() const { | |||
160 | const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace()); | |||
161 | return SSR ? SSR->getStackFrame() : nullptr; | |||
162 | } | |||
163 | ||||
164 | ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg) | |||
165 | : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {} | |||
166 | ||||
167 | const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; } | |||
168 | ||||
169 | QualType ObjCIvarRegion::getValueType() const { | |||
170 | return getDecl()->getType(); | |||
171 | } | |||
172 | ||||
173 | QualType CXXBaseObjectRegion::getValueType() const { | |||
174 | return QualType(getDecl()->getTypeForDecl(), 0); | |||
175 | } | |||
176 | ||||
177 | QualType CXXDerivedObjectRegion::getValueType() const { | |||
178 | return QualType(getDecl()->getTypeForDecl(), 0); | |||
179 | } | |||
180 | ||||
181 | QualType ParamVarRegion::getValueType() const { | |||
182 | assert(getDecl() &&(static_cast <bool> (getDecl() && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("getDecl() && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 184, __extension__ __PRETTY_FUNCTION__)) | |||
183 | "`ParamVarRegion` support functions without `Decl` not implemented"(static_cast <bool> (getDecl() && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("getDecl() && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 184, __extension__ __PRETTY_FUNCTION__)) | |||
184 | " yet.")(static_cast <bool> (getDecl() && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("getDecl() && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 184, __extension__ __PRETTY_FUNCTION__)); | |||
185 | return getDecl()->getType(); | |||
186 | } | |||
187 | ||||
188 | const ParmVarDecl *ParamVarRegion::getDecl() const { | |||
189 | const Decl *D = getStackFrame()->getDecl(); | |||
190 | ||||
191 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
192 | assert(Index < FD->param_size())(static_cast <bool> (Index < FD->param_size()) ? void (0) : __assert_fail ("Index < FD->param_size()", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 192, __extension__ __PRETTY_FUNCTION__)); | |||
193 | return FD->parameters()[Index]; | |||
194 | } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { | |||
195 | assert(Index < BD->param_size())(static_cast <bool> (Index < BD->param_size()) ? void (0) : __assert_fail ("Index < BD->param_size()", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 195, __extension__ __PRETTY_FUNCTION__)); | |||
196 | return BD->parameters()[Index]; | |||
197 | } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | |||
198 | assert(Index < MD->param_size())(static_cast <bool> (Index < MD->param_size()) ? void (0) : __assert_fail ("Index < MD->param_size()", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 198, __extension__ __PRETTY_FUNCTION__)); | |||
199 | return MD->parameters()[Index]; | |||
200 | } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) { | |||
201 | assert(Index < CD->param_size())(static_cast <bool> (Index < CD->param_size()) ? void (0) : __assert_fail ("Index < CD->param_size()", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 201, __extension__ __PRETTY_FUNCTION__)); | |||
202 | return CD->parameters()[Index]; | |||
203 | } else { | |||
204 | llvm_unreachable("Unexpected Decl kind!")::llvm::llvm_unreachable_internal("Unexpected Decl kind!", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 204); | |||
205 | } | |||
206 | } | |||
207 | ||||
208 | //===----------------------------------------------------------------------===// | |||
209 | // FoldingSet profiling. | |||
210 | //===----------------------------------------------------------------------===// | |||
211 | ||||
212 | void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
213 | ID.AddInteger(static_cast<unsigned>(getKind())); | |||
214 | } | |||
215 | ||||
216 | void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
217 | ID.AddInteger(static_cast<unsigned>(getKind())); | |||
218 | ID.AddPointer(getStackFrame()); | |||
219 | } | |||
220 | ||||
221 | void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
222 | ID.AddInteger(static_cast<unsigned>(getKind())); | |||
223 | ID.AddPointer(getCodeRegion()); | |||
224 | } | |||
225 | ||||
226 | void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
227 | const StringLiteral *Str, | |||
228 | const MemRegion *superRegion) { | |||
229 | ID.AddInteger(static_cast<unsigned>(StringRegionKind)); | |||
230 | ID.AddPointer(Str); | |||
231 | ID.AddPointer(superRegion); | |||
232 | } | |||
233 | ||||
234 | void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
235 | const ObjCStringLiteral *Str, | |||
236 | const MemRegion *superRegion) { | |||
237 | ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind)); | |||
238 | ID.AddPointer(Str); | |||
239 | ID.AddPointer(superRegion); | |||
240 | } | |||
241 | ||||
242 | void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
243 | const Expr *Ex, unsigned cnt, | |||
244 | const MemRegion *superRegion) { | |||
245 | ID.AddInteger(static_cast<unsigned>(AllocaRegionKind)); | |||
246 | ID.AddPointer(Ex); | |||
247 | ID.AddInteger(cnt); | |||
248 | ID.AddPointer(superRegion); | |||
249 | } | |||
250 | ||||
251 | void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
252 | ProfileRegion(ID, Ex, Cnt, superRegion); | |||
253 | } | |||
254 | ||||
255 | void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
256 | CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion); | |||
257 | } | |||
258 | ||||
259 | void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
260 | const CompoundLiteralExpr *CL, | |||
261 | const MemRegion* superRegion) { | |||
262 | ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind)); | |||
263 | ID.AddPointer(CL); | |||
264 | ID.AddPointer(superRegion); | |||
265 | } | |||
266 | ||||
267 | void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
268 | const PointerType *PT, | |||
269 | const MemRegion *sRegion) { | |||
270 | ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind)); | |||
271 | ID.AddPointer(PT); | |||
272 | ID.AddPointer(sRegion); | |||
273 | } | |||
274 | ||||
275 | void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
276 | CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); | |||
277 | } | |||
278 | ||||
279 | void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
280 | ProfileRegion(ID, getDecl(), superRegion); | |||
281 | } | |||
282 | ||||
283 | void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
284 | const ObjCIvarDecl *ivd, | |||
285 | const MemRegion* superRegion) { | |||
286 | ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind)); | |||
287 | ID.AddPointer(ivd); | |||
288 | ID.AddPointer(superRegion); | |||
289 | } | |||
290 | ||||
291 | void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
292 | ProfileRegion(ID, getDecl(), superRegion); | |||
293 | } | |||
294 | ||||
295 | void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
296 | const VarDecl *VD, | |||
297 | const MemRegion *superRegion) { | |||
298 | ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind)); | |||
299 | ID.AddPointer(VD); | |||
300 | ID.AddPointer(superRegion); | |||
301 | } | |||
302 | ||||
303 | void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
304 | ProfileRegion(ID, getDecl(), superRegion); | |||
305 | } | |||
306 | ||||
307 | void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE, | |||
308 | unsigned Idx, const MemRegion *SReg) { | |||
309 | ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind)); | |||
310 | ID.AddPointer(OE); | |||
311 | ID.AddInteger(Idx); | |||
312 | ID.AddPointer(SReg); | |||
313 | } | |||
314 | ||||
315 | void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
316 | ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion); | |||
317 | } | |||
318 | ||||
319 | void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, | |||
320 | const MemRegion *sreg) { | |||
321 | ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind)); | |||
322 | ID.Add(sym); | |||
323 | ID.AddPointer(sreg); | |||
324 | } | |||
325 | ||||
326 | void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
327 | SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion()); | |||
328 | } | |||
329 | ||||
330 | void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
331 | QualType ElementType, SVal Idx, | |||
332 | const MemRegion* superRegion) { | |||
333 | ID.AddInteger(MemRegion::ElementRegionKind); | |||
334 | ID.Add(ElementType); | |||
335 | ID.AddPointer(superRegion); | |||
336 | Idx.Profile(ID); | |||
337 | } | |||
338 | ||||
339 | void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
340 | ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); | |||
341 | } | |||
342 | ||||
343 | void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
344 | const NamedDecl *FD, | |||
345 | const MemRegion*) { | |||
346 | ID.AddInteger(MemRegion::FunctionCodeRegionKind); | |||
347 | ID.AddPointer(FD); | |||
348 | } | |||
349 | ||||
350 | void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
351 | FunctionCodeRegion::ProfileRegion(ID, FD, superRegion); | |||
352 | } | |||
353 | ||||
354 | void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
355 | const BlockDecl *BD, CanQualType, | |||
356 | const AnalysisDeclContext *AC, | |||
357 | const MemRegion*) { | |||
358 | ID.AddInteger(MemRegion::BlockCodeRegionKind); | |||
359 | ID.AddPointer(BD); | |||
360 | } | |||
361 | ||||
362 | void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
363 | BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); | |||
364 | } | |||
365 | ||||
366 | void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | |||
367 | const BlockCodeRegion *BC, | |||
368 | const LocationContext *LC, | |||
369 | unsigned BlkCount, | |||
370 | const MemRegion *sReg) { | |||
371 | ID.AddInteger(MemRegion::BlockDataRegionKind); | |||
372 | ID.AddPointer(BC); | |||
373 | ID.AddPointer(LC); | |||
374 | ID.AddInteger(BlkCount); | |||
375 | ID.AddPointer(sReg); | |||
376 | } | |||
377 | ||||
378 | void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { | |||
379 | BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion()); | |||
380 | } | |||
381 | ||||
382 | void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
383 | Expr const *Ex, | |||
384 | const MemRegion *sReg) { | |||
385 | ID.AddPointer(Ex); | |||
386 | ID.AddPointer(sReg); | |||
387 | } | |||
388 | ||||
389 | void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
390 | ProfileRegion(ID, Ex, getSuperRegion()); | |||
391 | } | |||
392 | ||||
393 | void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
394 | const CXXRecordDecl *RD, | |||
395 | bool IsVirtual, | |||
396 | const MemRegion *SReg) { | |||
397 | ID.AddPointer(RD); | |||
398 | ID.AddBoolean(IsVirtual); | |||
399 | ID.AddPointer(SReg); | |||
400 | } | |||
401 | ||||
402 | void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
403 | ProfileRegion(ID, getDecl(), isVirtual(), superRegion); | |||
404 | } | |||
405 | ||||
406 | void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, | |||
407 | const CXXRecordDecl *RD, | |||
408 | const MemRegion *SReg) { | |||
409 | ID.AddPointer(RD); | |||
410 | ID.AddPointer(SReg); | |||
411 | } | |||
412 | ||||
413 | void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { | |||
414 | ProfileRegion(ID, getDecl(), superRegion); | |||
415 | } | |||
416 | ||||
417 | //===----------------------------------------------------------------------===// | |||
418 | // Region anchors. | |||
419 | //===----------------------------------------------------------------------===// | |||
420 | ||||
421 | void GlobalsSpaceRegion::anchor() {} | |||
422 | ||||
423 | void NonStaticGlobalSpaceRegion::anchor() {} | |||
424 | ||||
425 | void StackSpaceRegion::anchor() {} | |||
426 | ||||
427 | void TypedRegion::anchor() {} | |||
428 | ||||
429 | void TypedValueRegion::anchor() {} | |||
430 | ||||
431 | void CodeTextRegion::anchor() {} | |||
432 | ||||
433 | void SubRegion::anchor() {} | |||
434 | ||||
435 | //===----------------------------------------------------------------------===// | |||
436 | // Region pretty-printing. | |||
437 | //===----------------------------------------------------------------------===// | |||
438 | ||||
439 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void MemRegion::dump() const { | |||
440 | dumpToStream(llvm::errs()); | |||
441 | } | |||
442 | ||||
443 | std::string MemRegion::getString() const { | |||
444 | std::string s; | |||
445 | llvm::raw_string_ostream os(s); | |||
446 | dumpToStream(os); | |||
447 | return s; | |||
448 | } | |||
449 | ||||
450 | void MemRegion::dumpToStream(raw_ostream &os) const { | |||
451 | os << "<Unknown Region>"; | |||
452 | } | |||
453 | ||||
454 | void AllocaRegion::dumpToStream(raw_ostream &os) const { | |||
455 | os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}'; | |||
456 | } | |||
457 | ||||
458 | void FunctionCodeRegion::dumpToStream(raw_ostream &os) const { | |||
459 | os << "code{" << getDecl()->getDeclName().getAsString() << '}'; | |||
460 | } | |||
461 | ||||
462 | void BlockCodeRegion::dumpToStream(raw_ostream &os) const { | |||
463 | os << "block_code{" << static_cast<const void *>(this) << '}'; | |||
464 | } | |||
465 | ||||
466 | void BlockDataRegion::dumpToStream(raw_ostream &os) const { | |||
467 | os << "block_data{" << BC; | |||
468 | os << "; "; | |||
469 | for (BlockDataRegion::referenced_vars_iterator | |||
470 | I = referenced_vars_begin(), | |||
471 | E = referenced_vars_end(); I != E; ++I) | |||
472 | os << "(" << I.getCapturedRegion() << "<-" << | |||
473 | I.getOriginalRegion() << ") "; | |||
474 | os << '}'; | |||
475 | } | |||
476 | ||||
477 | void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { | |||
478 | // FIXME: More elaborate pretty-printing. | |||
479 | os << "{ S" << CL->getID(getContext()) << " }"; | |||
480 | } | |||
481 | ||||
482 | void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { | |||
483 | os << "temp_object{" << getValueType().getAsString() << ", " | |||
484 | << "S" << Ex->getID(getContext()) << '}'; | |||
485 | } | |||
486 | ||||
487 | void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { | |||
488 | os << "Base{" << superRegion << ',' << getDecl()->getName() << '}'; | |||
489 | } | |||
490 | ||||
491 | void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const { | |||
492 | os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}'; | |||
493 | } | |||
494 | ||||
495 | void CXXThisRegion::dumpToStream(raw_ostream &os) const { | |||
496 | os << "this"; | |||
497 | } | |||
498 | ||||
499 | void ElementRegion::dumpToStream(raw_ostream &os) const { | |||
500 | os << "Element{" << superRegion << ',' | |||
501 | << Index << ',' << getElementType().getAsString() << '}'; | |||
502 | } | |||
503 | ||||
504 | void FieldRegion::dumpToStream(raw_ostream &os) const { | |||
505 | os << superRegion << "." << *getDecl(); | |||
506 | } | |||
507 | ||||
508 | void ObjCIvarRegion::dumpToStream(raw_ostream &os) const { | |||
509 | os << "Ivar{" << superRegion << ',' << *getDecl() << '}'; | |||
510 | } | |||
511 | ||||
512 | void StringRegion::dumpToStream(raw_ostream &os) const { | |||
513 | assert(Str != nullptr && "Expecting non-null StringLiteral")(static_cast <bool> (Str != nullptr && "Expecting non-null StringLiteral" ) ? void (0) : __assert_fail ("Str != nullptr && \"Expecting non-null StringLiteral\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 513, __extension__ __PRETTY_FUNCTION__)); | |||
514 | Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); | |||
515 | } | |||
516 | ||||
517 | void ObjCStringRegion::dumpToStream(raw_ostream &os) const { | |||
518 | assert(Str != nullptr && "Expecting non-null ObjCStringLiteral")(static_cast <bool> (Str != nullptr && "Expecting non-null ObjCStringLiteral" ) ? void (0) : __assert_fail ("Str != nullptr && \"Expecting non-null ObjCStringLiteral\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 518, __extension__ __PRETTY_FUNCTION__)); | |||
519 | Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); | |||
520 | } | |||
521 | ||||
522 | void SymbolicRegion::dumpToStream(raw_ostream &os) const { | |||
523 | if (isa<HeapSpaceRegion>(getSuperRegion())) | |||
524 | os << "Heap"; | |||
525 | os << "SymRegion{" << sym << '}'; | |||
526 | } | |||
527 | ||||
528 | void NonParamVarRegion::dumpToStream(raw_ostream &os) const { | |||
529 | if (const IdentifierInfo *ID = VD->getIdentifier()) | |||
530 | os << ID->getName(); | |||
531 | else | |||
532 | os << "NonParamVarRegion{D" << VD->getID() << '}'; | |||
533 | } | |||
534 | ||||
535 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void RegionRawOffset::dump() const { | |||
536 | dumpToStream(llvm::errs()); | |||
537 | } | |||
538 | ||||
539 | void RegionRawOffset::dumpToStream(raw_ostream &os) const { | |||
540 | os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}'; | |||
541 | } | |||
542 | ||||
543 | void CodeSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
544 | os << "CodeSpaceRegion"; | |||
545 | } | |||
546 | ||||
547 | void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
548 | os << "StaticGlobalsMemSpace{" << CR << '}'; | |||
549 | } | |||
550 | ||||
551 | void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
552 | os << "GlobalInternalSpaceRegion"; | |||
553 | } | |||
554 | ||||
555 | void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
556 | os << "GlobalSystemSpaceRegion"; | |||
557 | } | |||
558 | ||||
559 | void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
560 | os << "GlobalImmutableSpaceRegion"; | |||
561 | } | |||
562 | ||||
563 | void HeapSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
564 | os << "HeapSpaceRegion"; | |||
565 | } | |||
566 | ||||
567 | void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
568 | os << "UnknownSpaceRegion"; | |||
569 | } | |||
570 | ||||
571 | void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
572 | os << "StackArgumentsSpaceRegion"; | |||
573 | } | |||
574 | ||||
575 | void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const { | |||
576 | os << "StackLocalsSpaceRegion"; | |||
577 | } | |||
578 | ||||
579 | void ParamVarRegion::dumpToStream(raw_ostream &os) const { | |||
580 | const ParmVarDecl *PVD = getDecl(); | |||
581 | assert(PVD &&(static_cast <bool> (PVD && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("PVD && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 583, __extension__ __PRETTY_FUNCTION__)) | |||
582 | "`ParamVarRegion` support functions without `Decl` not implemented"(static_cast <bool> (PVD && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("PVD && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 583, __extension__ __PRETTY_FUNCTION__)) | |||
583 | " yet.")(static_cast <bool> (PVD && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("PVD && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 583, __extension__ __PRETTY_FUNCTION__)); | |||
584 | if (const IdentifierInfo *ID = PVD->getIdentifier()) { | |||
585 | os << ID->getName(); | |||
586 | } else { | |||
587 | os << "ParamVarRegion{P" << PVD->getID() << '}'; | |||
588 | } | |||
589 | } | |||
590 | ||||
591 | bool MemRegion::canPrintPretty() const { | |||
592 | return canPrintPrettyAsExpr(); | |||
593 | } | |||
594 | ||||
595 | bool MemRegion::canPrintPrettyAsExpr() const { | |||
596 | return false; | |||
597 | } | |||
598 | ||||
599 | void MemRegion::printPretty(raw_ostream &os) const { | |||
600 | assert(canPrintPretty() && "This region cannot be printed pretty.")(static_cast <bool> (canPrintPretty() && "This region cannot be printed pretty." ) ? void (0) : __assert_fail ("canPrintPretty() && \"This region cannot be printed pretty.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 600, __extension__ __PRETTY_FUNCTION__)); | |||
601 | os << "'"; | |||
602 | printPrettyAsExpr(os); | |||
603 | os << "'"; | |||
604 | } | |||
605 | ||||
606 | void MemRegion::printPrettyAsExpr(raw_ostream &) const { | |||
607 | llvm_unreachable("This region cannot be printed pretty.")::llvm::llvm_unreachable_internal("This region cannot be printed pretty." , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 607); | |||
608 | } | |||
609 | ||||
610 | bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; } | |||
611 | ||||
612 | void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
613 | os << getDecl()->getName(); | |||
614 | } | |||
615 | ||||
616 | bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; } | |||
617 | ||||
618 | void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
619 | assert(getDecl() &&(static_cast <bool> (getDecl() && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("getDecl() && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 621, __extension__ __PRETTY_FUNCTION__)) | |||
620 | "`ParamVarRegion` support functions without `Decl` not implemented"(static_cast <bool> (getDecl() && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("getDecl() && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 621, __extension__ __PRETTY_FUNCTION__)) | |||
621 | " yet.")(static_cast <bool> (getDecl() && "`ParamVarRegion` support functions without `Decl` not implemented" " yet.") ? void (0) : __assert_fail ("getDecl() && \"`ParamVarRegion` support functions without `Decl` not implemented\" \" yet.\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 621, __extension__ __PRETTY_FUNCTION__)); | |||
622 | os << getDecl()->getName(); | |||
623 | } | |||
624 | ||||
625 | bool ObjCIvarRegion::canPrintPrettyAsExpr() const { | |||
626 | return true; | |||
627 | } | |||
628 | ||||
629 | void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
630 | os << getDecl()->getName(); | |||
631 | } | |||
632 | ||||
633 | bool FieldRegion::canPrintPretty() const { | |||
634 | return true; | |||
635 | } | |||
636 | ||||
637 | bool FieldRegion::canPrintPrettyAsExpr() const { | |||
638 | return superRegion->canPrintPrettyAsExpr(); | |||
639 | } | |||
640 | ||||
641 | void FieldRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
642 | assert(canPrintPrettyAsExpr())(static_cast <bool> (canPrintPrettyAsExpr()) ? void (0) : __assert_fail ("canPrintPrettyAsExpr()", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 642, __extension__ __PRETTY_FUNCTION__)); | |||
643 | superRegion->printPrettyAsExpr(os); | |||
644 | os << "." << getDecl()->getName(); | |||
645 | } | |||
646 | ||||
647 | void FieldRegion::printPretty(raw_ostream &os) const { | |||
648 | if (canPrintPrettyAsExpr()) { | |||
649 | os << "\'"; | |||
650 | printPrettyAsExpr(os); | |||
651 | os << "'"; | |||
652 | } else { | |||
653 | os << "field " << "\'" << getDecl()->getName() << "'"; | |||
654 | } | |||
655 | } | |||
656 | ||||
657 | bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const { | |||
658 | return superRegion->canPrintPrettyAsExpr(); | |||
659 | } | |||
660 | ||||
661 | void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
662 | superRegion->printPrettyAsExpr(os); | |||
663 | } | |||
664 | ||||
665 | bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const { | |||
666 | return superRegion->canPrintPrettyAsExpr(); | |||
667 | } | |||
668 | ||||
669 | void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const { | |||
670 | superRegion->printPrettyAsExpr(os); | |||
671 | } | |||
672 | ||||
673 | std::string MemRegion::getDescriptiveName(bool UseQuotes) const { | |||
674 | std::string VariableName; | |||
675 | std::string ArrayIndices; | |||
676 | const MemRegion *R = this; | |||
677 | SmallString<50> buf; | |||
678 | llvm::raw_svector_ostream os(buf); | |||
679 | ||||
680 | // Obtain array indices to add them to the variable name. | |||
681 | const ElementRegion *ER = nullptr; | |||
682 | while ((ER = R->getAs<ElementRegion>())) { | |||
683 | // Index is a ConcreteInt. | |||
684 | if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) { | |||
685 | llvm::SmallString<2> Idx; | |||
686 | CI->getValue().toString(Idx); | |||
687 | ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); | |||
688 | } | |||
689 | // If not a ConcreteInt, try to obtain the variable | |||
690 | // name by calling 'getDescriptiveName' recursively. | |||
691 | else { | |||
692 | std::string Idx = ER->getDescriptiveName(false); | |||
693 | if (!Idx.empty()) { | |||
694 | ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); | |||
695 | } | |||
696 | } | |||
697 | R = ER->getSuperRegion(); | |||
698 | } | |||
699 | ||||
700 | // Get variable name. | |||
701 | if (R && R->canPrintPrettyAsExpr()) { | |||
702 | R->printPrettyAsExpr(os); | |||
703 | if (UseQuotes) | |||
704 | return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str(); | |||
705 | else | |||
706 | return (llvm::Twine(os.str()) + ArrayIndices).str(); | |||
707 | } | |||
708 | ||||
709 | return VariableName; | |||
710 | } | |||
711 | ||||
712 | SourceRange MemRegion::sourceRange() const { | |||
713 | const auto *const VR = dyn_cast<VarRegion>(this->getBaseRegion()); | |||
714 | const auto *const FR = dyn_cast<FieldRegion>(this); | |||
715 | ||||
716 | // Check for more specific regions first. | |||
717 | // FieldRegion | |||
718 | if (FR) { | |||
719 | return FR->getDecl()->getSourceRange(); | |||
720 | } | |||
721 | // VarRegion | |||
722 | else if (VR) { | |||
723 | return VR->getDecl()->getSourceRange(); | |||
724 | } | |||
725 | // Return invalid source range (can be checked by client). | |||
726 | else | |||
727 | return {}; | |||
728 | } | |||
729 | ||||
730 | //===----------------------------------------------------------------------===// | |||
731 | // MemRegionManager methods. | |||
732 | //===----------------------------------------------------------------------===// | |||
733 | ||||
734 | DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, | |||
735 | SValBuilder &SVB) const { | |||
736 | const auto *SR = cast<SubRegion>(MR); | |||
737 | SymbolManager &SymMgr = SVB.getSymbolManager(); | |||
738 | ||||
739 | switch (SR->getKind()) { | |||
740 | case MemRegion::AllocaRegionKind: | |||
741 | case MemRegion::SymbolicRegionKind: | |||
742 | return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); | |||
743 | case MemRegion::StringRegionKind: | |||
744 | return SVB.makeIntVal( | |||
745 | cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1, | |||
746 | SVB.getArrayIndexType()); | |||
747 | case MemRegion::CompoundLiteralRegionKind: | |||
748 | case MemRegion::CXXBaseObjectRegionKind: | |||
749 | case MemRegion::CXXDerivedObjectRegionKind: | |||
750 | case MemRegion::CXXTempObjectRegionKind: | |||
751 | case MemRegion::CXXThisRegionKind: | |||
752 | case MemRegion::ObjCIvarRegionKind: | |||
753 | case MemRegion::NonParamVarRegionKind: | |||
754 | case MemRegion::ParamVarRegionKind: | |||
755 | case MemRegion::ElementRegionKind: | |||
756 | case MemRegion::ObjCStringRegionKind: { | |||
757 | QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); | |||
758 | if (isa<VariableArrayType>(Ty)) | |||
759 | return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); | |||
760 | ||||
761 | if (Ty->isIncompleteType()) | |||
762 | return UnknownVal(); | |||
763 | ||||
764 | return getElementExtent(Ty, SVB); | |||
765 | } | |||
766 | case MemRegion::FieldRegionKind: { | |||
767 | // Force callers to deal with bitfields explicitly. | |||
768 | if (cast<FieldRegion>(SR)->getDecl()->isBitField()) | |||
769 | return UnknownVal(); | |||
770 | ||||
771 | QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); | |||
772 | const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB); | |||
773 | ||||
774 | // We currently don't model flexible array members (FAMs), which are: | |||
775 | // - int array[]; of IncompleteArrayType | |||
776 | // - int array[0]; of ConstantArrayType with size 0 | |||
777 | // - int array[1]; of ConstantArrayType with size 1 (*) | |||
778 | // (*): Consider single element array object members as FAM candidates only | |||
779 | // if the consider-single-element-arrays-as-flexible-array-members | |||
780 | // analyzer option is true. | |||
781 | // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html | |||
782 | const auto isFlexibleArrayMemberCandidate = [this, | |||
783 | &SVB](QualType Ty) -> bool { | |||
784 | const ArrayType *AT = Ctx.getAsArrayType(Ty); | |||
785 | if (!AT) | |||
786 | return false; | |||
787 | if (isa<IncompleteArrayType>(AT)) | |||
788 | return true; | |||
789 | ||||
790 | if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { | |||
791 | const llvm::APInt &Size = CAT->getSize(); | |||
792 | if (Size.isZero()) | |||
793 | return true; | |||
794 | ||||
795 | const AnalyzerOptions &Opts = SVB.getAnalyzerOptions(); | |||
796 | if (Opts.ShouldConsiderSingleElementArraysAsFlexibleArrayMembers && | |||
797 | Size.isOne()) | |||
798 | return true; | |||
799 | } | |||
800 | return false; | |||
801 | }; | |||
802 | ||||
803 | if (isFlexibleArrayMemberCandidate(Ty)) | |||
804 | return UnknownVal(); | |||
805 | ||||
806 | return Size; | |||
807 | } | |||
808 | // FIXME: The following are being used in 'SimpleSValBuilder' and in | |||
809 | // 'ArrayBoundChecker::checkLocation' because there is no symbol to | |||
810 | // represent the regions more appropriately. | |||
811 | case MemRegion::BlockDataRegionKind: | |||
812 | case MemRegion::BlockCodeRegionKind: | |||
813 | case MemRegion::FunctionCodeRegionKind: | |||
814 | return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); | |||
815 | default: | |||
816 | llvm_unreachable("Unhandled region")::llvm::llvm_unreachable_internal("Unhandled region", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 816); | |||
817 | } | |||
818 | } | |||
819 | ||||
820 | template <typename REG> | |||
821 | const REG *MemRegionManager::LazyAllocate(REG*& region) { | |||
822 | if (!region) { | |||
823 | region = A.Allocate<REG>(); | |||
824 | new (region) REG(*this); | |||
825 | } | |||
826 | ||||
827 | return region; | |||
828 | } | |||
829 | ||||
830 | template <typename REG, typename ARG> | |||
831 | const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { | |||
832 | if (!region) { | |||
833 | region = A.Allocate<REG>(); | |||
834 | new (region) REG(this, a); | |||
835 | } | |||
836 | ||||
837 | return region; | |||
838 | } | |||
839 | ||||
840 | const StackLocalsSpaceRegion* | |||
841 | MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { | |||
842 | assert(STC)(static_cast <bool> (STC) ? void (0) : __assert_fail ("STC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 842, __extension__ __PRETTY_FUNCTION__)); | |||
843 | StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; | |||
844 | ||||
845 | if (R) | |||
846 | return R; | |||
847 | ||||
848 | R = A.Allocate<StackLocalsSpaceRegion>(); | |||
849 | new (R) StackLocalsSpaceRegion(*this, STC); | |||
850 | return R; | |||
851 | } | |||
852 | ||||
853 | const StackArgumentsSpaceRegion * | |||
854 | MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { | |||
855 | assert(STC)(static_cast <bool> (STC) ? void (0) : __assert_fail ("STC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 855, __extension__ __PRETTY_FUNCTION__)); | |||
856 | StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC]; | |||
857 | ||||
858 | if (R) | |||
859 | return R; | |||
860 | ||||
861 | R = A.Allocate<StackArgumentsSpaceRegion>(); | |||
862 | new (R) StackArgumentsSpaceRegion(*this, STC); | |||
863 | return R; | |||
864 | } | |||
865 | ||||
866 | const GlobalsSpaceRegion | |||
867 | *MemRegionManager::getGlobalsRegion(MemRegion::Kind K, | |||
868 | const CodeTextRegion *CR) { | |||
869 | if (!CR) { | |||
870 | if (K == MemRegion::GlobalSystemSpaceRegionKind) | |||
871 | return LazyAllocate(SystemGlobals); | |||
872 | if (K == MemRegion::GlobalImmutableSpaceRegionKind) | |||
873 | return LazyAllocate(ImmutableGlobals); | |||
874 | assert(K == MemRegion::GlobalInternalSpaceRegionKind)(static_cast <bool> (K == MemRegion::GlobalInternalSpaceRegionKind ) ? void (0) : __assert_fail ("K == MemRegion::GlobalInternalSpaceRegionKind" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 874, __extension__ __PRETTY_FUNCTION__)); | |||
875 | return LazyAllocate(InternalGlobals); | |||
876 | } | |||
877 | ||||
878 | assert(K == MemRegion::StaticGlobalSpaceRegionKind)(static_cast <bool> (K == MemRegion::StaticGlobalSpaceRegionKind ) ? void (0) : __assert_fail ("K == MemRegion::StaticGlobalSpaceRegionKind" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 878, __extension__ __PRETTY_FUNCTION__)); | |||
879 | StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR]; | |||
880 | if (R) | |||
881 | return R; | |||
882 | ||||
883 | R = A.Allocate<StaticGlobalSpaceRegion>(); | |||
884 | new (R) StaticGlobalSpaceRegion(*this, CR); | |||
885 | return R; | |||
886 | } | |||
887 | ||||
888 | const HeapSpaceRegion *MemRegionManager::getHeapRegion() { | |||
889 | return LazyAllocate(heap); | |||
890 | } | |||
891 | ||||
892 | const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() { | |||
893 | return LazyAllocate(unknown); | |||
894 | } | |||
895 | ||||
896 | const CodeSpaceRegion *MemRegionManager::getCodeRegion() { | |||
897 | return LazyAllocate(code); | |||
898 | } | |||
899 | ||||
900 | //===----------------------------------------------------------------------===// | |||
901 | // Constructing regions. | |||
902 | //===----------------------------------------------------------------------===// | |||
903 | ||||
904 | const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){ | |||
905 | return getSubRegion<StringRegion>( | |||
906 | Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); | |||
907 | } | |||
908 | ||||
909 | const ObjCStringRegion * | |||
910 | MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){ | |||
911 | return getSubRegion<ObjCStringRegion>( | |||
912 | Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); | |||
913 | } | |||
914 | ||||
915 | /// Look through a chain of LocationContexts to either find the | |||
916 | /// StackFrameContext that matches a DeclContext, or find a VarRegion | |||
917 | /// for a variable captured by a block. | |||
918 | static llvm::PointerUnion<const StackFrameContext *, const VarRegion *> | |||
919 | getStackOrCaptureRegionForDeclContext(const LocationContext *LC, | |||
920 | const DeclContext *DC, | |||
921 | const VarDecl *VD) { | |||
922 | while (LC) { | |||
923 | if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) { | |||
924 | if (cast<DeclContext>(SFC->getDecl()) == DC) | |||
925 | return SFC; | |||
926 | } | |||
927 | if (const auto *BC = dyn_cast<BlockInvocationContext>(LC)) { | |||
928 | const auto *BR = static_cast<const BlockDataRegion *>(BC->getData()); | |||
929 | // FIXME: This can be made more efficient. | |||
930 | for (BlockDataRegion::referenced_vars_iterator | |||
931 | I = BR->referenced_vars_begin(), | |||
932 | E = BR->referenced_vars_end(); I != E; ++I) { | |||
933 | const TypedValueRegion *OrigR = I.getOriginalRegion(); | |||
934 | if (const auto *VR = dyn_cast<VarRegion>(OrigR)) { | |||
935 | if (VR->getDecl() == VD) | |||
936 | return cast<VarRegion>(I.getCapturedRegion()); | |||
937 | } | |||
938 | } | |||
939 | } | |||
940 | ||||
941 | LC = LC->getParent(); | |||
942 | } | |||
943 | return (const StackFrameContext *)nullptr; | |||
944 | } | |||
945 | ||||
946 | const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, | |||
947 | const LocationContext *LC) { | |||
948 | const auto *PVD = dyn_cast<ParmVarDecl>(D); | |||
949 | if (PVD
| |||
950 | unsigned Index = PVD->getFunctionScopeIndex(); | |||
951 | const StackFrameContext *SFC = LC->getStackFrame(); | |||
| ||||
952 | const Stmt *CallSite = SFC->getCallSite(); | |||
953 | if (CallSite) { | |||
954 | const Decl *D = SFC->getDecl(); | |||
955 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
956 | if (Index < FD->param_size() && FD->parameters()[Index] == PVD) | |||
957 | return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, | |||
958 | getStackArgumentsRegion(SFC)); | |||
959 | } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { | |||
960 | if (Index < BD->param_size() && BD->parameters()[Index] == PVD) | |||
961 | return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, | |||
962 | getStackArgumentsRegion(SFC)); | |||
963 | } else { | |||
964 | return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, | |||
965 | getStackArgumentsRegion(SFC)); | |||
966 | } | |||
967 | } | |||
968 | } | |||
969 | ||||
970 | D = D->getCanonicalDecl(); | |||
971 | const MemRegion *sReg = nullptr; | |||
972 | ||||
973 | if (D->hasGlobalStorage() && !D->isStaticLocal()) { | |||
974 | ||||
975 | // First handle the globals defined in system headers. | |||
976 | if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) { | |||
977 | // Allow the system globals which often DO GET modified, assume the | |||
978 | // rest are immutable. | |||
979 | if (D->getName().contains("errno")) | |||
980 | sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); | |||
981 | else | |||
982 | sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); | |||
983 | ||||
984 | // Treat other globals as GlobalInternal unless they are constants. | |||
985 | } else { | |||
986 | QualType GQT = D->getType(); | |||
987 | const Type *GT = GQT.getTypePtrOrNull(); | |||
988 | // TODO: We could walk the complex types here and see if everything is | |||
989 | // constified. | |||
990 | if (GT && GQT.isConstQualified() && GT->isArithmeticType()) | |||
991 | sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); | |||
992 | else | |||
993 | sReg = getGlobalsRegion(); | |||
994 | } | |||
995 | ||||
996 | // Finally handle static locals. | |||
997 | } else { | |||
998 | // FIXME: Once we implement scope handling, we will need to properly lookup | |||
999 | // 'D' to the proper LocationContext. | |||
1000 | const DeclContext *DC = D->getDeclContext(); | |||
1001 | llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V = | |||
1002 | getStackOrCaptureRegionForDeclContext(LC, DC, D); | |||
1003 | ||||
1004 | if (V.is<const VarRegion*>()) | |||
1005 | return V.get<const VarRegion*>(); | |||
1006 | ||||
1007 | const auto *STC = V.get<const StackFrameContext *>(); | |||
1008 | ||||
1009 | if (!STC) { | |||
1010 | // FIXME: Assign a more sensible memory space to static locals | |||
1011 | // we see from within blocks that we analyze as top-level declarations. | |||
1012 | sReg = getUnknownRegion(); | |||
1013 | } else { | |||
1014 | if (D->hasLocalStorage()) { | |||
1015 | sReg = | |||
1016 | isa<ParmVarDecl, ImplicitParamDecl>(D) | |||
1017 | ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC)) | |||
1018 | : static_cast<const MemRegion *>(getStackLocalsRegion(STC)); | |||
1019 | } | |||
1020 | else { | |||
1021 | assert(D->isStaticLocal())(static_cast <bool> (D->isStaticLocal()) ? void (0) : __assert_fail ("D->isStaticLocal()", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1021, __extension__ __PRETTY_FUNCTION__)); | |||
1022 | const Decl *STCD = STC->getDecl(); | |||
1023 | if (isa<FunctionDecl, ObjCMethodDecl>(STCD)) | |||
1024 | sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, | |||
1025 | getFunctionCodeRegion(cast<NamedDecl>(STCD))); | |||
1026 | else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) { | |||
1027 | // FIXME: The fallback type here is totally bogus -- though it should | |||
1028 | // never be queried, it will prevent uniquing with the real | |||
1029 | // BlockCodeRegion. Ideally we'd fix the AST so that we always had a | |||
1030 | // signature. | |||
1031 | QualType T; | |||
1032 | if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) | |||
1033 | T = TSI->getType(); | |||
1034 | if (T.isNull()) | |||
1035 | T = getContext().VoidTy; | |||
1036 | if (!T->getAs<FunctionType>()) | |||
1037 | T = getContext().getFunctionNoProtoType(T); | |||
1038 | T = getContext().getBlockPointerType(T); | |||
1039 | ||||
1040 | const BlockCodeRegion *BTR = | |||
1041 | getBlockCodeRegion(BD, Ctx.getCanonicalType(T), | |||
1042 | STC->getAnalysisDeclContext()); | |||
1043 | sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, | |||
1044 | BTR); | |||
1045 | } | |||
1046 | else { | |||
1047 | sReg = getGlobalsRegion(); | |||
1048 | } | |||
1049 | } | |||
1050 | } | |||
1051 | } | |||
1052 | ||||
1053 | return getSubRegion<NonParamVarRegion>(D, sReg); | |||
1054 | } | |||
1055 | ||||
1056 | const NonParamVarRegion * | |||
1057 | MemRegionManager::getNonParamVarRegion(const VarDecl *D, | |||
1058 | const MemRegion *superR) { | |||
1059 | D = D->getCanonicalDecl(); | |||
1060 | return getSubRegion<NonParamVarRegion>(D, superR); | |||
1061 | } | |||
1062 | ||||
1063 | const ParamVarRegion * | |||
1064 | MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index, | |||
1065 | const LocationContext *LC) { | |||
1066 | const StackFrameContext *SFC = LC->getStackFrame(); | |||
1067 | assert(SFC)(static_cast <bool> (SFC) ? void (0) : __assert_fail ("SFC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1067, __extension__ __PRETTY_FUNCTION__)); | |||
1068 | return getSubRegion<ParamVarRegion>(OriginExpr, Index, | |||
1069 | getStackArgumentsRegion(SFC)); | |||
1070 | } | |||
1071 | ||||
1072 | const BlockDataRegion * | |||
1073 | MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, | |||
1074 | const LocationContext *LC, | |||
1075 | unsigned blockCount) { | |||
1076 | const MemSpaceRegion *sReg = nullptr; | |||
1077 | const BlockDecl *BD = BC->getDecl(); | |||
1078 | if (!BD->hasCaptures()) { | |||
1079 | // This handles 'static' blocks. | |||
1080 | sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); | |||
1081 | } | |||
1082 | else { | |||
1083 | if (LC) { | |||
1084 | // FIXME: Once we implement scope handling, we want the parent region | |||
1085 | // to be the scope. | |||
1086 | const StackFrameContext *STC = LC->getStackFrame(); | |||
1087 | assert(STC)(static_cast <bool> (STC) ? void (0) : __assert_fail ("STC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1087, __extension__ __PRETTY_FUNCTION__)); | |||
1088 | sReg = getStackLocalsRegion(STC); | |||
1089 | } | |||
1090 | else { | |||
1091 | // We allow 'LC' to be NULL for cases where want BlockDataRegions | |||
1092 | // without context-sensitivity. | |||
1093 | sReg = getUnknownRegion(); | |||
1094 | } | |||
1095 | } | |||
1096 | ||||
1097 | return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg); | |||
1098 | } | |||
1099 | ||||
1100 | const CXXTempObjectRegion * | |||
1101 | MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) { | |||
1102 | return getSubRegion<CXXTempObjectRegion>( | |||
1103 | Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr)); | |||
1104 | } | |||
1105 | ||||
1106 | const CompoundLiteralRegion* | |||
1107 | MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, | |||
1108 | const LocationContext *LC) { | |||
1109 | const MemSpaceRegion *sReg = nullptr; | |||
1110 | ||||
1111 | if (CL->isFileScope()) | |||
1112 | sReg = getGlobalsRegion(); | |||
1113 | else { | |||
1114 | const StackFrameContext *STC = LC->getStackFrame(); | |||
1115 | assert(STC)(static_cast <bool> (STC) ? void (0) : __assert_fail ("STC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1115, __extension__ __PRETTY_FUNCTION__)); | |||
1116 | sReg = getStackLocalsRegion(STC); | |||
1117 | } | |||
1118 | ||||
1119 | return getSubRegion<CompoundLiteralRegion>(CL, sReg); | |||
1120 | } | |||
1121 | ||||
1122 | const ElementRegion* | |||
1123 | MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, | |||
1124 | const SubRegion* superRegion, | |||
1125 | ASTContext &Ctx){ | |||
1126 | QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); | |||
1127 | ||||
1128 | llvm::FoldingSetNodeID ID; | |||
1129 | ElementRegion::ProfileRegion(ID, T, Idx, superRegion); | |||
1130 | ||||
1131 | void *InsertPos; | |||
1132 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | |||
1133 | auto *R = cast_or_null<ElementRegion>(data); | |||
1134 | ||||
1135 | if (!R) { | |||
1136 | R = A.Allocate<ElementRegion>(); | |||
1137 | new (R) ElementRegion(T, Idx, superRegion); | |||
1138 | Regions.InsertNode(R, InsertPos); | |||
1139 | } | |||
1140 | ||||
1141 | return R; | |||
1142 | } | |||
1143 | ||||
1144 | const FunctionCodeRegion * | |||
1145 | MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) { | |||
1146 | // To think: should we canonicalize the declaration here? | |||
1147 | return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion()); | |||
1148 | } | |||
1149 | ||||
1150 | const BlockCodeRegion * | |||
1151 | MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, | |||
1152 | AnalysisDeclContext *AC) { | |||
1153 | return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion()); | |||
1154 | } | |||
1155 | ||||
1156 | const SymbolicRegion * | |||
1157 | MemRegionManager::getSymbolicRegion(SymbolRef sym, | |||
1158 | const MemSpaceRegion *MemSpace) { | |||
1159 | if (MemSpace == nullptr) | |||
1160 | MemSpace = getUnknownRegion(); | |||
1161 | return getSubRegion<SymbolicRegion>(sym, MemSpace); | |||
1162 | } | |||
1163 | ||||
1164 | const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) { | |||
1165 | return getSubRegion<SymbolicRegion>(Sym, getHeapRegion()); | |||
1166 | } | |||
1167 | ||||
1168 | const FieldRegion* | |||
1169 | MemRegionManager::getFieldRegion(const FieldDecl *d, | |||
1170 | const SubRegion* superRegion){ | |||
1171 | return getSubRegion<FieldRegion>(d, superRegion); | |||
1172 | } | |||
1173 | ||||
1174 | const ObjCIvarRegion* | |||
1175 | MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, | |||
1176 | const SubRegion* superRegion) { | |||
1177 | return getSubRegion<ObjCIvarRegion>(d, superRegion); | |||
1178 | } | |||
1179 | ||||
1180 | const CXXTempObjectRegion* | |||
1181 | MemRegionManager::getCXXTempObjectRegion(Expr const *E, | |||
1182 | LocationContext const *LC) { | |||
1183 | const StackFrameContext *SFC = LC->getStackFrame(); | |||
1184 | assert(SFC)(static_cast <bool> (SFC) ? void (0) : __assert_fail ("SFC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1184, __extension__ __PRETTY_FUNCTION__)); | |||
1185 | return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC)); | |||
1186 | } | |||
1187 | ||||
1188 | /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base | |||
1189 | /// class of the type of \p Super. | |||
1190 | static bool isValidBaseClass(const CXXRecordDecl *BaseClass, | |||
1191 | const TypedValueRegion *Super, | |||
1192 | bool IsVirtual) { | |||
1193 | BaseClass = BaseClass->getCanonicalDecl(); | |||
1194 | ||||
1195 | const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl(); | |||
1196 | if (!Class) | |||
1197 | return true; | |||
1198 | ||||
1199 | if (IsVirtual) | |||
1200 | return Class->isVirtuallyDerivedFrom(BaseClass); | |||
1201 | ||||
1202 | for (const auto &I : Class->bases()) { | |||
1203 | if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass) | |||
1204 | return true; | |||
1205 | } | |||
1206 | ||||
1207 | return false; | |||
1208 | } | |||
1209 | ||||
1210 | const CXXBaseObjectRegion * | |||
1211 | MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, | |||
1212 | const SubRegion *Super, | |||
1213 | bool IsVirtual) { | |||
1214 | if (isa<TypedValueRegion>(Super)) { | |||
1215 | assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual))(static_cast <bool> (isValidBaseClass(RD, cast<TypedValueRegion >(Super), IsVirtual)) ? void (0) : __assert_fail ("isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual)" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1215, __extension__ __PRETTY_FUNCTION__)); | |||
1216 | (void)&isValidBaseClass; | |||
1217 | ||||
1218 | if (IsVirtual) { | |||
1219 | // Virtual base regions should not be layered, since the layout rules | |||
1220 | // are different. | |||
1221 | while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super)) | |||
1222 | Super = cast<SubRegion>(Base->getSuperRegion()); | |||
1223 | assert(Super && !isa<MemSpaceRegion>(Super))(static_cast <bool> (Super && !isa<MemSpaceRegion >(Super)) ? void (0) : __assert_fail ("Super && !isa<MemSpaceRegion>(Super)" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1223, __extension__ __PRETTY_FUNCTION__)); | |||
1224 | } | |||
1225 | } | |||
1226 | ||||
1227 | return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super); | |||
1228 | } | |||
1229 | ||||
1230 | const CXXDerivedObjectRegion * | |||
1231 | MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD, | |||
1232 | const SubRegion *Super) { | |||
1233 | return getSubRegion<CXXDerivedObjectRegion>(RD, Super); | |||
1234 | } | |||
1235 | ||||
1236 | const CXXThisRegion* | |||
1237 | MemRegionManager::getCXXThisRegion(QualType thisPointerTy, | |||
1238 | const LocationContext *LC) { | |||
1239 | const auto *PT = thisPointerTy->getAs<PointerType>(); | |||
1240 | assert(PT)(static_cast <bool> (PT) ? void (0) : __assert_fail ("PT" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1240, __extension__ __PRETTY_FUNCTION__)); | |||
1241 | // Inside the body of the operator() of a lambda a this expr might refer to an | |||
1242 | // object in one of the parent location contexts. | |||
1243 | const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl()); | |||
1244 | // FIXME: when operator() of lambda is analyzed as a top level function and | |||
1245 | // 'this' refers to a this to the enclosing scope, there is no right region to | |||
1246 | // return. | |||
1247 | while (!LC->inTopFrame() && (!D || D->isStatic() || | |||
1248 | PT != D->getThisType()->getAs<PointerType>())) { | |||
1249 | LC = LC->getParent(); | |||
1250 | D = dyn_cast<CXXMethodDecl>(LC->getDecl()); | |||
1251 | } | |||
1252 | const StackFrameContext *STC = LC->getStackFrame(); | |||
1253 | assert(STC)(static_cast <bool> (STC) ? void (0) : __assert_fail ("STC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1253, __extension__ __PRETTY_FUNCTION__)); | |||
1254 | return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); | |||
1255 | } | |||
1256 | ||||
1257 | const AllocaRegion* | |||
1258 | MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, | |||
1259 | const LocationContext *LC) { | |||
1260 | const StackFrameContext *STC = LC->getStackFrame(); | |||
1261 | assert(STC)(static_cast <bool> (STC) ? void (0) : __assert_fail ("STC" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1261, __extension__ __PRETTY_FUNCTION__)); | |||
1262 | return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC)); | |||
1263 | } | |||
1264 | ||||
1265 | const MemSpaceRegion *MemRegion::getMemorySpace() const { | |||
1266 | const MemRegion *R = this; | |||
1267 | const auto *SR = dyn_cast<SubRegion>(this); | |||
1268 | ||||
1269 | while (SR) { | |||
1270 | R = SR->getSuperRegion(); | |||
1271 | SR = dyn_cast<SubRegion>(R); | |||
1272 | } | |||
1273 | ||||
1274 | return dyn_cast<MemSpaceRegion>(R); | |||
1275 | } | |||
1276 | ||||
1277 | bool MemRegion::hasStackStorage() const { | |||
1278 | return isa<StackSpaceRegion>(getMemorySpace()); | |||
1279 | } | |||
1280 | ||||
1281 | bool MemRegion::hasStackNonParametersStorage() const { | |||
1282 | return isa<StackLocalsSpaceRegion>(getMemorySpace()); | |||
1283 | } | |||
1284 | ||||
1285 | bool MemRegion::hasStackParametersStorage() const { | |||
1286 | return isa<StackArgumentsSpaceRegion>(getMemorySpace()); | |||
1287 | } | |||
1288 | ||||
1289 | bool MemRegion::hasGlobalsOrParametersStorage() const { | |||
1290 | return isa<StackArgumentsSpaceRegion, GlobalsSpaceRegion>(getMemorySpace()); | |||
1291 | } | |||
1292 | ||||
1293 | // getBaseRegion strips away all elements and fields, and get the base region | |||
1294 | // of them. | |||
1295 | const MemRegion *MemRegion::getBaseRegion() const { | |||
1296 | const MemRegion *R = this; | |||
1297 | while (true) { | |||
1298 | switch (R->getKind()) { | |||
1299 | case MemRegion::ElementRegionKind: | |||
1300 | case MemRegion::FieldRegionKind: | |||
1301 | case MemRegion::ObjCIvarRegionKind: | |||
1302 | case MemRegion::CXXBaseObjectRegionKind: | |||
1303 | case MemRegion::CXXDerivedObjectRegionKind: | |||
1304 | R = cast<SubRegion>(R)->getSuperRegion(); | |||
1305 | continue; | |||
1306 | default: | |||
1307 | break; | |||
1308 | } | |||
1309 | break; | |||
1310 | } | |||
1311 | return R; | |||
1312 | } | |||
1313 | ||||
1314 | // getgetMostDerivedObjectRegion gets the region of the root class of a C++ | |||
1315 | // class hierarchy. | |||
1316 | const MemRegion *MemRegion::getMostDerivedObjectRegion() const { | |||
1317 | const MemRegion *R = this; | |||
1318 | while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R)) | |||
1319 | R = BR->getSuperRegion(); | |||
1320 | return R; | |||
1321 | } | |||
1322 | ||||
1323 | bool MemRegion::isSubRegionOf(const MemRegion *) const { | |||
1324 | return false; | |||
1325 | } | |||
1326 | ||||
1327 | //===----------------------------------------------------------------------===// | |||
1328 | // View handling. | |||
1329 | //===----------------------------------------------------------------------===// | |||
1330 | ||||
1331 | const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const { | |||
1332 | const MemRegion *R = this; | |||
1333 | while (true) { | |||
1334 | switch (R->getKind()) { | |||
1335 | case ElementRegionKind: { | |||
1336 | const auto *ER = cast<ElementRegion>(R); | |||
1337 | if (!ER->getIndex().isZeroConstant()) | |||
1338 | return R; | |||
1339 | R = ER->getSuperRegion(); | |||
1340 | break; | |||
1341 | } | |||
1342 | case CXXBaseObjectRegionKind: | |||
1343 | case CXXDerivedObjectRegionKind: | |||
1344 | if (!StripBaseAndDerivedCasts) | |||
1345 | return R; | |||
1346 | R = cast<TypedValueRegion>(R)->getSuperRegion(); | |||
1347 | break; | |||
1348 | default: | |||
1349 | return R; | |||
1350 | } | |||
1351 | } | |||
1352 | } | |||
1353 | ||||
1354 | const SymbolicRegion *MemRegion::getSymbolicBase() const { | |||
1355 | const auto *SubR = dyn_cast<SubRegion>(this); | |||
1356 | ||||
1357 | while (SubR) { | |||
1358 | if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR)) | |||
1359 | return SymR; | |||
1360 | SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); | |||
1361 | } | |||
1362 | return nullptr; | |||
1363 | } | |||
1364 | ||||
1365 | RegionRawOffset ElementRegion::getAsArrayOffset() const { | |||
1366 | int64_t offset = 0; | |||
1367 | const ElementRegion *ER = this; | |||
1368 | const MemRegion *superR = nullptr; | |||
1369 | ASTContext &C = getContext(); | |||
1370 | ||||
1371 | // FIXME: Handle multi-dimensional arrays. | |||
1372 | ||||
1373 | while (ER) { | |||
1374 | superR = ER->getSuperRegion(); | |||
1375 | ||||
1376 | // FIXME: generalize to symbolic offsets. | |||
1377 | SVal index = ER->getIndex(); | |||
1378 | if (auto CI = index.getAs<nonloc::ConcreteInt>()) { | |||
1379 | // Update the offset. | |||
1380 | int64_t i = CI->getValue().getSExtValue(); | |||
1381 | ||||
1382 | if (i != 0) { | |||
1383 | QualType elemType = ER->getElementType(); | |||
1384 | ||||
1385 | // If we are pointing to an incomplete type, go no further. | |||
1386 | if (elemType->isIncompleteType()) { | |||
1387 | superR = ER; | |||
1388 | break; | |||
1389 | } | |||
1390 | ||||
1391 | int64_t size = C.getTypeSizeInChars(elemType).getQuantity(); | |||
1392 | if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) { | |||
1393 | offset = *NewOffset; | |||
1394 | } else { | |||
1395 | LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("MemRegion")) { llvm::dbgs() << "MemRegion::getAsArrayOffset: " << "offset overflowing, returning unknown\n"; } } while (false) | |||
1396 | << "offset overflowing, returning unknown\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("MemRegion")) { llvm::dbgs() << "MemRegion::getAsArrayOffset: " << "offset overflowing, returning unknown\n"; } } while (false); | |||
1397 | ||||
1398 | return nullptr; | |||
1399 | } | |||
1400 | } | |||
1401 | ||||
1402 | // Go to the next ElementRegion (if any). | |||
1403 | ER = dyn_cast<ElementRegion>(superR); | |||
1404 | continue; | |||
1405 | } | |||
1406 | ||||
1407 | return nullptr; | |||
1408 | } | |||
1409 | ||||
1410 | assert(superR && "super region cannot be NULL")(static_cast <bool> (superR && "super region cannot be NULL" ) ? void (0) : __assert_fail ("superR && \"super region cannot be NULL\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1410, __extension__ __PRETTY_FUNCTION__)); | |||
1411 | return RegionRawOffset(superR, CharUnits::fromQuantity(offset)); | |||
1412 | } | |||
1413 | ||||
1414 | /// Returns true if \p Base is an immediate base class of \p Child | |||
1415 | static bool isImmediateBase(const CXXRecordDecl *Child, | |||
1416 | const CXXRecordDecl *Base) { | |||
1417 | assert(Child && "Child must not be null")(static_cast <bool> (Child && "Child must not be null" ) ? void (0) : __assert_fail ("Child && \"Child must not be null\"" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1417, __extension__ __PRETTY_FUNCTION__)); | |||
1418 | // Note that we do NOT canonicalize the base class here, because | |||
1419 | // ASTRecordLayout doesn't either. If that leads us down the wrong path, | |||
1420 | // so be it; at least we won't crash. | |||
1421 | for (const auto &I : Child->bases()) { | |||
1422 | if (I.getType()->getAsCXXRecordDecl() == Base) | |||
1423 | return true; | |||
1424 | } | |||
1425 | ||||
1426 | return false; | |||
1427 | } | |||
1428 | ||||
1429 | static RegionOffset calculateOffset(const MemRegion *R) { | |||
1430 | const MemRegion *SymbolicOffsetBase = nullptr; | |||
1431 | int64_t Offset = 0; | |||
1432 | ||||
1433 | while (true) { | |||
1434 | switch (R->getKind()) { | |||
1435 | case MemRegion::CodeSpaceRegionKind: | |||
1436 | case MemRegion::StackLocalsSpaceRegionKind: | |||
1437 | case MemRegion::StackArgumentsSpaceRegionKind: | |||
1438 | case MemRegion::HeapSpaceRegionKind: | |||
1439 | case MemRegion::UnknownSpaceRegionKind: | |||
1440 | case MemRegion::StaticGlobalSpaceRegionKind: | |||
1441 | case MemRegion::GlobalInternalSpaceRegionKind: | |||
1442 | case MemRegion::GlobalSystemSpaceRegionKind: | |||
1443 | case MemRegion::GlobalImmutableSpaceRegionKind: | |||
1444 | // Stores can bind directly to a region space to set a default value. | |||
1445 | assert(Offset == 0 && !SymbolicOffsetBase)(static_cast <bool> (Offset == 0 && !SymbolicOffsetBase ) ? void (0) : __assert_fail ("Offset == 0 && !SymbolicOffsetBase" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1445, __extension__ __PRETTY_FUNCTION__)); | |||
1446 | goto Finish; | |||
1447 | ||||
1448 | case MemRegion::FunctionCodeRegionKind: | |||
1449 | case MemRegion::BlockCodeRegionKind: | |||
1450 | case MemRegion::BlockDataRegionKind: | |||
1451 | // These will never have bindings, but may end up having values requested | |||
1452 | // if the user does some strange casting. | |||
1453 | if (Offset != 0) | |||
1454 | SymbolicOffsetBase = R; | |||
1455 | goto Finish; | |||
1456 | ||||
1457 | case MemRegion::SymbolicRegionKind: | |||
1458 | case MemRegion::AllocaRegionKind: | |||
1459 | case MemRegion::CompoundLiteralRegionKind: | |||
1460 | case MemRegion::CXXThisRegionKind: | |||
1461 | case MemRegion::StringRegionKind: | |||
1462 | case MemRegion::ObjCStringRegionKind: | |||
1463 | case MemRegion::NonParamVarRegionKind: | |||
1464 | case MemRegion::ParamVarRegionKind: | |||
1465 | case MemRegion::CXXTempObjectRegionKind: | |||
1466 | // Usual base regions. | |||
1467 | goto Finish; | |||
1468 | ||||
1469 | case MemRegion::ObjCIvarRegionKind: | |||
1470 | // This is a little strange, but it's a compromise between | |||
1471 | // ObjCIvarRegions having unknown compile-time offsets (when using the | |||
1472 | // non-fragile runtime) and yet still being distinct, non-overlapping | |||
1473 | // regions. Thus we treat them as "like" base regions for the purposes | |||
1474 | // of computing offsets. | |||
1475 | goto Finish; | |||
1476 | ||||
1477 | case MemRegion::CXXBaseObjectRegionKind: { | |||
1478 | const auto *BOR = cast<CXXBaseObjectRegion>(R); | |||
1479 | R = BOR->getSuperRegion(); | |||
1480 | ||||
1481 | QualType Ty; | |||
1482 | bool RootIsSymbolic = false; | |||
1483 | if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) { | |||
1484 | Ty = TVR->getDesugaredValueType(R->getContext()); | |||
1485 | } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) { | |||
1486 | // If our base region is symbolic, we don't know what type it really is. | |||
1487 | // Pretend the type of the symbol is the true dynamic type. | |||
1488 | // (This will at least be self-consistent for the life of the symbol.) | |||
1489 | Ty = SR->getSymbol()->getType()->getPointeeType(); | |||
1490 | RootIsSymbolic = true; | |||
1491 | } | |||
1492 | ||||
1493 | const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl(); | |||
1494 | if (!Child) { | |||
1495 | // We cannot compute the offset of the base class. | |||
1496 | SymbolicOffsetBase = R; | |||
1497 | } else { | |||
1498 | if (RootIsSymbolic) { | |||
1499 | // Base layers on symbolic regions may not be type-correct. | |||
1500 | // Double-check the inheritance here, and revert to a symbolic offset | |||
1501 | // if it's invalid (e.g. due to a reinterpret_cast). | |||
1502 | if (BOR->isVirtual()) { | |||
1503 | if (!Child->isVirtuallyDerivedFrom(BOR->getDecl())) | |||
1504 | SymbolicOffsetBase = R; | |||
1505 | } else { | |||
1506 | if (!isImmediateBase(Child, BOR->getDecl())) | |||
1507 | SymbolicOffsetBase = R; | |||
1508 | } | |||
1509 | } | |||
1510 | } | |||
1511 | ||||
1512 | // Don't bother calculating precise offsets if we already have a | |||
1513 | // symbolic offset somewhere in the chain. | |||
1514 | if (SymbolicOffsetBase) | |||
1515 | continue; | |||
1516 | ||||
1517 | CharUnits BaseOffset; | |||
1518 | const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child); | |||
1519 | if (BOR->isVirtual()) | |||
1520 | BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl()); | |||
1521 | else | |||
1522 | BaseOffset = Layout.getBaseClassOffset(BOR->getDecl()); | |||
1523 | ||||
1524 | // The base offset is in chars, not in bits. | |||
1525 | Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth(); | |||
1526 | break; | |||
1527 | } | |||
1528 | ||||
1529 | case MemRegion::CXXDerivedObjectRegionKind: { | |||
1530 | // TODO: Store the base type in the CXXDerivedObjectRegion and use it. | |||
1531 | goto Finish; | |||
1532 | } | |||
1533 | ||||
1534 | case MemRegion::ElementRegionKind: { | |||
1535 | const auto *ER = cast<ElementRegion>(R); | |||
1536 | R = ER->getSuperRegion(); | |||
1537 | ||||
1538 | QualType EleTy = ER->getValueType(); | |||
1539 | if (EleTy->isIncompleteType()) { | |||
1540 | // We cannot compute the offset of the base class. | |||
1541 | SymbolicOffsetBase = R; | |||
1542 | continue; | |||
1543 | } | |||
1544 | ||||
1545 | SVal Index = ER->getIndex(); | |||
1546 | if (Optional<nonloc::ConcreteInt> CI = | |||
1547 | Index.getAs<nonloc::ConcreteInt>()) { | |||
1548 | // Don't bother calculating precise offsets if we already have a | |||
1549 | // symbolic offset somewhere in the chain. | |||
1550 | if (SymbolicOffsetBase) | |||
1551 | continue; | |||
1552 | ||||
1553 | int64_t i = CI->getValue().getSExtValue(); | |||
1554 | // This type size is in bits. | |||
1555 | Offset += i * R->getContext().getTypeSize(EleTy); | |||
1556 | } else { | |||
1557 | // We cannot compute offset for non-concrete index. | |||
1558 | SymbolicOffsetBase = R; | |||
1559 | } | |||
1560 | break; | |||
1561 | } | |||
1562 | case MemRegion::FieldRegionKind: { | |||
1563 | const auto *FR = cast<FieldRegion>(R); | |||
1564 | R = FR->getSuperRegion(); | |||
1565 | assert(R)(static_cast <bool> (R) ? void (0) : __assert_fail ("R" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1565, __extension__ __PRETTY_FUNCTION__)); | |||
1566 | ||||
1567 | const RecordDecl *RD = FR->getDecl()->getParent(); | |||
1568 | if (RD->isUnion() || !RD->isCompleteDefinition()) { | |||
1569 | // We cannot compute offset for incomplete type. | |||
1570 | // For unions, we could treat everything as offset 0, but we'd rather | |||
1571 | // treat each field as a symbolic offset so they aren't stored on top | |||
1572 | // of each other, since we depend on things in typed regions actually | |||
1573 | // matching their types. | |||
1574 | SymbolicOffsetBase = R; | |||
1575 | } | |||
1576 | ||||
1577 | // Don't bother calculating precise offsets if we already have a | |||
1578 | // symbolic offset somewhere in the chain. | |||
1579 | if (SymbolicOffsetBase) | |||
1580 | continue; | |||
1581 | ||||
1582 | // Get the field number. | |||
1583 | unsigned idx = 0; | |||
1584 | for (RecordDecl::field_iterator FI = RD->field_begin(), | |||
1585 | FE = RD->field_end(); FI != FE; ++FI, ++idx) { | |||
1586 | if (FR->getDecl() == *FI) | |||
1587 | break; | |||
1588 | } | |||
1589 | const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD); | |||
1590 | // This is offset in bits. | |||
1591 | Offset += Layout.getFieldOffset(idx); | |||
1592 | break; | |||
1593 | } | |||
1594 | } | |||
1595 | } | |||
1596 | ||||
1597 | Finish: | |||
1598 | if (SymbolicOffsetBase) | |||
1599 | return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic); | |||
1600 | return RegionOffset(R, Offset); | |||
1601 | } | |||
1602 | ||||
1603 | RegionOffset MemRegion::getAsOffset() const { | |||
1604 | if (!cachedOffset) | |||
1605 | cachedOffset = calculateOffset(this); | |||
1606 | return *cachedOffset; | |||
1607 | } | |||
1608 | ||||
1609 | //===----------------------------------------------------------------------===// | |||
1610 | // BlockDataRegion | |||
1611 | //===----------------------------------------------------------------------===// | |||
1612 | ||||
1613 | std::pair<const VarRegion *, const VarRegion *> | |||
1614 | BlockDataRegion::getCaptureRegions(const VarDecl *VD) { | |||
1615 | MemRegionManager &MemMgr = getMemRegionManager(); | |||
1616 | const VarRegion *VR = nullptr; | |||
1617 | const VarRegion *OriginalVR = nullptr; | |||
1618 | ||||
1619 | if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) { | |||
1620 | VR = MemMgr.getNonParamVarRegion(VD, this); | |||
1621 | OriginalVR = MemMgr.getVarRegion(VD, LC); | |||
1622 | } | |||
1623 | else { | |||
1624 | if (LC) { | |||
1625 | VR = MemMgr.getVarRegion(VD, LC); | |||
1626 | OriginalVR = VR; | |||
1627 | } | |||
1628 | else { | |||
1629 | VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion()); | |||
1630 | OriginalVR = MemMgr.getVarRegion(VD, LC); | |||
1631 | } | |||
1632 | } | |||
1633 | return std::make_pair(VR, OriginalVR); | |||
1634 | } | |||
1635 | ||||
1636 | void BlockDataRegion::LazyInitializeReferencedVars() { | |||
1637 | if (ReferencedVars) | |||
1638 | return; | |||
1639 | ||||
1640 | AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext(); | |||
1641 | const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl()); | |||
1642 | auto NumBlockVars = | |||
1643 | std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end()); | |||
1644 | ||||
1645 | if (NumBlockVars == 0) { | |||
1646 | ReferencedVars = (void*) 0x1; | |||
1647 | return; | |||
1648 | } | |||
1649 | ||||
1650 | MemRegionManager &MemMgr = getMemRegionManager(); | |||
1651 | llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); | |||
1652 | BumpVectorContext BC(A); | |||
1653 | ||||
1654 | using VarVec = BumpVector<const MemRegion *>; | |||
1655 | ||||
1656 | auto *BV = A.Allocate<VarVec>(); | |||
1657 | new (BV) VarVec(BC, NumBlockVars); | |||
1658 | auto *BVOriginal = A.Allocate<VarVec>(); | |||
1659 | new (BVOriginal) VarVec(BC, NumBlockVars); | |||
1660 | ||||
1661 | for (const auto *VD : ReferencedBlockVars) { | |||
1662 | const VarRegion *VR = nullptr; | |||
1663 | const VarRegion *OriginalVR = nullptr; | |||
1664 | std::tie(VR, OriginalVR) = getCaptureRegions(VD); | |||
1665 | assert(VR)(static_cast <bool> (VR) ? void (0) : __assert_fail ("VR" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1665, __extension__ __PRETTY_FUNCTION__)); | |||
1666 | assert(OriginalVR)(static_cast <bool> (OriginalVR) ? void (0) : __assert_fail ("OriginalVR", "clang/lib/StaticAnalyzer/Core/MemRegion.cpp" , 1666, __extension__ __PRETTY_FUNCTION__)); | |||
1667 | BV->push_back(VR, BC); | |||
1668 | BVOriginal->push_back(OriginalVR, BC); | |||
1669 | } | |||
1670 | ||||
1671 | ReferencedVars = BV; | |||
1672 | OriginalVars = BVOriginal; | |||
1673 | } | |||
1674 | ||||
1675 | BlockDataRegion::referenced_vars_iterator | |||
1676 | BlockDataRegion::referenced_vars_begin() const { | |||
1677 | const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); | |||
1678 | ||||
1679 | auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); | |||
1680 | ||||
1681 | if (Vec == (void*) 0x1) | |||
1682 | return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); | |||
1683 | ||||
1684 | auto *VecOriginal = | |||
1685 | static_cast<BumpVector<const MemRegion *> *>(OriginalVars); | |||
1686 | ||||
1687 | return BlockDataRegion::referenced_vars_iterator(Vec->begin(), | |||
1688 | VecOriginal->begin()); | |||
1689 | } | |||
1690 | ||||
1691 | BlockDataRegion::referenced_vars_iterator | |||
1692 | BlockDataRegion::referenced_vars_end() const { | |||
1693 | const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); | |||
1694 | ||||
1695 | auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); | |||
1696 | ||||
1697 | if (Vec == (void*) 0x1) | |||
1698 | return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); | |||
1699 | ||||
1700 | auto *VecOriginal = | |||
1701 | static_cast<BumpVector<const MemRegion *> *>(OriginalVars); | |||
1702 | ||||
1703 | return BlockDataRegion::referenced_vars_iterator(Vec->end(), | |||
1704 | VecOriginal->end()); | |||
1705 | } | |||
1706 | ||||
1707 | const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const { | |||
1708 | for (referenced_vars_iterator I = referenced_vars_begin(), | |||
| ||||
1709 | E = referenced_vars_end(); | |||
1710 | I != E; ++I) { | |||
1711 | if (I.getCapturedRegion() == R) | |||
1712 | return I.getOriginalRegion(); | |||
1713 | } | |||
1714 | return nullptr; | |||
1715 | } | |||
1716 | ||||
1717 | //===----------------------------------------------------------------------===// | |||
1718 | // RegionAndSymbolInvalidationTraits | |||
1719 | //===----------------------------------------------------------------------===// | |||
1720 | ||||
1721 | void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym, | |||
1722 | InvalidationKinds IK) { | |||
1723 | SymTraitsMap[Sym] |= IK; | |||
1724 | } | |||
1725 | ||||
1726 | void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR, | |||
1727 | InvalidationKinds IK) { | |||
1728 | assert(MR)(static_cast <bool> (MR) ? void (0) : __assert_fail ("MR" , "clang/lib/StaticAnalyzer/Core/MemRegion.cpp", 1728, __extension__ __PRETTY_FUNCTION__)); | |||
1729 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) | |||
1730 | setTrait(SR->getSymbol(), IK); | |||
1731 | else | |||
1732 | MRTraitsMap[MR] |= IK; | |||
1733 | } | |||
1734 | ||||
1735 | bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym, | |||
1736 | InvalidationKinds IK) const { | |||
1737 | const_symbol_iterator I = SymTraitsMap.find(Sym); | |||
1738 | if (I != SymTraitsMap.end()) | |||
1739 | return I->second & IK; | |||
1740 | ||||
1741 | return false; | |||
1742 | } | |||
1743 | ||||
1744 | bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR, | |||
1745 | InvalidationKinds IK) const { | |||
1746 | if (!MR) | |||
1747 | return false; | |||
1748 | ||||
1749 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) | |||
1750 | return hasTrait(SR->getSymbol(), IK); | |||
1751 | ||||
1752 | const_region_iterator I = MRTraitsMap.find(MR); | |||
1753 | if (I != MRTraitsMap.end()) | |||
1754 | return I->second & IK; | |||
1755 | ||||
1756 | return false; | |||
1757 | } |