1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
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 | |
62 | class RegionOffset { |
63 | |
64 | const MemRegion *R = nullptr; |
65 | |
66 | |
67 | int64_t Offset; |
68 | |
69 | public: |
70 | |
71 | |
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()); |
83 | return Offset; |
84 | } |
85 | |
86 | bool isValid() const { return R; } |
87 | }; |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
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 | |
122 | |
123 | const MemRegion *getMostDerivedObjectRegion() const; |
124 | |
125 | |
126 | |
127 | virtual bool isSubRegionOf(const MemRegion *R) const; |
128 | |
129 | const MemRegion *StripCasts(bool StripBaseAndDerivedCasts = true) const; |
130 | |
131 | |
132 | |
133 | const SymbolicRegion *getSymbolicBase() const; |
134 | |
135 | bool () const; |
136 | |
137 | bool hasStackStorage() const; |
138 | |
139 | bool () const; |
140 | |
141 | bool () const; |
142 | |
143 | |
144 | RegionOffset getAsOffset() const; |
145 | |
146 | |
147 | std::string getString() const; |
148 | |
149 | virtual void dumpToStream(raw_ostream &os) const; |
150 | |
151 | void dump() const; |
152 | |
153 | |
154 | virtual bool canPrintPretty() const; |
155 | |
156 | |
157 | virtual void printPretty(raw_ostream &os) const; |
158 | |
159 | |
160 | |
161 | virtual bool canPrintPrettyAsExpr() const; |
162 | |
163 | |
164 | |
165 | |
166 | |
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 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | std::string getDescriptiveName(bool UseQuotes = true) const; |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | SourceRange sourceRange() const; |
194 | }; |
195 | |
196 | |
197 | |
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)); |
204 | assert(mgr); |
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 | |
221 | |
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)); |
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 | |
252 | |
253 | |
254 | |
255 | |
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); |
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 | |
279 | |
280 | |
281 | |
282 | |
283 | |
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)); |
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 | |
302 | |
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 | |
318 | |
319 | |
320 | |
321 | |
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 | |
337 | |
338 | |
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)); |
390 | assert(sfc); |
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 | |
434 | |
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)); |
443 | assert(sReg); |
444 | } |
445 | |
446 | public: |
447 | const MemRegion* getSuperRegion() const { |
448 | return superRegion; |
449 | } |
450 | |
451 | |
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 | |
467 | |
468 | |
469 | |
470 | |
471 | class AllocaRegion : public SubRegion { |
472 | friend class MemRegionManager; |
473 | |
474 | |
475 | |
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); |
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 | |
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)); |
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 | |
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)); |
535 | } |
536 | |
537 | public: |
538 | virtual QualType getValueType() const = 0; |
539 | |
540 | QualType getLocationType() const override { |
541 | |
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)); |
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 | |
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 | (fd) || isa(fd)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 587, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); |
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 | (FD)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 600, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<ObjCMethodDecl>(FD)); |
601 | (0) . __assert_fail ("false && \"Getting the type of ObjCMethod is not supported yet\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 601, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(false && "Getting the type of ObjCMethod is not supported yet"); |
602 | |
603 | |
604 | |
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 | |
622 | |
623 | |
624 | |
625 | |
626 | |
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); |
638 | assert(ac); |
639 | getTypePtr()->isBlockPointerType()", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 639, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(lTy->getTypePtr()->isBlockPointerType()); |
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 | |
667 | |
668 | |
669 | |
670 | |
671 | |
672 | class BlockDataRegion : public TypedRegion { |
673 | friend class MemRegionManager; |
674 | |
675 | const BlockCodeRegion *BC; |
676 | const LocationContext *LC; |
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); |
686 | assert(lc); |
687 | (sreg) || isa(sreg) || isa(sreg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 689, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<GlobalImmutableSpaceRegion>(sreg) || |
688 | (sreg) || isa(sreg) || isa(sreg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 689, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> isa<StackLocalsSpaceRegion>(sreg) || |
689 | (sreg) || isa(sreg) || isa(sreg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 689, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> isa<UnknownSpaceRegion>(sreg)); |
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)); |
722 | return I.R == R; |
723 | } |
724 | |
725 | bool operator!=(const referenced_vars_iterator &I) const { |
726 | assert((R == nullptr) == (I.R == nullptr)); |
727 | return I.R != R; |
728 | } |
729 | |
730 | referenced_vars_iterator &operator++() { |
731 | ++R; |
732 | ++OriginalR; |
733 | return *this; |
734 | } |
735 | }; |
736 | |
737 | |
738 | |
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 | |
759 | |
760 | |
761 | |
762 | |
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 | |
771 | |
772 | (s)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 772, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(s && isa<SymbolData>(s)); |
773 | getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 775, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(s->getType()->isAnyPointerType() || |
774 | getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 775, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> s->getType()->isReferenceType() || |
775 | getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 775, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> s->getType()->isBlockPointerType()); |
776 | (sreg) || isa(sreg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 776, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg)); |
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 | |
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); |
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 | |
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); |
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 | |
869 | |
870 | |
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); |
880 | (sReg) || isa(sReg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 881, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<GlobalInternalSpaceRegion>(sReg) || |
881 | (sReg) || isa(sReg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 881, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> isa<StackLocalsSpaceRegion>(sReg)); |
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)); |
911 | isCanonicalDecl()", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 911, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(d && d->isCanonicalDecl()); |
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 | |
931 | VarRegion(const VarDecl *vd, const MemRegion *sReg) |
932 | : DeclRegion(vd, sReg, VarRegionKind) { |
933 | |
934 | |
935 | |
936 | |
937 | (sReg) || isa(sReg) || isa(sReg) || isa(sReg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 938, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) || |
938 | (sReg) || isa(sReg) || isa(sReg) || isa(sReg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 938, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg)); |
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 | |
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 | |
970 | |
971 | |
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 | (0) . __assert_fail ("ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && \"Invalid region type!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 980, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && |
980 | (0) . __assert_fail ("ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && \"Invalid region type!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 980, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> "Invalid region type!"); |
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 | |
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 | |
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 | |
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 | |
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 | (0) . __assert_fail ("(!Idx.getAs() || Idx.castAs().getValue().isSigned()) && \"The index must be signed\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1093, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert((!Idx.getAs<nonloc::ConcreteInt>() || |
1092 | (0) . __assert_fail ("(!Idx.getAs() || Idx.castAs().getValue().isSigned()) && \"The index must be signed\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1093, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && |
1093 | (0) . __assert_fail ("(!Idx.getAs() || Idx.castAs().getValue().isSigned()) && \"The index must be signed\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1093, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> "The index must be signed"); |
1094 | (0) . __assert_fail ("!elementType.isNull() && !elementType->isVoidType() && \"Invalid region type!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1095, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(!elementType.isNull() && !elementType->isVoidType() && |
1095 | (0) . __assert_fail ("!elementType.isNull() && !elementType->isVoidType() && \"Invalid region type!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1095, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> "Invalid region type!"); |
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 | |
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 | |
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); |
1129 | (sReg) || isa(sReg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1130, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(isa<StackLocalsSpaceRegion>(sReg) || |
1130 | (sReg) || isa(sReg)", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1130, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> isa<GlobalInternalSpaceRegion>(sReg)); |
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 | |
1151 | |
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); |
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 | |
1186 | |
1187 | |
1188 | |
1189 | |
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); |
1198 | |
1199 | |
1200 | |
1201 | (0) . __assert_fail ("SReg->getSymbolicBase() && \"Should have unwrapped a base region instead!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1202, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true">assert(SReg->getSymbolicBase() && |
1202 | (0) . __assert_fail ("SReg->getSymbolicBase() && \"Should have unwrapped a base region instead!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h", 1202, __PRETTY_FUNCTION__))" file_link="../../../../../../include/assert.h.html#88" macro="true"> "Should have unwrapped a base region instead!"); |
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 | |
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 | |
1267 | |
1268 | const StackLocalsSpaceRegion * |
1269 | getStackLocalsRegion(const StackFrameContext *STC); |
1270 | |
1271 | |
1272 | |
1273 | const StackArgumentsSpaceRegion * |
1274 | getStackArgumentsRegion(const StackFrameContext *STC); |
1275 | |
1276 | |
1277 | |
1278 | const GlobalsSpaceRegion *getGlobalsRegion( |
1279 | MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind, |
1280 | const CodeTextRegion *R = nullptr); |
1281 | |
1282 | |
1283 | |
1284 | const HeapSpaceRegion *getHeapRegion(); |
1285 | |
1286 | |
1287 | |
1288 | const UnknownSpaceRegion *getUnknownRegion(); |
1289 | |
1290 | const CodeSpaceRegion *getCodeRegion(); |
1291 | |
1292 | |
1293 | const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt, |
1294 | const LocationContext *LC); |
1295 | |
1296 | |
1297 | |
1298 | const CompoundLiteralRegion* |
1299 | getCompoundLiteralRegion(const CompoundLiteralExpr *CL, |
1300 | const LocationContext *LC); |
1301 | |
1302 | |
1303 | |
1304 | const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, |
1305 | const LocationContext *LC); |
1306 | |
1307 | |
1308 | const SymbolicRegion* getSymbolicRegion(SymbolRef Sym); |
1309 | |
1310 | |
1311 | const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym); |
1312 | |
1313 | const StringRegion *getStringRegion(const StringLiteral *Str); |
1314 | |
1315 | const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str); |
1316 | |
1317 | |
1318 | |
1319 | const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); |
1320 | |
1321 | |
1322 | |
1323 | const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR); |
1324 | |
1325 | |
1326 | |
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 | |
1338 | |
1339 | |
1340 | |
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 | |
1350 | |
1351 | |
1352 | |
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 | |
1360 | |
1361 | |
1362 | |
1363 | const CXXBaseObjectRegion * |
1364 | getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, |
1365 | bool IsVirtual); |
1366 | |
1367 | |
1368 | |
1369 | const CXXBaseObjectRegion * |
1370 | getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg, |
1371 | const SubRegion *superRegion) { |
1372 | return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion, |
1373 | baseReg->isVirtual()); |
1374 | } |
1375 | |
1376 | |
1377 | |
1378 | |
1379 | |
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 | |
1390 | |
1391 | |
1392 | |
1393 | const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc, |
1394 | const LocationContext *lc, |
1395 | unsigned blockCount); |
1396 | |
1397 | |
1398 | |
1399 | |
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 | |
1428 | |
1429 | |
1430 | inline ASTContext &MemRegion::getContext() const { |
1431 | return getMemRegionManager()->getContext(); |
1432 | } |
1433 | |
1434 | |
1435 | |
1436 | |
1437 | |
1438 | |
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 | |
1452 | enum InvalidationKinds { |
1453 | |
1454 | TK_PreserveContents = 0x1, |
1455 | |
1456 | |
1457 | TK_SuppressEscape = 0x2, |
1458 | |
1459 | |
1460 | TK_DoNotInvalidateSuperRegion = 0x4, |
1461 | |
1462 | |
1463 | |
1464 | TK_EntireMemSpace = 0x8 |
1465 | |
1466 | |
1467 | |
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 | |
1478 | |
1479 | inline raw_ostream &operator<<(raw_ostream &os, const MemRegion *R) { |
1480 | R->dumpToStream(os); |
1481 | return os; |
1482 | } |
1483 | |
1484 | } |
1485 | |
1486 | } |
1487 | |
1488 | #endif |
1489 | |