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