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